diff options
Diffstat (limited to 'chromium/content/renderer')
400 files changed, 13472 insertions, 14270 deletions
diff --git a/chromium/content/renderer/BUILD.gn b/chromium/content/renderer/BUILD.gn index 4f9c35e697b..d97b7082177 100644 --- a/chromium/content/renderer/BUILD.gn +++ b/chromium/content/renderer/BUILD.gn @@ -45,8 +45,6 @@ target(link_target_type, "renderer") { "android/renderer_date_time_picker.h", "android/synchronous_compositor_proxy.cc", "android/synchronous_compositor_proxy.h", - "android/synchronous_compositor_proxy_mojo.cc", - "android/synchronous_compositor_proxy_mojo.h", "android/synchronous_compositor_registry.h", "android/synchronous_layer_tree_frame_sink.cc", "android/synchronous_layer_tree_frame_sink.h", @@ -69,10 +67,6 @@ target(link_target_type, "renderer") { "child_frame_compositing_helper.cc", "child_frame_compositing_helper.h", "child_frame_compositor.h", - "child_message_filter.cc", - "child_message_filter.h", - "clipboard_utils.cc", - "clipboard_utils.h", "content_security_policy_util.cc", "content_security_policy_util.h", "context_menu_params_builder.cc", @@ -81,11 +75,6 @@ target(link_target_type, "renderer") { "crash_helpers.h", "cursor_utils.cc", "cursor_utils.h", - "device_sensors/device_motion_event_pump.cc", - "device_sensors/device_motion_event_pump.h", - "device_sensors/device_orientation_event_pump.cc", - "device_sensors/device_orientation_event_pump.h", - "device_sensors/device_sensor_event_pump.h", "devtools/render_widget_screen_metrics_emulator.cc", "devtools/render_widget_screen_metrics_emulator.h", "devtools/render_widget_screen_metrics_emulator_delegate.h", @@ -136,8 +125,6 @@ target(link_target_type, "renderer") { "frame_blame_context.h", "frame_owner_properties.cc", "frame_owner_properties.h", - "gamepad_shared_memory_reader.cc", - "gamepad_shared_memory_reader.h", "gpu/actions_parser.cc", "gpu/actions_parser.h", "gpu/compositor_dependencies.h", @@ -145,11 +132,11 @@ target(link_target_type, "renderer") { "gpu/frame_swap_message_queue.h", "gpu/gpu_benchmarking_extension.cc", "gpu/gpu_benchmarking_extension.h", + "gpu/layer_tree_view.cc", + "gpu/layer_tree_view.h", + "gpu/layer_tree_view_delegate.h", "gpu/queue_message_swap_promise.cc", "gpu/queue_message_swap_promise.h", - "gpu/render_widget_compositor.cc", - "gpu/render_widget_compositor.h", - "gpu/render_widget_compositor_delegate.h", "gpu/stream_texture_host_android.cc", "gpu/stream_texture_host_android.h", "history_entry.cc", @@ -246,8 +233,12 @@ target(link_target_type, "renderer") { "loader/web_url_loader_impl.h", "loader/web_url_request_util.cc", "loader/web_url_request_util.h", + "loader/web_worker_fetch_context_impl.cc", + "loader/web_worker_fetch_context_impl.h", "loader/weburlresponse_extradata_impl.cc", "loader/weburlresponse_extradata_impl.h", + "low_memory_mode_controller.cc", + "low_memory_mode_controller.h", "manifest/manifest_change_notifier.cc", "manifest/manifest_change_notifier.h", "manifest/manifest_manager.cc", @@ -262,25 +253,27 @@ target(link_target_type, "renderer") { "media/android/media_player_renderer_client_factory.h", "media/android/renderer_media_player_manager.cc", "media/android/renderer_media_player_manager.h", - "media/android/renderer_surface_view_manager.cc", - "media/android/renderer_surface_view_manager.h", "media/android/stream_texture_factory.cc", "media/android/stream_texture_factory.h", "media/android/stream_texture_wrapper_impl.cc", "media/android/stream_texture_wrapper_impl.h", + "media/audio/audio_device_factory.cc", + "media/audio/audio_device_factory.h", + "media/audio/audio_input_ipc_factory.cc", + "media/audio/audio_input_ipc_factory.h", + "media/audio/audio_output_ipc_factory.cc", + "media/audio/audio_output_ipc_factory.h", + "media/audio/audio_renderer_mixer_manager.cc", + "media/audio/audio_renderer_mixer_manager.h", + "media/audio/audio_renderer_sink_cache.h", + "media/audio/audio_renderer_sink_cache_impl.cc", + "media/audio/audio_renderer_sink_cache_impl.h", + "media/audio/mojo_audio_input_ipc.cc", + "media/audio/mojo_audio_input_ipc.h", + "media/audio/mojo_audio_output_ipc.cc", + "media/audio/mojo_audio_output_ipc.h", "media/audio_decoder.cc", "media/audio_decoder.h", - "media/audio_device_factory.cc", - "media/audio_device_factory.h", - "media/audio_input_ipc_factory.cc", - "media/audio_input_ipc_factory.h", - "media/audio_output_ipc_factory.cc", - "media/audio_output_ipc_factory.h", - "media/audio_renderer_mixer_manager.cc", - "media/audio_renderer_mixer_manager.h", - "media/audio_renderer_sink_cache.h", - "media/audio_renderer_sink_cache_impl.cc", - "media/audio_renderer_sink_cache_impl.h", "media/gpu/gpu_video_accelerator_factories_impl.cc", "media/gpu/gpu_video_accelerator_factories_impl.h", "media/media_factory.cc", @@ -291,10 +284,6 @@ target(link_target_type, "renderer") { "media/midi/midi_message_filter.h", "media/midi/renderer_webmidiaccessor_impl.cc", "media/midi/renderer_webmidiaccessor_impl.h", - "media/mojo_audio_input_ipc.cc", - "media/mojo_audio_input_ipc.h", - "media/mojo_audio_output_ipc.cc", - "media/mojo_audio_output_ipc.h", "media/render_media_client.cc", "media/render_media_client.h", "media/render_media_log.cc", @@ -379,6 +368,8 @@ target(link_target_type, "renderer") { "media/web_media_element_source_utils.h", "media/webrtc/audio_codec_factory.cc", "media/webrtc/audio_codec_factory.h", + "media/webrtc/fake_rtc_rtp_transceiver.cc", + "media/webrtc/fake_rtc_rtp_transceiver.h", "media/webrtc/media_stream_remote_video_source.cc", "media/webrtc/media_stream_remote_video_source.h", "media/webrtc/media_stream_track_metrics.cc", @@ -410,6 +401,8 @@ target(link_target_type, "renderer") { "media/webrtc/rtc_rtp_receiver.h", "media/webrtc/rtc_rtp_sender.cc", "media/webrtc/rtc_rtp_sender.h", + "media/webrtc/rtc_rtp_transceiver.cc", + "media/webrtc/rtc_rtp_transceiver.h", "media/webrtc/rtc_stats.cc", "media/webrtc/rtc_stats.h", "media/webrtc/rtc_video_decoder.cc", @@ -424,6 +417,8 @@ target(link_target_type, "renderer") { "media/webrtc/stun_field_trial.h", "media/webrtc/track_observer.cc", "media/webrtc/track_observer.h", + "media/webrtc/transceiver_state_surfacer.cc", + "media/webrtc/transceiver_state_surfacer.h", "media/webrtc/two_keys_adapter_map.h", "media/webrtc/webrtc_audio_device_impl.cc", "media/webrtc/webrtc_audio_device_impl.h", @@ -433,18 +428,15 @@ target(link_target_type, "renderer") { "media/webrtc/webrtc_audio_renderer.h", "media/webrtc/webrtc_audio_sink.cc", "media/webrtc/webrtc_audio_sink.h", - "media/webrtc/webrtc_media_stream_adapter.cc", - "media/webrtc/webrtc_media_stream_adapter.h", - "media/webrtc/webrtc_media_stream_adapter_map.cc", - "media/webrtc/webrtc_media_stream_adapter_map.h", "media/webrtc/webrtc_media_stream_track_adapter.cc", "media/webrtc/webrtc_media_stream_track_adapter.h", "media/webrtc/webrtc_media_stream_track_adapter_map.cc", "media/webrtc/webrtc_media_stream_track_adapter_map.h", - "media/webrtc/webrtc_set_remote_description_observer.cc", - "media/webrtc/webrtc_set_remote_description_observer.h", + "media/webrtc/webrtc_set_description_observer.cc", + "media/webrtc/webrtc_set_description_observer.h", "media/webrtc/webrtc_uma_histograms.cc", "media/webrtc/webrtc_uma_histograms.h", + "media/webrtc/webrtc_util.h", "media/webrtc/webrtc_video_capturer_adapter.cc", "media/webrtc/webrtc_video_capturer_adapter.h", "media/webrtc/webrtc_video_frame_adapter.cc", @@ -484,6 +476,8 @@ target(link_target_type, "renderer") { "mojo/blink_interface_registry_impl.h", "mouse_lock_dispatcher.cc", "mouse_lock_dispatcher.h", + "navigation_client.cc", + "navigation_client.h", "navigation_state_impl.cc", "navigation_state_impl.h", "net_info_helper.cc", @@ -573,8 +567,6 @@ target(link_target_type, "renderer") { "service_worker/service_worker_context_client.h", "service_worker/service_worker_fetch_context_impl.cc", "service_worker/service_worker_fetch_context_impl.h", - "service_worker/service_worker_message_filter.cc", - "service_worker/service_worker_message_filter.h", "service_worker/service_worker_network_provider.cc", "service_worker/service_worker_network_provider.h", "service_worker/service_worker_provider_context.cc", @@ -597,8 +589,6 @@ target(link_target_type, "renderer") { "service_worker/web_service_worker_provider_impl.h", "service_worker/web_service_worker_registration_impl.cc", "service_worker/web_service_worker_registration_impl.h", - "service_worker/worker_fetch_context_impl.cc", - "service_worker/worker_fetch_context_impl.h", "shared_worker/embedded_shared_worker_stub.cc", "shared_worker/embedded_shared_worker_stub.h", "shared_worker/shared_worker_client_impl.cc", @@ -609,8 +599,6 @@ target(link_target_type, "renderer") { "shared_worker/shared_worker_repository.h", "skia_benchmarking_extension.cc", "skia_benchmarking_extension.h", - "speech_recognition_dispatcher.cc", - "speech_recognition_dispatcher.h", "stats_collection_controller.cc", "stats_collection_controller.h", "stats_collection_observer.cc", @@ -627,22 +615,12 @@ target(link_target_type, "renderer") { "v8_value_converter_impl.h", "web_database_observer_impl.cc", "web_database_observer_impl.h", - "web_frame_utils.cc", - "web_frame_utils.h", "web_ui_extension.cc", "web_ui_extension.h", "web_ui_extension_data.cc", "web_ui_extension_data.h", "webgraphicscontext3d_provider_impl.cc", "webgraphicscontext3d_provider_impl.h", - "webpublicsuffixlist_impl.cc", - "webpublicsuffixlist_impl.h", - "webscrollbarbehavior_impl_aura.cc", - "webscrollbarbehavior_impl_aura.h", - "webscrollbarbehavior_impl_mac.h", - "webscrollbarbehavior_impl_mac.mm", - "worker_thread_message_filter.cc", - "worker_thread_message_filter.h", "worker_thread_registry.cc", "worker_thread_registry.h", ] @@ -671,6 +649,7 @@ target(link_target_type, "renderer") { "//base:i18n", "//cc", "//cc/animation", + "//cc/mojo_embedder", "//cc/paint", "//components/discardable_memory/client", "//components/metrics", @@ -740,7 +719,6 @@ target(link_target_type, "renderer") { "//third_party/opus", "//third_party/webrtc/api:libjingle_logging_api", "//third_party/webrtc/api:libjingle_peerconnection_api", - "//third_party/webrtc/api:optional", "//third_party/webrtc/api:rtc_stats_api", "//third_party/webrtc/api/audio:aec3_factory", "//third_party/webrtc/api/audio_codecs:audio_codecs_api", @@ -809,13 +787,6 @@ target(link_target_type, "renderer") { ] } - if (is_mac) { - sources -= [ - "webscrollbarbehavior_impl_aura.cc", - "webscrollbarbehavior_impl_aura.h", - ] - } - if (is_android) { # Add back the Linux file which Android shares. set_sources_assignment_filter([]) @@ -839,7 +810,10 @@ target(link_target_type, "renderer") { } if (is_linux) { - deps += [ "//services/service_manager/zygote" ] + deps += [ + "//components/services/font/public/cpp", + "//services/service_manager/zygote", + ] } if (is_fuchsia) { diff --git a/chromium/content/renderer/OWNERS b/chromium/content/renderer/OWNERS index 9b1fac28656..d646d43c6cc 100644 --- a/chromium/content/renderer/OWNERS +++ b/chromium/content/renderer/OWNERS @@ -14,3 +14,4 @@ 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/accessibility/blink_ax_enum_conversion.cc b/chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc index 1e9b5afec74..3b504e29872 100644 --- a/chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc +++ b/chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc @@ -113,6 +113,10 @@ ax::mojom::Role AXRoleFromBlink(blink::WebAXRole role) { return ax::mojom::Role::kComboBoxMenuButton; case blink::kWebAXRoleComplementary: return ax::mojom::Role::kComplementary; + case blink::kWebAXRoleContentDeletion: + return ax::mojom::Role::kContentDeletion; + case blink::kWebAXRoleContentInsertion: + return ax::mojom::Role::kContentInsertion; case blink::kWebAXRoleContentInfo: return ax::mojom::Role::kContentInfo; case blink::kWebAXRoleDate: @@ -420,6 +424,8 @@ ax::mojom::Event AXEventFromBlink(blink::WebAXEvent event) { return ax::mojom::Event::kClicked; case blink::kWebAXEventDocumentSelectionChanged: return ax::mojom::Event::kDocumentSelectionChanged; + case blink::kWebAXEventDocumentTitleChanged: + return ax::mojom::Event::kDocumentTitleChanged; case blink::kWebAXEventExpandedChanged: return ax::mojom::Event::kExpandedChanged; case blink::kWebAXEventFocus: diff --git a/chromium/content/renderer/accessibility/blink_ax_tree_source.cc b/chromium/content/renderer/accessibility/blink_ax_tree_source.cc index 2e67e084f9c..f43d7214fd2 100644 --- a/chromium/content/renderer/accessibility/blink_ax_tree_source.cc +++ b/chromium/content/renderer/accessibility/blink_ax_tree_source.cc @@ -39,6 +39,7 @@ #include "third_party/blink/public/web/web_view.h" #include "ui/accessibility/ax_enum_util.h" #include "ui/accessibility/ax_role_properties.h" +#include "ui/gfx/geometry/vector2d_f.h" using base::ASCIIToUTF16; using base::UTF16ToUTF8; @@ -395,6 +396,13 @@ void BlinkAXTreeSource::GetChildren( if (!is_iframe && !IsParentUnignoredOf(parent, child)) continue; + // Skip table headers and columns, they're only needed on Mac + // and soon we'll get rid of this code entirely. + if (child.Role() == blink::kWebAXRoleColumn || + child.Role() == blink::kWebAXRoleLayoutTableColumn || + child.Role() == blink::kWebAXRoleTableHeaderContainer) + continue; + out_children->push_back(child); } } @@ -442,8 +450,24 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, src.GetRelativeBounds(offset_container, bounds_in_container, container_transform, &clips_children); dst->location = bounds_in_container; +#if !defined(OS_ANDROID) && !defined(OS_MACOSX) + if (src.Equals(root())) { + WebView* web_view = render_frame_->GetRenderView()->GetWebView(); + std::unique_ptr<gfx::Transform> container_transform_gfx = + std::make_unique<gfx::Transform>(container_transform); + container_transform_gfx->Scale(web_view->PageScaleFactor(), + web_view->PageScaleFactor()); + container_transform_gfx->Translate( + gfx::Vector2dF(-web_view->VisualViewportOffset().x, + -web_view->VisualViewportOffset().y)); + if (!container_transform_gfx->IsIdentity()) + dst->transform = std::move(container_transform_gfx); + } else if (!container_transform.isIdentity()) + dst->transform = base::WrapUnique(new gfx::Transform(container_transform)); +#else if (!container_transform.isIdentity()) dst->transform = base::WrapUnique(new gfx::Transform(container_transform)); +#endif // !defined(OS_ANDROID) && !defined(OS_MACOSX) if (!offset_container.IsDetached()) dst->offset_container_id = offset_container.AxID(); if (clips_children) @@ -457,7 +481,8 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, blink::WebString web_name = src.GetName(nameFrom, nameObjects); if ((!web_name.IsEmpty() && !web_name.IsNull()) || nameFrom == blink::kWebAXNameFromAttributeExplicitlyEmpty) { - dst->AddStringAttribute(ax::mojom::StringAttribute::kName, web_name.Utf8()); + TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kName, + web_name.Utf8()); dst->SetNameFrom(AXNameFromFromBlink(nameFrom)); AddIntListAttributeFromWebObjects( ax::mojom::IntListAttribute::kLabelledbyIds, nameObjects, dst); @@ -468,8 +493,8 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, blink::WebString web_description = src.Description(nameFrom, descriptionFrom, descriptionObjects); if (!web_description.IsEmpty()) { - dst->AddStringAttribute(ax::mojom::StringAttribute::kDescription, - web_description.Utf8()); + TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kDescription, + web_description.Utf8()); dst->AddIntAttribute( ax::mojom::IntAttribute::kDescriptionFrom, static_cast<int32_t>(AXDescriptionFromFromBlink(descriptionFrom))); @@ -478,11 +503,11 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, } if (src.ValueDescription().length()) { - dst->AddStringAttribute(ax::mojom::StringAttribute::kValue, - src.ValueDescription().Utf8()); + TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kValue, + src.ValueDescription().Utf8()); } else { - dst->AddStringAttribute(ax::mojom::StringAttribute::kValue, - src.StringValue().Utf8()); + TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kValue, + src.StringValue().Utf8()); } switch (src.Restriction()) { @@ -499,8 +524,8 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, } if (!src.Url().IsEmpty()) - dst->AddStringAttribute(ax::mojom::StringAttribute::kUrl, - src.Url().GetString().Utf8()); + TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kUrl, + src.Url().GetString().Utf8()); // The following set of attributes are only accessed when the accessibility // mode is set to screen reader mode, otherwise only the more basic @@ -508,8 +533,9 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, if (accessibility_mode_.has_mode(ui::AXMode::kScreenReader)) { blink::WebString web_placeholder = src.Placeholder(nameFrom); if (!web_placeholder.IsEmpty()) - dst->AddStringAttribute(ax::mojom::StringAttribute::kPlaceholder, - web_placeholder.Utf8()); + TruncateAndAddStringAttribute(dst, + ax::mojom::StringAttribute::kPlaceholder, + web_placeholder.Utf8()); if (dst->role == ax::mojom::Role::kColorWell) dst->AddIntAttribute(ax::mojom::IntAttribute::kColorValue, @@ -541,8 +567,9 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, WebAXObject parent = ParentObjectUnignored(src); if (src.FontFamily().length()) { if (parent.IsNull() || parent.FontFamily() != src.FontFamily()) - dst->AddStringAttribute(ax::mojom::StringAttribute::kFontFamily, - src.FontFamily().Utf8()); + TruncateAndAddStringAttribute(dst, + ax::mojom::StringAttribute::kFontFamily, + src.FontFamily().Utf8()); } // Font size is in pixels. @@ -566,8 +593,9 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, } if (src.InvalidState() == blink::kWebAXInvalidStateOther && src.AriaInvalidValue().length()) { - dst->AddStringAttribute(ax::mojom::StringAttribute::kAriaInvalidValue, - src.AriaInvalidValue().Utf8()); + TruncateAndAddStringAttribute( + dst, ax::mojom::StringAttribute::kAriaInvalidValue, + src.AriaInvalidValue().Utf8()); } if (src.CheckedState()) { @@ -618,13 +646,14 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, } if (src.AccessKey().length()) { - dst->AddStringAttribute(ax::mojom::StringAttribute::kAccessKey, - src.AccessKey().Utf8()); + TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kAccessKey, + src.AccessKey().Utf8()); } if (src.AriaAutoComplete().length()) { - dst->AddStringAttribute(ax::mojom::StringAttribute::kAutoComplete, - src.AriaAutoComplete().Utf8()); + TruncateAndAddStringAttribute(dst, + ax::mojom::StringAttribute::kAutoComplete, + src.AriaAutoComplete().Utf8()); } if (src.Action() != blink::WebAXDefaultActionVerb::kNone) { @@ -632,20 +661,21 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, } if (src.HasComputedStyle()) { - dst->AddStringAttribute(ax::mojom::StringAttribute::kDisplay, - src.ComputedStyleDisplay().Utf8()); + TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kDisplay, + src.ComputedStyleDisplay().Utf8()); } if (src.Language().length()) { if (parent.IsNull() || parent.Language() != src.Language()) - dst->AddStringAttribute(ax::mojom::StringAttribute::kLanguage, - src.Language().Utf8()); + TruncateAndAddStringAttribute( + dst, ax::mojom::StringAttribute::kLanguage, src.Language().Utf8()); } if (src.KeyboardShortcut().length() && !dst->HasStringAttribute(ax::mojom::StringAttribute::kKeyShortcuts)) { - dst->AddStringAttribute(ax::mojom::StringAttribute::kKeyShortcuts, - src.KeyboardShortcut().Utf8()); + TruncateAndAddStringAttribute(dst, + ax::mojom::StringAttribute::kKeyShortcuts, + src.KeyboardShortcut().Utf8()); } if (!src.NextOnLine().IsDetached()) { @@ -715,11 +745,13 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, dst->AddBoolAttribute(ax::mojom::BoolAttribute::kLiveAtomic, src.LiveRegionAtomic()); if (!src.LiveRegionStatus().IsEmpty()) { - dst->AddStringAttribute(ax::mojom::StringAttribute::kLiveStatus, - src.LiveRegionStatus().Utf8()); + TruncateAndAddStringAttribute(dst, + ax::mojom::StringAttribute::kLiveStatus, + src.LiveRegionStatus().Utf8()); } - dst->AddStringAttribute(ax::mojom::StringAttribute::kLiveRelevant, - src.LiveRegionRelevant().Utf8()); + TruncateAndAddStringAttribute(dst, + ax::mojom::StringAttribute::kLiveRelevant, + src.LiveRegionRelevant().Utf8()); // If we are not at the root of an atomic live region. if (src.ContainerLiveRegionAtomic() && !src.LiveRegionRoot().IsDetached() && !src.LiveRegionAtomic()) { @@ -730,10 +762,11 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, src.ContainerLiveRegionAtomic()); dst->AddBoolAttribute(ax::mojom::BoolAttribute::kContainerLiveBusy, src.ContainerLiveRegionBusy()); - dst->AddStringAttribute(ax::mojom::StringAttribute::kContainerLiveStatus, - src.ContainerLiveRegionStatus().Utf8()); - dst->AddStringAttribute( - ax::mojom::StringAttribute::kContainerLiveRelevant, + TruncateAndAddStringAttribute( + dst, ax::mojom::StringAttribute::kContainerLiveStatus, + src.ContainerLiveRegionStatus().Utf8()); + TruncateAndAddStringAttribute( + dst, ax::mojom::StringAttribute::kContainerLiveRelevant, src.ContainerLiveRegionRelevant().Utf8()); } @@ -774,12 +807,10 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, } if (dst->role == ax::mojom::Role::kRootWebArea) - dst->AddStringAttribute(ax::mojom::StringAttribute::kHtmlTag, - "#document"); + TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kHtmlTag, + "#document"); - const bool is_table_like_role = dst->role == ax::mojom::Role::kTable || - dst->role == ax::mojom::Role::kGrid || - dst->role == ax::mojom::Role::kTreeGrid; + const bool is_table_like_role = ui::IsTableLikeRole(dst->role); if (is_table_like_role) { int column_count = src.ColumnCount(); int row_count = src.RowCount(); @@ -788,10 +819,6 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, column_count); dst->AddIntAttribute(ax::mojom::IntAttribute::kTableRowCount, row_count); - WebAXObject header = src.HeaderContainerObject(); - if (!header.IsDetached()) - dst->AddIntAttribute(ax::mojom::IntAttribute::kTableHeaderId, - header.AxID()); } int aria_colcount = src.AriaColumnCount(); @@ -814,15 +841,6 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, header.AxID()); } - if (dst->role == ax::mojom::Role::kColumn) { - dst->AddIntAttribute(ax::mojom::IntAttribute::kTableColumnIndex, - src.ColumnIndex()); - WebAXObject header = src.ColumnHeader(); - if (!header.IsDetached()) - dst->AddIntAttribute(ax::mojom::IntAttribute::kTableColumnHeaderId, - header.AxID()); - } - if (dst->role == ax::mojom::Role::kCell || dst->role == ax::mojom::Role::kRowHeader || dst->role == ax::mojom::Role::kColumnHeader || @@ -873,8 +891,9 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, // TODO(ctguil): The tagName in WebKit is lower cased but // HTMLElement::nodeName calls localNameUpper. Consider adding // a WebElement method that returns the original lower cased tagName. - dst->AddStringAttribute(ax::mojom::StringAttribute::kHtmlTag, - base::ToLowerASCII(element.TagName().Utf8())); + TruncateAndAddStringAttribute( + dst, ax::mojom::StringAttribute::kHtmlTag, + base::ToLowerASCII(element.TagName().Utf8())); for (unsigned i = 0; i < element.AttributeCount(); ++i) { std::string name = base::ToLowerASCII(element.AttributeLocalName(i).Utf8()); @@ -886,8 +905,9 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, // and remove ifdef. #if defined(OS_WIN) if (dst->role == ax::mojom::Role::kMath && element.InnerHTML().length()) { - dst->AddStringAttribute(ax::mojom::StringAttribute::kInnerHtml, - element.InnerHTML().Utf8()); + TruncateAndAddStringAttribute(dst, + ax::mojom::StringAttribute::kInnerHtml, + element.InnerHTML().Utf8()); } #endif } @@ -907,12 +927,13 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, // ARIA role. if (element.HasAttribute("role")) { - dst->AddStringAttribute(ax::mojom::StringAttribute::kRole, - element.GetAttribute("role").Utf8()); + TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kRole, + element.GetAttribute("role").Utf8()); } else { std::string role = GetEquivalentAriaRoleString(dst->role); if (!role.empty()) - dst->AddStringAttribute(ax::mojom::StringAttribute::kRole, role); + TruncateAndAddStringAttribute(dst, ax::mojom::StringAttribute::kRole, + role); } // Browser plugin (used in a <webview>). @@ -967,6 +988,9 @@ void BlinkAXTreeSource::SerializeNode(WebAXObject src, } if (dst->id == image_data_node_id_) { + // In general, string attributes should be truncated using + // TruncateAndAddStringAttribute, but ImageDataUrl contains a data url + // representing an image, so add it directly using AddStringAttribute. dst->AddStringAttribute(ax::mojom::StringAttribute::kImageDataUrl, src.ImageDataUrl(max_image_data_size_).Utf8()); } @@ -991,4 +1015,18 @@ WebAXObject BlinkAXTreeSource::ComputeRoot() const { return WebAXObject(); } +void BlinkAXTreeSource::TruncateAndAddStringAttribute( + AXContentNodeData* dst, + ax::mojom::StringAttribute attribute, + const std::string& value) const { + if (value.size() > BlinkAXTreeSource::kMaxStringAttributeLength) { + std::string truncated; + base::TruncateUTF8ToByteSize( + value, BlinkAXTreeSource::kMaxStringAttributeLength, &truncated); + dst->AddStringAttribute(attribute, truncated); + } else { + dst->AddStringAttribute(attribute, value); + } +} + } // namespace content diff --git a/chromium/content/renderer/accessibility/blink_ax_tree_source.h b/chromium/content/renderer/accessibility/blink_ax_tree_source.h index 4447c4eb800..2adf7bf8cbe 100644 --- a/chromium/content/renderer/accessibility/blink_ax_tree_source.h +++ b/chromium/content/renderer/accessibility/blink_ax_tree_source.h @@ -110,6 +110,11 @@ class BlinkAXTreeSource blink::WebAXObject ComputeRoot() const; + uint32_t kMaxStringAttributeLength = 10000; + void TruncateAndAddStringAttribute(AXContentNodeData* dst, + ax::mojom::StringAttribute attribute, + const std::string& value) const; + RenderFrameImpl* render_frame_; ui::AXMode accessibility_mode_; diff --git a/chromium/content/renderer/accessibility/render_accessibility_impl.cc b/chromium/content/renderer/accessibility/render_accessibility_impl.cc index 79fd36cffc5..05fbd8de672 100644 --- a/chromium/content/renderer/accessibility/render_accessibility_impl.cc +++ b/chromium/content/renderer/accessibility/render_accessibility_impl.cc @@ -29,7 +29,9 @@ #include "third_party/blink/public/web/web_user_gesture_indicator.h" #include "third_party/blink/public/web/web_view.h" #include "ui/accessibility/ax_enum_util.h" +#include "ui/accessibility/ax_event.h" #include "ui/accessibility/ax_node.h" +#include "ui/accessibility/ax_role_properties.h" using blink::WebAXObject; using blink::WebDocument; @@ -183,7 +185,7 @@ bool RenderAccessibilityImpl::OnMessageReceived(const IPC::Message& message) { IPC_BEGIN_MESSAGE_MAP(RenderAccessibilityImpl, message) IPC_MESSAGE_HANDLER(AccessibilityMsg_PerformAction, OnPerformAction) - IPC_MESSAGE_HANDLER(AccessibilityMsg_Events_ACK, OnEventsAck) + IPC_MESSAGE_HANDLER(AccessibilityMsg_EventBundle_ACK, OnEventsAck) IPC_MESSAGE_HANDLER(AccessibilityMsg_HitTest, OnHitTest) IPC_MESSAGE_HANDLER(AccessibilityMsg_Reset, OnReset) IPC_MESSAGE_HANDLER(AccessibilityMsg_FatalError, OnFatalError) @@ -272,7 +274,7 @@ void RenderAccessibilityImpl::HandleAXEvent(const blink::WebAXObject& obj, // Force the newly focused node to be re-serialized so we include its // inline text boxes. if (event == ax::mojom::Event::kFocus) - serializer_.DeleteClientSubtree(obj); + serializer_.InvalidateSubtree(obj); #endif // If some cell IDs have been added or removed, we need to update the whole @@ -281,7 +283,7 @@ void RenderAccessibilityImpl::HandleAXEvent(const blink::WebAXObject& obj, event == ax::mojom::Event::kChildrenChanged) { WebAXObject table_like_object = obj.ParentObject(); if (!table_like_object.IsDetached()) { - serializer_.DeleteClientSubtree(table_like_object); + serializer_.InvalidateSubtree(table_like_object); HandleAXEvent(table_like_object, ax::mojom::Event::kChildrenChanged); } } @@ -292,13 +294,13 @@ void RenderAccessibilityImpl::HandleAXEvent(const blink::WebAXObject& obj, event == ax::mojom::Event::kChildrenChanged) { WebAXObject popup_like_object = obj.ParentObject(); if (!popup_like_object.IsDetached()) { - serializer_.DeleteClientSubtree(popup_like_object); + serializer_.InvalidateSubtree(popup_like_object); HandleAXEvent(popup_like_object, ax::mojom::Event::kChildrenChanged); } } // Add the accessibility object to our cache and ensure it's valid. - AccessibilityHostMsg_EventParams acc_event; + ui::AXEvent acc_event; acc_event.id = obj.AxID(); acc_event.event_type = event; @@ -410,18 +412,23 @@ void RenderAccessibilityImpl::SendPendingAccessibilityEvents() { // Make a copy of the events, because it's possible that // actions inside this loop will cause more events to be // queued up. - std::vector<AccessibilityHostMsg_EventParams> src_events = pending_events_; + std::vector<ui::AXEvent> src_events = pending_events_; pending_events_.clear(); - // Generate an event message from each Blink event. - std::vector<AccessibilityHostMsg_EventParams> event_msgs; + // The serialized event bundle to send to the browser. + AccessibilityHostMsg_EventBundleParams bundle; + + // Keep track of nodes in the tree that need to be updated. + std::vector<DirtyObject> dirty_objects; // If there's a layout complete message, we need to send location changes. bool had_layout_complete_messages = false; + ScopedFreezeBlinkAXTreeSource freeze(&tree_source_); + // Loop over each event and generate an updated event message. for (size_t i = 0; i < src_events.size(); ++i) { - AccessibilityHostMsg_EventParams& event = src_events[i]; + ui::AXEvent& event = src_events[i]; if (event.event_type == ax::mojom::Event::kLayoutComplete) had_layout_complete_messages = true; @@ -435,40 +442,64 @@ void RenderAccessibilityImpl::SendPendingAccessibilityEvents() { while (!obj.IsDetached() && obj.AccessibilityIsIgnored()) obj = obj.ParentObject(); - ScopedFreezeBlinkAXTreeSource freeze(&tree_source_); - // Make sure it's a descendant of our root node - exceptions include the // scroll area that's the parent of the main document (we ignore it), and // possibly nodes attached to a different document. if (!tree_source_.IsInTree(obj)) continue; - AccessibilityHostMsg_EventParams event_msg; - event_msg.event_type = event.event_type; - event_msg.id = event.id; - event_msg.event_from = event.event_from; - event_msg.action_request_id = event.action_request_id; + bundle.events.push_back(event); + + // Whenever there's a change within a table, invalidate the + // whole table so that row and cell indexes are recomputed. + ax::mojom::Role role = AXRoleFromBlink(obj.Role()); + if (ui::IsTableLikeRole(role) || role == ax::mojom::Role::kRow || + ui::IsCellOrTableHeaderRole(role)) { + auto table = obj; + while (!table.IsDetached() && + !ui::IsTableLikeRole(AXRoleFromBlink(table.Role()))) + table = table.ParentObject(); + if (!table.IsDetached()) + serializer_.InvalidateSubtree(table); + } + + VLOG(1) << "Accessibility event: " << ui::ToString(event.event_type) + << " on node id " << event.id; + + DirtyObject dirty_object; + dirty_object.obj = obj; + dirty_object.event_from = event.event_from; + dirty_objects.push_back(dirty_object); + } + + // Now serialize all dirty objects. Keep track of IDs serialized + // so we don't have to serialize the same node twice. + std::set<int32_t> already_serialized_ids; + for (size_t i = 0; i < dirty_objects.size(); i++) { + auto obj = dirty_objects[i].obj; + if (already_serialized_ids.find(obj.AxID()) != already_serialized_ids.end()) + continue; + AXContentTreeUpdate update; + update.event_from = dirty_objects[i].event_from; // If there's a plugin, force the tree data to be generated in every // message so the plugin can merge its own tree data changes. if (plugin_tree_source_) - event_msg.update.has_tree_data = true; + update.has_tree_data = true; - if (!serializer_.SerializeChanges(obj, &event_msg.update)) { + if (!serializer_.SerializeChanges(obj, &update)) { VLOG(1) << "Failed to serialize one accessibility event."; continue; } if (plugin_tree_source_) - AddPluginTreeToUpdate(&event_msg.update); - - event_msgs.push_back(event_msg); + AddPluginTreeToUpdate(&update); // For each node in the update, set the location in our map from // ids to locations. - for (size_t j = 0; j < event_msg.update.nodes.size(); ++j) { - ui::AXNodeData& src = event_msg.update.nodes[j]; - ui::AXRelativeBounds& dst = locations_[event_msg.update.nodes[j].id]; + for (size_t j = 0; j < update.nodes.size(); ++j) { + ui::AXNodeData& src = update.nodes[j]; + ui::AXRelativeBounds& dst = locations_[update.nodes[j].id]; dst.offset_container_id = src.offset_container_id; dst.bounds = src.location; dst.transform.reset(nullptr); @@ -476,13 +507,16 @@ void RenderAccessibilityImpl::SendPendingAccessibilityEvents() { dst.transform.reset(new gfx::Transform(*src.transform)); } - VLOG(1) << "Accessibility event: " << ui::ToString(event.event_type) - << " on node id " << event_msg.id - << "\n" << event_msg.update.ToString(); + for (size_t j = 0; j < update.nodes.size(); ++j) + already_serialized_ids.insert(update.nodes[j].id); + + bundle.updates.push_back(update); + + VLOG(1) << "Accessibility tree update:\n" << update.ToString(); } - Send(new AccessibilityHostMsg_Events(routing_id(), event_msgs, reset_token_, - ack_token_)); + Send(new AccessibilityHostMsg_EventBundle(routing_id(), bundle, reset_token_, + ack_token_)); reset_token_ = 0; if (had_layout_complete_messages) @@ -495,7 +529,6 @@ void RenderAccessibilityImpl::SendLocationChanges() { std::vector<AccessibilityHostMsg_LocationChangeParams> messages; // Update layout on the root of the tree. - ScopedFreezeBlinkAXTreeSource freeze(&tree_source_); WebAXObject root = tree_source_.GetRoot(); if (!root.UpdateLayoutAndCheckValidity()) return; @@ -616,7 +649,7 @@ void RenderAccessibilityImpl::OnPerformAction( target.SetSequentialFocusNavigationStartingPoint(); break; case ax::mojom::Action::kSetValue: - target.SetValue(blink::WebString::FromUTF16(data.value)); + target.SetValue(blink::WebString::FromUTF8(data.value)); HandleAXEvent(target, ax::mojom::Event::kValueChanged); break; case ax::mojom::Action::kShowContextMenu: @@ -700,7 +733,7 @@ void RenderAccessibilityImpl::OnLoadInlineTextBoxes( // This object may not be a leaf node. Force the whole subtree to be // re-serialized. - serializer_.DeleteClientSubtree(obj); + serializer_.InvalidateSubtree(obj); // Explicitly send a tree change update event now. HandleAXEvent(obj, ax::mojom::Event::kTreeChanged); @@ -719,7 +752,7 @@ void RenderAccessibilityImpl::OnGetImageData( if (document.IsNull()) return; - serializer_.DeleteClientSubtree(obj); + serializer_.InvalidateSubtree(obj); HandleAXEvent(obj, ax::mojom::Event::kImageFrameUpdated); } diff --git a/chromium/content/renderer/accessibility/render_accessibility_impl.h b/chromium/content/renderer/accessibility/render_accessibility_impl.h index 3d3563a7ffc..f2c5d3fb805 100644 --- a/chromium/content/renderer/accessibility/render_accessibility_impl.h +++ b/chromium/content/renderer/accessibility/render_accessibility_impl.h @@ -20,8 +20,6 @@ #include "ui/accessibility/ax_tree_serializer.h" #include "ui/gfx/geometry/rect_f.h" -struct AccessibilityHostMsg_EventParams; - namespace blink { class WebDocument; class WebNode; @@ -29,6 +27,7 @@ class WebNode; namespace ui { struct AXActionData; +struct AXEvent; } namespace content { @@ -115,6 +114,11 @@ class CONTENT_EXPORT RenderAccessibilityImpl void SendLocationChanges(); private: + struct DirtyObject { + blink::WebAXObject obj; + ax::mojom::EventFrom event_from; + }; + // RenderFrameObserver implementation. void OnDestruct() override; @@ -137,7 +141,7 @@ class CONTENT_EXPORT RenderAccessibilityImpl // Events from Blink are collected until they are ready to be // sent to the browser. - std::vector<AccessibilityHostMsg_EventParams> pending_events_; + std::vector<ui::AXEvent> pending_events_; // The adapter that exposes Blink's accessibility tree to AXTreeSerializer. BlinkAXTreeSource tree_source_; diff --git a/chromium/content/renderer/accessibility/render_accessibility_impl_browsertest.cc b/chromium/content/renderer/accessibility/render_accessibility_impl_browsertest.cc index 07978a44eec..e812e74632f 100644 --- a/chromium/content/renderer/accessibility/render_accessibility_impl_browsertest.cc +++ b/chromium/content/renderer/accessibility/render_accessibility_impl_browsertest.cc @@ -67,28 +67,26 @@ class RenderAccessibilityImplTest : public RenderViewTest { void SetMode(ui::AXMode mode) { frame()->OnSetAccessibilityMode(mode); } - void GetAllAccEvents( - std::vector<AccessibilityHostMsg_EventParams>* param_list) { + void GetLastAccessibilityEventBundle( + AccessibilityHostMsg_EventBundleParams* event_bundle) { const IPC::Message* message = - sink_->GetUniqueMessageMatching(AccessibilityHostMsg_Events::ID); + sink_->GetUniqueMessageMatching(AccessibilityHostMsg_EventBundle::ID); ASSERT_TRUE(message); - std::tuple<std::vector<AccessibilityHostMsg_EventParams>, int, int> param; - AccessibilityHostMsg_Events::Read(message, ¶m); - *param_list = std::get<0>(param); + std::tuple<AccessibilityHostMsg_EventBundleParams, int, int> param; + AccessibilityHostMsg_EventBundle::Read(message, ¶m); + *event_bundle = std::get<0>(param); } - void GetLastAccEvent( - AccessibilityHostMsg_EventParams* params) { - std::vector<AccessibilityHostMsg_EventParams> param_list; - GetAllAccEvents(¶m_list); - ASSERT_GE(param_list.size(), 1U); - *params = param_list[0]; + AXContentTreeUpdate GetLastAccUpdate() { + AccessibilityHostMsg_EventBundleParams event_bundle; + GetLastAccessibilityEventBundle(&event_bundle); + CHECK_GE(event_bundle.updates.size(), 1U); + return event_bundle.updates[event_bundle.updates.size() - 1]; } int CountAccessibilityNodesSentToBrowser() { - AccessibilityHostMsg_EventParams event; - GetLastAccEvent(&event); - return event.update.nodes.size(); + AXContentTreeUpdate update = GetLastAccUpdate(); + return update.nodes.size(); } protected: @@ -130,9 +128,8 @@ TEST_F(RenderAccessibilityImplTest, SendFullAccessibilityTreeOnReload) { EXPECT_EQ(1, CountAccessibilityNodesSentToBrowser()); { // Make sure it's the root object that was updated. - AccessibilityHostMsg_EventParams event; - GetLastAccEvent(&event); - EXPECT_EQ(root_obj.AxID(), event.update.nodes[0].id); + AXContentTreeUpdate update = GetLastAccUpdate(); + EXPECT_EQ(root_obj.AxID(), update.nodes[0].id); } // If we reload the page and send a event, we should send @@ -197,15 +194,14 @@ TEST_F(RenderAccessibilityImplTest, HideAccessibilityObject) { accessibility->HandleAXEvent(node_a, ax::mojom::Event::kChildrenChanged); accessibility->SendPendingAccessibilityEvents(); - AccessibilityHostMsg_EventParams event; - GetLastAccEvent(&event); - ASSERT_EQ(2U, event.update.nodes.size()); + AXContentTreeUpdate update = GetLastAccUpdate(); + ASSERT_EQ(2U, update.nodes.size()); // RenderAccessibilityImpl notices that 'C' is being reparented, // so it clears the subtree rooted at 'A', then updates 'A' and then 'C'. - EXPECT_EQ(node_a.AxID(), event.update.node_id_to_clear); - EXPECT_EQ(node_a.AxID(), event.update.nodes[0].id); - EXPECT_EQ(node_c.AxID(), event.update.nodes[1].id); + EXPECT_EQ(node_a.AxID(), update.node_id_to_clear); + EXPECT_EQ(node_a.AxID(), update.nodes[0].id); + EXPECT_EQ(node_c.AxID(), update.nodes[1].id); EXPECT_EQ(2, CountAccessibilityNodesSentToBrowser()); } @@ -245,14 +241,13 @@ TEST_F(RenderAccessibilityImplTest, ShowAccessibilityObject) { accessibility->HandleAXEvent(node_a, ax::mojom::Event::kChildrenChanged); accessibility->SendPendingAccessibilityEvents(); - AccessibilityHostMsg_EventParams event; - GetLastAccEvent(&event); - - ASSERT_EQ(3U, event.update.nodes.size()); - EXPECT_EQ(node_a.AxID(), event.update.node_id_to_clear); - EXPECT_EQ(node_a.AxID(), event.update.nodes[0].id); - EXPECT_EQ(node_b.AxID(), event.update.nodes[1].id); - EXPECT_EQ(node_c.AxID(), event.update.nodes[2].id); + AXContentTreeUpdate update = GetLastAccUpdate(); + + ASSERT_EQ(3U, update.nodes.size()); + EXPECT_EQ(node_a.AxID(), update.node_id_to_clear); + EXPECT_EQ(node_a.AxID(), update.nodes[0].id); + EXPECT_EQ(node_b.AxID(), update.nodes[1].id); + EXPECT_EQ(node_c.AxID(), update.nodes[2].id); EXPECT_EQ(3, CountAccessibilityNodesSentToBrowser()); } diff --git a/chromium/content/renderer/android/synchronous_compositor_proxy.cc b/chromium/content/renderer/android/synchronous_compositor_proxy.cc index 441d8e860b7..0ad58b0748e 100644 --- a/chromium/content/renderer/android/synchronous_compositor_proxy.cc +++ b/chromium/content/renderer/android/synchronous_compositor_proxy.cc @@ -23,6 +23,7 @@ namespace content { SynchronousCompositorProxy::SynchronousCompositorProxy( ui::SynchronousInputHandlerProxy* input_handler_proxy) : input_handler_proxy_(input_handler_proxy), + binding_(this), use_in_process_zero_copy_software_draw_( base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kSingleProcess)), @@ -31,6 +32,7 @@ SynchronousCompositorProxy::SynchronousCompositorProxy( max_page_scale_factor_(0.f), need_animate_scroll_(false), need_invalidate_count_(0u), + invalidate_needs_draw_(false), did_activate_pending_tree_count_(0u) { DCHECK(input_handler_proxy_); } @@ -66,7 +68,7 @@ void SynchronousCompositorProxy::SetNeedsSynchronousAnimateInput() { SendSetNeedsBeginFramesIfNeeded(); } else { need_animate_scroll_ = true; - Invalidate(); + Invalidate(true); } } @@ -94,8 +96,9 @@ void SynchronousCompositorProxy::UpdateRootLayerState( } } -void SynchronousCompositorProxy::Invalidate() { +void SynchronousCompositorProxy::Invalidate(bool needs_draw) { ++need_invalidate_count_; + invalidate_needs_draw_ |= needs_draw; SendAsyncRendererStateIfNeeded(); } @@ -114,6 +117,7 @@ void SynchronousCompositorProxy::PopulateCommonParams( params->min_page_scale_factor = min_page_scale_factor_; params->max_page_scale_factor = max_page_scale_factor_; params->need_invalidate_count = need_invalidate_count_; + params->invalidate_needs_draw = invalidate_needs_draw_; params->did_activate_pending_tree_count = did_activate_pending_tree_count_; if (!compute_scroll_called_via_ipc_) params->need_animate_scroll = need_animate_scroll_; @@ -130,6 +134,7 @@ void SynchronousCompositorProxy::DemandDrawHwAsync( void SynchronousCompositorProxy::DemandDrawHw( const SyncCompositorDemandDrawHwParams& params, DemandDrawHwCallback callback) { + invalidate_needs_draw_ = false; hardware_draw_reply_ = std::move(callback); if (layer_tree_frame_sink_) { @@ -149,6 +154,10 @@ void SynchronousCompositorProxy::DemandDrawHw( } } +void SynchronousCompositorProxy::WillSkipDraw() { + layer_tree_frame_sink_->WillSkipDraw(); +} + struct SynchronousCompositorProxy::SharedMemoryWithSize { base::SharedMemory shm; const size_t buffer_size; @@ -172,6 +181,7 @@ void SynchronousCompositorProxy::ZeroSharedMemory() { void SynchronousCompositorProxy::DemandDrawSw( const SyncCompositorDemandDrawSwParams& params, DemandDrawSwCallback callback) { + invalidate_needs_draw_ = false; software_draw_reply_ = std::move(callback); if (layer_tree_frame_sink_) { SkCanvas* sk_canvas_for_draw = SynchronousCompositorGetSkCanvas(); @@ -336,4 +346,55 @@ uint32_t SynchronousCompositorProxy::NextMetadataVersion() { return ++metadata_version_; } +void SynchronousCompositorProxy::SendDemandDrawHwAsyncReply( + const content::SyncCompositorCommonRendererParams&, + uint32_t layer_tree_frame_sink_id, + uint32_t metadata_version, + base::Optional<viz::CompositorFrame> frame) { + control_host_->ReturnFrame(layer_tree_frame_sink_id, metadata_version, + std::move(frame)); +} + +void SynchronousCompositorProxy::SendBeginFrameResponse( + const content::SyncCompositorCommonRendererParams& param) { + control_host_->BeginFrameResponse(param); +} + +void SynchronousCompositorProxy::SendAsyncRendererStateIfNeeded() { + if (hardware_draw_reply_ || software_draw_reply_ || zoom_by_reply_ || !host_) + return; + + SyncCompositorCommonRendererParams params; + PopulateCommonParams(¶ms); + host_->UpdateState(params); +} + +void SynchronousCompositorProxy::SendSetNeedsBeginFrames( + bool needs_begin_frames) { + needs_begin_frame_ = needs_begin_frames; + if (host_) + host_->SetNeedsBeginFrames(needs_begin_frames); +} + +void SynchronousCompositorProxy::LayerTreeFrameSinkCreated() { + DCHECK(layer_tree_frame_sink_); + if (host_) + host_->LayerTreeFrameSinkCreated(); +} + +void SynchronousCompositorProxy::BindChannel( + mojom::SynchronousCompositorControlHostPtr control_host, + mojom::SynchronousCompositorHostAssociatedPtrInfo host, + mojom::SynchronousCompositorAssociatedRequest compositor_request) { + control_host_ = std::move(control_host); + host_.Bind(std::move(host)); + binding_.Bind(std::move(compositor_request)); + + if (layer_tree_frame_sink_) + LayerTreeFrameSinkCreated(); + + if (needs_begin_frame_) + host_->SetNeedsBeginFrames(true); +} + } // namespace content diff --git a/chromium/content/renderer/android/synchronous_compositor_proxy.h b/chromium/content/renderer/android/synchronous_compositor_proxy.h index e3ed37f29cc..8319840a6d4 100644 --- a/chromium/content/renderer/android/synchronous_compositor_proxy.h +++ b/chromium/content/renderer/android/synchronous_compositor_proxy.h @@ -40,6 +40,10 @@ class SynchronousCompositorProxy : public ui::SynchronousInputHandler, ~SynchronousCompositorProxy() override; void Init(); + void BindChannel( + mojom::SynchronousCompositorControlHostPtr control_host, + mojom::SynchronousCompositorHostAssociatedPtrInfo host, + mojom::SynchronousCompositorAssociatedRequest compositor_request); // ui::SynchronousInputHandler overrides. void SetNeedsSynchronousAnimateInput() final; @@ -52,7 +56,7 @@ class SynchronousCompositorProxy : public ui::SynchronousInputHandler, // SynchronousLayerTreeFrameSinkClient overrides. void DidActivatePendingTree() final; - void Invalidate() final; + void Invalidate(bool needs_draw) final; void SubmitCompositorFrame(uint32_t layer_tree_frame_sink_id, viz::CompositorFrame frame) final; void SetNeedsBeginFrames(bool needs_begin_frames) final; @@ -74,6 +78,7 @@ class SynchronousCompositorProxy : public ui::SynchronousInputHandler, SetSharedMemoryCallback callback) final; void DemandDrawSw(const SyncCompositorDemandDrawSwParams& params, DemandDrawSwCallback callback) final; + void WillSkipDraw() final; void ZeroSharedMemory() final; void ZoomBy(float zoom_delta, const gfx::Point& anchor, ZoomByCallback) final; void SetMemoryPolicy(uint32_t bytes_limit) final; @@ -85,16 +90,16 @@ class SynchronousCompositorProxy : public ui::SynchronousInputHandler, void SetBeginFrameSourcePaused(bool paused) final; protected: - virtual void SendSetNeedsBeginFrames(bool needs_begin_frames) = 0; - virtual void SendAsyncRendererStateIfNeeded() = 0; - virtual void LayerTreeFrameSinkCreated() = 0; - virtual void SendBeginFrameResponse( - const content::SyncCompositorCommonRendererParams&) = 0; - virtual void SendDemandDrawHwAsyncReply( + void SendSetNeedsBeginFrames(bool needs_begin_frames); + void SendAsyncRendererStateIfNeeded(); + void LayerTreeFrameSinkCreated(); + void SendBeginFrameResponse( + const content::SyncCompositorCommonRendererParams&); + void SendDemandDrawHwAsyncReply( const content::SyncCompositorCommonRendererParams&, uint32_t layer_tree_frame_sink_id, uint32_t metadata_version, - base::Optional<viz::CompositorFrame>) = 0; + base::Optional<viz::CompositorFrame>); DemandDrawHwCallback hardware_draw_reply_; DemandDrawSwCallback software_draw_reply_; @@ -109,10 +114,14 @@ class SynchronousCompositorProxy : public ui::SynchronousInputHandler, struct SharedMemoryWithSize; ui::SynchronousInputHandlerProxy* const input_handler_proxy_; + mojom::SynchronousCompositorControlHostPtr control_host_; + mojom::SynchronousCompositorHostAssociatedPtr host_; + mojo::AssociatedBinding<mojom::SynchronousCompositor> binding_; const bool use_in_process_zero_copy_software_draw_; bool compute_scroll_called_via_ipc_ = false; bool browser_needs_begin_frame_state_ = false; + bool needs_begin_frame_ = false; bool needs_begin_frame_for_frame_sink_ = false; bool needs_begin_frame_for_animate_input_ = false; @@ -129,6 +138,7 @@ class SynchronousCompositorProxy : public ui::SynchronousInputHandler, float max_page_scale_factor_; bool need_animate_scroll_; uint32_t need_invalidate_count_; + bool invalidate_needs_draw_; uint32_t did_activate_pending_tree_count_; uint32_t metadata_version_ = 0u; diff --git a/chromium/content/renderer/android/synchronous_compositor_proxy_mojo.cc b/chromium/content/renderer/android/synchronous_compositor_proxy_mojo.cc deleted file mode 100644 index 3c3019de1c0..00000000000 --- a/chromium/content/renderer/android/synchronous_compositor_proxy_mojo.cc +++ /dev/null @@ -1,66 +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/renderer/android/synchronous_compositor_proxy_mojo.h" - -namespace content { - -SynchronousCompositorProxyMojo::SynchronousCompositorProxyMojo( - ui::SynchronousInputHandlerProxy* input_handler_proxy) - : SynchronousCompositorProxy(input_handler_proxy), binding_(this) {} - -SynchronousCompositorProxyMojo::~SynchronousCompositorProxyMojo() {} - -void SynchronousCompositorProxyMojo::SendDemandDrawHwAsyncReply( - const content::SyncCompositorCommonRendererParams&, - uint32_t layer_tree_frame_sink_id, - uint32_t metadata_version, - base::Optional<viz::CompositorFrame> frame) { - control_host_->ReturnFrame(layer_tree_frame_sink_id, metadata_version, - std::move(frame)); -} - -void SynchronousCompositorProxyMojo::SendBeginFrameResponse( - const content::SyncCompositorCommonRendererParams& param) { - control_host_->BeginFrameResponse(param); -} - -void SynchronousCompositorProxyMojo::SendAsyncRendererStateIfNeeded() { - if (hardware_draw_reply_ || software_draw_reply_ || zoom_by_reply_ || !host_) - return; - - SyncCompositorCommonRendererParams params; - PopulateCommonParams(¶ms); - host_->UpdateState(params); -} - -void SynchronousCompositorProxyMojo::SendSetNeedsBeginFrames( - bool needs_begin_frames) { - needs_begin_frame_ = needs_begin_frames; - if (host_) - host_->SetNeedsBeginFrames(needs_begin_frames); -} - -void SynchronousCompositorProxyMojo::LayerTreeFrameSinkCreated() { - DCHECK(layer_tree_frame_sink_); - if (host_) - host_->LayerTreeFrameSinkCreated(); -} - -void SynchronousCompositorProxyMojo::BindChannel( - mojom::SynchronousCompositorControlHostPtr control_host, - mojom::SynchronousCompositorHostAssociatedPtrInfo host, - mojom::SynchronousCompositorAssociatedRequest compositor_request) { - control_host_ = std::move(control_host); - host_.Bind(std::move(host)); - binding_.Bind(std::move(compositor_request)); - - if (layer_tree_frame_sink_) - LayerTreeFrameSinkCreated(); - - if (needs_begin_frame_) - host_->SetNeedsBeginFrames(true); -} - -} // namespace content diff --git a/chromium/content/renderer/android/synchronous_compositor_proxy_mojo.h b/chromium/content/renderer/android/synchronous_compositor_proxy_mojo.h deleted file mode 100644 index 236b938db92..00000000000 --- a/chromium/content/renderer/android/synchronous_compositor_proxy_mojo.h +++ /dev/null @@ -1,48 +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_RENDERER_ANDROID_SYNCHRONOUS_COMPOSITOR_PROXY_MOJO_H_ -#define CONTENT_RENDERER_ANDROID_SYNCHRONOUS_COMPOSITOR_PROXY_MOJO_H_ - -#include "content/renderer/android/synchronous_compositor_proxy.h" - -namespace content { - -// This class implements the SynchronousCompositorProxy with -// IPC messaging backed by mojo. -class SynchronousCompositorProxyMojo : public SynchronousCompositorProxy { - public: - SynchronousCompositorProxyMojo( - ui::SynchronousInputHandlerProxy* input_handler_proxy); - ~SynchronousCompositorProxyMojo() override; - - void BindChannel( - mojom::SynchronousCompositorControlHostPtr control_host, - mojom::SynchronousCompositorHostAssociatedPtrInfo host, - mojom::SynchronousCompositorAssociatedRequest compositor_request); - - protected: - void SendSetNeedsBeginFrames(bool needs_begin_frames) final; - void SendAsyncRendererStateIfNeeded() final; - void LayerTreeFrameSinkCreated() final; - void SendBeginFrameResponse( - const content::SyncCompositorCommonRendererParams&) final; - void SendDemandDrawHwAsyncReply( - const content::SyncCompositorCommonRendererParams&, - uint32_t layer_tree_frame_sink_id, - uint32_t metadata_version, - base::Optional<viz::CompositorFrame>) final; - - private: - mojom::SynchronousCompositorControlHostPtr control_host_; - mojom::SynchronousCompositorHostAssociatedPtr host_; - mojo::AssociatedBinding<mojom::SynchronousCompositor> binding_; - bool needs_begin_frame_ = false; - - DISALLOW_COPY_AND_ASSIGN(SynchronousCompositorProxyMojo); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_ANDROID_SYNCHRONOUS_COMPOSITOR_PROXY_MOJO_H_ diff --git a/chromium/content/renderer/android/synchronous_layer_tree_frame_sink.cc b/chromium/content/renderer/android/synchronous_layer_tree_frame_sink.cc index 2b66ba1ad54..24c569eea65 100644 --- a/chromium/content/renderer/android/synchronous_layer_tree_frame_sink.cc +++ b/chromium/content/renderer/android/synchronous_layer_tree_frame_sink.cc @@ -86,6 +86,12 @@ class SynchronousLayerTreeFrameSink::SoftwareOutputSurface void BindFramebuffer() override {} void SetDrawRectangle(const gfx::Rect& rect) override {} void SwapBuffers(viz::OutputSurfaceFrame frame) override {} +#if BUILDFLAG(ENABLE_VULKAN) + gpu::VulkanSurface* GetVulkanSurface() override { + NOTIMPLEMENTED(); + return nullptr; + } +#endif void Reshape(const gfx::Size& size, float scale_factor, const gfx::ColorSpace& color_space, @@ -154,7 +160,10 @@ bool SynchronousLayerTreeFrameSink::BindToClient( if (!cc::LayerTreeFrameSink::BindToClient(sink_client)) return false; - frame_sink_manager_ = std::make_unique<viz::FrameSinkManagerImpl>(); + // The SharedBitmapManager is null since software compositing is not supported + // or used on Android. + frame_sink_manager_ = std::make_unique<viz::FrameSinkManagerImpl>( + /*shared_bitmap_manager=*/nullptr); client_->SetBeginFrameSource(synthetic_begin_frame_source_ ? synthetic_begin_frame_source_.get() @@ -361,10 +370,10 @@ void SynchronousLayerTreeFrameSink::FallbackTickFired() { frame_swap_message_queue_->NotifyFramesAreDiscarded(false); } -void SynchronousLayerTreeFrameSink::Invalidate() { +void SynchronousLayerTreeFrameSink::Invalidate(bool needs_draw) { DCHECK(CalledOnValidThread()); if (sync_client_) - sync_client_->Invalidate(); + sync_client_->Invalidate(needs_draw); if (!fallback_tick_pending_) { fallback_tick_.Reset( @@ -413,6 +422,12 @@ void SynchronousLayerTreeFrameSink::DemandDrawSw(SkCanvas* canvas) { InvokeComposite(transform, viewport); } +void SynchronousLayerTreeFrameSink::WillSkipDraw() { + CancelFallbackTick(); + client_->OnDraw(gfx::Transform(), gfx::Rect(), in_software_draw_, + true /*skip_draw*/); +} + void SynchronousLayerTreeFrameSink::InvokeComposite( const gfx::Transform& transform, const gfx::Rect& viewport) { @@ -425,7 +440,8 @@ void SynchronousLayerTreeFrameSink::InvokeComposite( // SetExternalTilePriorityConstraints), surely this could be more clear? gfx::Transform adjusted_transform = transform; adjusted_transform.matrix().postTranslate(-viewport.x(), -viewport.y(), 0); - client_->OnDraw(adjusted_transform, viewport, in_software_draw_); + client_->OnDraw(adjusted_transform, viewport, in_software_draw_, + false /*skip_draw*/); if (did_submit_frame_) { // This must happen after unwinding the stack and leaving the compositor. @@ -500,12 +516,7 @@ void SynchronousLayerTreeFrameSink::DidReceiveCompositorFrameAck( void SynchronousLayerTreeFrameSink::DidPresentCompositorFrame( uint32_t presentation_token, - base::TimeTicks time, - base::TimeDelta refresh, - uint32_t flags) {} - -void SynchronousLayerTreeFrameSink::DidDiscardCompositorFrame( - uint32_t presentation_token) {} + const gfx::PresentationFeedback& feedback) {} void SynchronousLayerTreeFrameSink::OnBeginFrame( const viz::BeginFrameArgs& args) {} diff --git a/chromium/content/renderer/android/synchronous_layer_tree_frame_sink.h b/chromium/content/renderer/android/synchronous_layer_tree_frame_sink.h index 380c3109a16..5177e340848 100644 --- a/chromium/content/renderer/android/synchronous_layer_tree_frame_sink.h +++ b/chromium/content/renderer/android/synchronous_layer_tree_frame_sink.h @@ -50,7 +50,7 @@ class SynchronousCompositorRegistry; class SynchronousLayerTreeFrameSinkClient { public: virtual void DidActivatePendingTree() = 0; - virtual void Invalidate() = 0; + virtual void Invalidate(bool needs_draw) = 0; virtual void SubmitCompositorFrame(uint32_t layer_tree_frame_sink_id, viz::CompositorFrame frame) = 0; virtual void SetNeedsBeginFrames(bool needs_begin_frames) = 0; @@ -96,22 +96,21 @@ class SynchronousLayerTreeFrameSink void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer, const viz::SharedBitmapId& id) override; void DidDeleteSharedBitmap(const viz::SharedBitmapId& id) override; - void Invalidate() override; + void Invalidate(bool needs_draw) override; // Partial SynchronousCompositor API implementation. void DemandDrawHw(const gfx::Size& viewport_size, const gfx::Rect& viewport_rect_for_tile_priority, const gfx::Transform& transform_for_tile_priority); void DemandDrawSw(SkCanvas* canvas); + void WillSkipDraw(); // viz::mojom::CompositorFrameSinkClient implementation. void DidReceiveCompositorFrameAck( const std::vector<viz::ReturnedResource>& resources) override; - void DidPresentCompositorFrame(uint32_t presentation_token, - base::TimeTicks time, - base::TimeDelta refresh, - uint32_t flags) override; - void DidDiscardCompositorFrame(uint32_t presentation_token) override; + void DidPresentCompositorFrame( + uint32_t presentation_token, + const gfx::PresentationFeedback& feedback) override; void OnBeginFrame(const viz::BeginFrameArgs& args) override; void ReclaimResources( const std::vector<viz::ReturnedResource>& resources) override; @@ -172,6 +171,7 @@ class SynchronousLayerTreeFrameSink void DisplayDidDrawAndSwap() override {} void DisplayDidReceiveCALayerParams( const gfx::CALayerParams& ca_layer_params) override {} + void DisplayDidCompleteSwapWithSize(const gfx::Size& pixel_size) override {} void DidSwapAfterSnapshotRequestReceived( const std::vector<ui::LatencyInfo>& latency_info) override {} }; diff --git a/chromium/content/renderer/appcache/web_application_cache_host_impl.cc b/chromium/content/renderer/appcache/web_application_cache_host_impl.cc index ef2969aaa1c..8e1f7d18566 100644 --- a/chromium/content/renderer/appcache/web_application_cache_host_impl.cc +++ b/chromium/content/renderer/appcache/web_application_cache_host_impl.cc @@ -5,21 +5,19 @@ #include "content/renderer/appcache/web_application_cache_host_impl.h" #include <stddef.h> +#include <vector> #include "base/compiler_specific.h" #include "base/containers/id_map.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" -#include "content/public/common/browser_side_navigation_policy.h" #include "third_party/blink/public/platform/web_string.h" #include "third_party/blink/public/platform/web_url.h" -#include "third_party/blink/public/platform/web_url_request.h" #include "third_party/blink/public/platform/web_url_response.h" using blink::WebApplicationCacheHost; using blink::WebApplicationCacheHostClient; using blink::WebString; -using blink::WebURLRequest; using blink::WebURL; using blink::WebURLResponse; using blink::WebVector; @@ -70,7 +68,6 @@ WebApplicationCacheHostImpl::WebApplicationCacheHostImpl( DCHECK(client && backend); // PlzNavigate: The browser passes the ID to be used. if (appcache_host_id != kAppCacheNoHostId) { - DCHECK(IsBrowserSideNavigationEnabled()); all_hosts()->AddWithID(this, appcache_host_id); host_id_ = appcache_host_id; } else { diff --git a/chromium/content/renderer/blob_storage/OWNERS b/chromium/content/renderer/blob_storage/OWNERS index 471c08e8a01..d04a7d57277 100644 --- a/chromium/content/renderer/blob_storage/OWNERS +++ b/chromium/content/renderer/blob_storage/OWNERS @@ -1 +1,4 @@ dmurph@chromium.org + +# 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 d64895137a7..4d8251069ae 100644 --- a/chromium/content/renderer/browser_plugin/browser_plugin.cc +++ b/chromium/content/renderer/browser_plugin/browser_plugin.cc @@ -136,16 +136,16 @@ bool BrowserPlugin::OnMessageReceived(const IPC::Message& message) { #endif IPC_MESSAGE_HANDLER(BrowserPluginMsg_ShouldAcceptTouchEvents, OnShouldAcceptTouchEvents) - IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetChildFrameSurface, - OnSetChildFrameSurface) + IPC_MESSAGE_HANDLER(BrowserPluginMsg_FirstSurfaceActivation, + OnFirstSurfaceActivation) IPC_END_MESSAGE_MAP() return handled; } -void BrowserPlugin::OnSetChildFrameSurface( +void BrowserPlugin::OnFirstSurfaceActivation( int browser_plugin_instance_id, const viz::SurfaceInfo& surface_info) { - if (!attached() || base::FeatureList::IsEnabled(features::kMash)) + if (!attached() || !features::IsAshInBrowserProcess()) return; if (!enable_surface_synchronization_) { @@ -264,6 +264,10 @@ void BrowserPlugin::SynchronizeVisualProperties() { sent_visual_properties_->screen_space_rect.size() != pending_visual_properties_.screen_space_rect.size(); + bool zoom_changed = + !sent_visual_properties_ || sent_visual_properties_->zoom_level != + pending_visual_properties_.zoom_level; + // Note that the following flag is true if the capture sequence number // actually changed. That is, it is false if we did not have // |sent_visual_properties_|, which is different from the other local flags @@ -274,7 +278,7 @@ void BrowserPlugin::SynchronizeVisualProperties() { pending_visual_properties_.capture_sequence_number; bool synchronized_props_changed = - !sent_visual_properties_ || size_changed || + !sent_visual_properties_ || size_changed || zoom_changed || sent_visual_properties_->screen_info != pending_visual_properties_.screen_info || capture_sequence_number_changed; @@ -316,7 +320,7 @@ void BrowserPlugin::SynchronizeVisualProperties() { sent_visual_properties_ = pending_visual_properties_; #if defined(USE_AURA) - if (features::IsMashEnabled() && mus_embedded_frame_) { + if (!features::IsAshInBrowserProcess() && mus_embedded_frame_) { mus_embedded_frame_->SetWindowBounds(GetLocalSurfaceId(), FrameRectInPixels()); } @@ -390,22 +394,19 @@ void BrowserPlugin::OnSetCursor(int browser_plugin_instance_id, void BrowserPlugin::OnSetMouseLock(int browser_plugin_instance_id, bool enable) { - auto* render_frame = - RenderFrameImpl::FromRoutingID(render_frame_routing_id()); - auto* render_view = static_cast<RenderViewImpl*>( - render_frame ? render_frame->GetRenderView() : nullptr); + RenderWidget* render_widget = GetMainWidget(); if (enable) { - if (mouse_locked_ || !render_view) + if (mouse_locked_ || !render_widget) return; - render_view->mouse_lock_dispatcher()->LockMouse(this); + render_widget->mouse_lock_dispatcher()->LockMouse(this); } else { if (!mouse_locked_) { OnLockMouseACK(false); return; } - if (!render_view) + if (!render_widget) return; - render_view->mouse_lock_dispatcher()->UnlockMouse(this); + render_widget->mouse_lock_dispatcher()->UnlockMouse(this); } } @@ -413,7 +414,7 @@ void BrowserPlugin::OnSetMouseLock(int browser_plugin_instance_id, void BrowserPlugin::OnSetMusEmbedToken( int instance_id, const base::UnguessableToken& embed_token) { - DCHECK(base::FeatureList::IsEnabled(features::kMash)); + DCHECK(!features::IsAshInBrowserProcess()); if (!attached_) { pending_embed_token_ = embed_token; } else { @@ -444,6 +445,20 @@ float BrowserPlugin::GetDeviceScaleFactor() const { return pending_visual_properties_.screen_info.device_scale_factor; } +RenderWidget* BrowserPlugin::GetMainWidget() const { + RenderFrameImpl* frame = + RenderFrameImpl::FromRoutingID(render_frame_routing_id()); + if (frame) { + RenderViewImpl* render_view = + static_cast<RenderViewImpl*>(frame->GetRenderView()); + if (render_view) { + return render_view->GetWidget(); + } + } + + return nullptr; +} + void BrowserPlugin::UpdateInternalInstanceId() { // This is a way to notify observers of our attributes that this plugin is // available in render tree. @@ -475,6 +490,11 @@ void BrowserPlugin::ScreenInfoChanged(const ScreenInfo& screen_info) { SynchronizeVisualProperties(); } +void BrowserPlugin::OnZoomLevelChanged(double zoom_level) { + pending_visual_properties_.zoom_level = zoom_level; + SynchronizeVisualProperties(); +} + void BrowserPlugin::UpdateCaptureSequenceNumber( uint32_t capture_sequence_number) { pending_visual_properties_.capture_sequence_number = capture_sequence_number; @@ -483,12 +503,9 @@ void BrowserPlugin::UpdateCaptureSequenceNumber( bool BrowserPlugin::ShouldGuestBeFocused() const { bool embedder_focused = false; - auto* render_frame = - RenderFrameImpl::FromRoutingID(render_frame_routing_id()); - auto* render_view = static_cast<RenderViewImpl*>( - render_frame ? render_frame->GetRenderView() : nullptr); - if (render_view) - embedder_focused = render_view->has_focus(); + RenderWidget* render_widget = GetMainWidget(); + if (render_widget) + embedder_focused = render_widget->has_focus(); return plugin_focused_ && embedder_focused; } @@ -539,12 +556,9 @@ void BrowserPlugin::Destroy() { container_ = nullptr; // Will be a no-op if the mouse is not currently locked. - auto* render_frame = - RenderFrameImpl::FromRoutingID(render_frame_routing_id()); - auto* render_view = static_cast<RenderViewImpl*>( - render_frame ? render_frame->GetRenderView() : nullptr); - if (render_view) - render_view->mouse_lock_dispatcher()->OnLockTargetDestroyed(this); + RenderWidget* render_widget = GetMainWidget(); + if (render_widget) + render_widget->mouse_lock_dispatcher()->OnLockTargetDestroyed(this); task_runner_->DeleteSoon(FROM_HERE, this); } @@ -847,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(base::FeatureList::IsEnabled(features::kMash)); + DCHECK(!features::IsAshInBrowserProcess()); 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 8ab2c1b82ba..b3091678c58 100644 --- a/chromium/content/renderer/browser_plugin/browser_plugin.h +++ b/chromium/content/renderer/browser_plugin/browser_plugin.h @@ -81,6 +81,8 @@ class CONTENT_EXPORT BrowserPlugin : public blink::WebPlugin, void ScreenInfoChanged(const ScreenInfo& screen_info); + void OnZoomLevelChanged(double zoom_level); + void UpdateCaptureSequenceNumber(uint32_t capture_sequence_number); // Indicates whether the guest should be focused. @@ -112,7 +114,7 @@ class CONTENT_EXPORT BrowserPlugin : public blink::WebPlugin, bool SupportsInputMethod() const override; bool CanProcessDrag() const override; void UpdateAllLifecyclePhases() override {} - void Paint(blink::WebCanvas* canvas, const blink::WebRect& rect) override {} + void Paint(cc::PaintCanvas* canvas, const blink::WebRect& rect) override {} void UpdateGeometry(const blink::WebRect& window_rect, const blink::WebRect& clip_rect, const blink::WebRect& unobscured_rect, @@ -176,6 +178,7 @@ class CONTENT_EXPORT BrowserPlugin : public blink::WebPlugin, } gfx::Rect FrameRectInPixels() const; float GetDeviceScaleFactor() const; + RenderWidget* GetMainWidget() const; const ScreenInfo& screen_info() const { return pending_visual_properties_.screen_info; @@ -201,8 +204,8 @@ class CONTENT_EXPORT BrowserPlugin : public blink::WebPlugin, const gfx::Size& min_size, const gfx::Size& max_size); void OnDisableAutoResize(int browser_plugin_instance_id); - void OnSetChildFrameSurface(int instance_id, - const viz::SurfaceInfo& surface_info); + void OnFirstSurfaceActivation(int instance_id, + const viz::SurfaceInfo& surface_info); void OnSetContentsOpaque(int instance_id, bool opaque); void OnSetCursor(int instance_id, const WebCursor& cursor); void OnSetMouseLock(int instance_id, bool enable); diff --git a/chromium/content/renderer/child_frame_compositing_helper.cc b/chromium/content/renderer/child_frame_compositing_helper.cc index 8ef6f5b20b7..ba7454e3faa 100644 --- a/chromium/content/renderer/child_frame_compositing_helper.cc +++ b/chromium/content/renderer/child_frame_compositing_helper.cc @@ -101,9 +101,6 @@ void ChildFrameCompositingHelper::SetPrimarySurfaceId( void ChildFrameCompositingHelper::SetFallbackSurfaceId( const viz::SurfaceId& surface_id, const gfx::Size& frame_size_in_dip) { - if (fallback_surface_id_ == surface_id) - return; - fallback_surface_id_ = surface_id; if (!surface_layer_) { diff --git a/chromium/content/renderer/child_message_filter.cc b/chromium/content/renderer/child_message_filter.cc deleted file mode 100644 index c212d4835fa..00000000000 --- a/chromium/content/renderer/child_message_filter.cc +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/child_message_filter.h" - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/location.h" -#include "base/macros.h" -#include "base/task_runner.h" -#include "content/child/child_thread_impl.h" -#include "content/child/thread_safe_sender.h" -#include "ipc/message_filter.h" - -namespace content { - -class ChildMessageFilter::Internal : public IPC::MessageFilter { - public: - explicit Internal(ChildMessageFilter* filter) : filter_(filter) {} - - bool OnMessageReceived(const IPC::Message& msg) override { - scoped_refptr<base::TaskRunner> runner = - filter_->OverrideTaskRunnerForMessage(msg); - if (runner.get() && !runner->RunsTasksInCurrentSequence()) { - if (!runner->PostTask( - FROM_HERE, - base::BindOnce( - base::IgnoreResult(&ChildMessageFilter::OnMessageReceived), - filter_, msg))) - filter_->OnStaleMessageReceived(msg); - return true; - } - - return filter_->OnMessageReceived(msg); - } - - private: - ~Internal() override {} - scoped_refptr<ChildMessageFilter> filter_; - - DISALLOW_COPY_AND_ASSIGN(Internal); -}; - -bool ChildMessageFilter::Send(IPC::Message* message) { - return thread_safe_sender_->Send(message); -} - -base::TaskRunner* ChildMessageFilter::OverrideTaskRunnerForMessage( - const IPC::Message& msg) { - return nullptr; -} - -ChildMessageFilter::ChildMessageFilter() - : internal_(nullptr), - thread_safe_sender_(ChildThreadImpl::current()->thread_safe_sender()) {} - -ChildMessageFilter::~ChildMessageFilter() {} - -IPC::MessageFilter* ChildMessageFilter::GetFilter() { - if (!internal_) - internal_ = new Internal(this); - return internal_; -} - -} // namespace content diff --git a/chromium/content/renderer/child_message_filter.h b/chromium/content/renderer/child_message_filter.h deleted file mode 100644 index d02cf3a09d3..00000000000 --- a/chromium/content/renderer/child_message_filter.h +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_CHILD_MESSAGE_FILTER_H_ -#define CONTENT_RENDERER_CHILD_MESSAGE_FILTER_H_ - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "ipc/ipc_sender.h" - -namespace base { -class TaskRunner; -} - -namespace IPC { -class MessageFilter; -} - -namespace content { - -class ThreadSafeSender; - -// A base class for implementing IPC MessageFilter's that run on a different -// thread or TaskRunner than the main thread. -class ChildMessageFilter - : public base::RefCountedThreadSafe<ChildMessageFilter>, - public IPC::Sender { - public: - // IPC::Sender implementation. Can be called on any threads. - bool Send(IPC::Message* message) override; - - // If implementers want to run OnMessageReceived on a different task - // runner it should override this and return the TaskRunner for the message. - // Returning NULL runs OnMessageReceived() on the current IPC thread. - virtual base::TaskRunner* OverrideTaskRunnerForMessage( - const IPC::Message& msg) = 0; - - // If OverrideTaskRunnerForMessage is overriden and returns non-null - // this will be called on the returned TaskRunner. - virtual bool OnMessageReceived(const IPC::Message& msg) = 0; - - // This method is called when WorkerTaskRunner::PostTask() returned false - // for the target thread. Note that there's still a little chance that - // PostTask() returns true but OnMessageReceived() is never called on the - // target thread. By default this does nothing. - virtual void OnStaleMessageReceived(const IPC::Message& msg) {} - - protected: - ChildMessageFilter(); - ~ChildMessageFilter() override; - - private: - class Internal; - friend class ChildThreadImpl; - friend class RenderThreadImpl; - friend class WorkerThread; - - friend class base::RefCountedThreadSafe<ChildMessageFilter>; - - IPC::MessageFilter* GetFilter(); - - // This implements IPC::MessageFilter to hide the actual filter methods from - // child classes. - Internal* internal_; - - scoped_refptr<ThreadSafeSender> thread_safe_sender_; - - DISALLOW_COPY_AND_ASSIGN(ChildMessageFilter); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_CHILD_MESSAGE_FILTER_H_ diff --git a/chromium/content/renderer/clipboard_utils.cc b/chromium/content/renderer/clipboard_utils.cc deleted file mode 100644 index 8324300097b..00000000000 --- a/chromium/content/renderer/clipboard_utils.cc +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/clipboard_utils.h" - -#include "base/strings/utf_string_conversions.h" -#include "net/base/escape.h" -#include "third_party/blink/public/platform/web_string.h" -#include "third_party/blink/public/platform/web_url.h" - -namespace content { - -std::string URLToImageMarkup(const blink::WebURL& url, - const blink::WebString& title) { - std::string markup("<img src=\""); - markup.append(net::EscapeForHTML(url.GetString().Utf8())); - markup.append("\""); - if (!title.IsEmpty()) { - markup.append(" alt=\""); - markup.append(net::EscapeForHTML(title.Utf8())); - markup.append("\""); - } - markup.append("/>"); - return markup; -} - -} // namespace content diff --git a/chromium/content/renderer/clipboard_utils.h b/chromium/content/renderer/clipboard_utils.h deleted file mode 100644 index 069488c81fb..00000000000 --- a/chromium/content/renderer/clipboard_utils.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_RENDERER_CLIPBOARD_UTILS_H_ -#define CONTENT_RENDERER_CLIPBOARD_UTILS_H_ - -#include <string> - -#include "content/common/content_export.h" - -namespace blink { -class WebString; -class WebURL; -} - -namespace content { - -CONTENT_EXPORT std::string URLToImageMarkup(const blink::WebURL& url, - const blink::WebString& title); - -} // namespace content - -#endif // CONTENT_RENDERER_CLIPBOARD_UTILS_H_ diff --git a/chromium/content/renderer/cursor_utils.cc b/chromium/content/renderer/cursor_utils.cc index ccdb7bceddf..523fd5361cd 100644 --- a/chromium/content/renderer/cursor_utils.cc +++ b/chromium/content/renderer/cursor_utils.cc @@ -30,7 +30,7 @@ void InitializeCursorFromWebCursorInfo(WebCursor* cursor, cursor_info.type = web_cursor_info.type; cursor_info.image_scale_factor = web_cursor_info.image_scale_factor; cursor_info.hotspot = web_cursor_info.hot_spot; - cursor_info.custom_image = web_cursor_info.custom_image.GetSkBitmap(); + cursor_info.custom_image = web_cursor_info.custom_image; cursor->InitFromCursorInfo(cursor_info); } diff --git a/chromium/content/renderer/device_sensors/OWNERS b/chromium/content/renderer/device_sensors/OWNERS deleted file mode 100644 index 7b1e4f284f7..00000000000 --- a/chromium/content/renderer/device_sensors/OWNERS +++ /dev/null @@ -1,4 +0,0 @@ -timvolodine@chromium.org - -# COMPONENT: Blink>Sensor>DeviceOrientation -# TEAM: device-dev@chromium.org diff --git a/chromium/content/renderer/device_sensors/device_motion_event_pump.cc b/chromium/content/renderer/device_sensors/device_motion_event_pump.cc deleted file mode 100644 index e19341cd04f..00000000000 --- a/chromium/content/renderer/device_sensors/device_motion_event_pump.cc +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/device_sensors/device_motion_event_pump.h" - -#include <cmath> - -#include "base/logging.h" -#include "content/public/renderer/render_frame.h" -#include "content/public/renderer/render_thread.h" -#include "content/renderer/render_thread_impl.h" -#include "services/device/public/cpp/generic_sensor/motion_data.h" -#include "services/device/public/mojom/sensor.mojom.h" -#include "services/service_manager/public/cpp/interface_provider.h" -#include "ui/gfx/geometry/angle_conversions.h" - -namespace content { - -template class DeviceSensorEventPump<blink::WebDeviceMotionListener>; - -DeviceMotionEventPump::DeviceMotionEventPump(RenderThread* thread) - : DeviceSensorEventPump<blink::WebDeviceMotionListener>(thread), - accelerometer_(this, device::mojom::SensorType::ACCELEROMETER), - linear_acceleration_sensor_( - this, - device::mojom::SensorType::LINEAR_ACCELERATION), - gyroscope_(this, device::mojom::SensorType::GYROSCOPE) {} - -DeviceMotionEventPump::~DeviceMotionEventPump() {} - -void DeviceMotionEventPump::SendStartMessage() { - // When running layout tests, those observers should not listen to the - // actual hardware changes. In order to make that happen, don't connect - // the other end of the mojo pipe to anything. - // - // TODO(sammc): Remove this when JS layout test support for shared buffers - // is ready and the layout tests are converted to use that for mocking. - // https://crbug.com/774183 - if (!RenderThreadImpl::current() || - RenderThreadImpl::current()->layout_test_mode()) { - return; - } - - SendStartMessageImpl(); -} - -void DeviceMotionEventPump::SendStopMessage() { - // SendStopMessage() gets called both when the page visibility changes and if - // all device motion event listeners are unregistered. Since removing the - // event listener is more rare than the page visibility changing, - // Sensor::Suspend() is used to optimize this case for not doing extra work. - - accelerometer_.Stop(); - linear_acceleration_sensor_.Stop(); - gyroscope_.Stop(); -} - -void DeviceMotionEventPump::SendFakeDataForTesting(void* fake_data) { - if (!listener()) - return; - - device::MotionData data = *static_cast<device::MotionData*>(fake_data); - listener()->DidChangeDeviceMotion(data); -} - -void DeviceMotionEventPump::FireEvent() { - device::MotionData data; - // The device orientation spec states that interval should be in milliseconds. - // https://w3c.github.io/deviceorientation/spec-source-orientation.html#devicemotion - data.interval = kDefaultPumpDelayMicroseconds / 1000; - - DCHECK(listener()); - - GetDataFromSharedMemory(&data); - - if (ShouldFireEvent(data)) - listener()->DidChangeDeviceMotion(data); -} - -void DeviceMotionEventPump::SendStartMessageImpl() { - if (!sensor_provider_) { - RenderFrame* const render_frame = GetRenderFrame(); - if (!render_frame) - return; - - render_frame->GetRemoteInterfaces()->GetInterface( - mojo::MakeRequest(&sensor_provider_)); - sensor_provider_.set_connection_error_handler( - base::BindOnce(&DeviceSensorEventPump::HandleSensorProviderError, - base::Unretained(this))); - } - - accelerometer_.Start(sensor_provider_.get()); - linear_acceleration_sensor_.Start(sensor_provider_.get()); - gyroscope_.Start(sensor_provider_.get()); -} - -bool DeviceMotionEventPump::SensorsReadyOrErrored() const { - return accelerometer_.ReadyOrErrored() && - linear_acceleration_sensor_.ReadyOrErrored() && - gyroscope_.ReadyOrErrored(); -} - -void DeviceMotionEventPump::GetDataFromSharedMemory(device::MotionData* data) { - // "Active" here means that sensor has been initialized and is either ready - // or not available. - bool accelerometer_active = true; - bool linear_acceleration_sensor_active = true; - bool gyroscope_active = true; - - if (accelerometer_.SensorReadingCouldBeRead() && - (accelerometer_active = accelerometer_.reading.timestamp() != 0.0)) { - data->acceleration_including_gravity_x = accelerometer_.reading.accel.x; - data->acceleration_including_gravity_y = accelerometer_.reading.accel.y; - data->acceleration_including_gravity_z = accelerometer_.reading.accel.z; - data->has_acceleration_including_gravity_x = - !std::isnan(accelerometer_.reading.accel.x.value()); - data->has_acceleration_including_gravity_y = - !std::isnan(accelerometer_.reading.accel.y.value()); - data->has_acceleration_including_gravity_z = - !std::isnan(accelerometer_.reading.accel.z.value()); - } - - if (linear_acceleration_sensor_.SensorReadingCouldBeRead() && - (linear_acceleration_sensor_active = - linear_acceleration_sensor_.reading.timestamp() != 0.0)) { - data->acceleration_x = linear_acceleration_sensor_.reading.accel.x; - data->acceleration_y = linear_acceleration_sensor_.reading.accel.y; - data->acceleration_z = linear_acceleration_sensor_.reading.accel.z; - data->has_acceleration_x = - !std::isnan(linear_acceleration_sensor_.reading.accel.x.value()); - data->has_acceleration_y = - !std::isnan(linear_acceleration_sensor_.reading.accel.y.value()); - data->has_acceleration_z = - !std::isnan(linear_acceleration_sensor_.reading.accel.z.value()); - } - - if (gyroscope_.SensorReadingCouldBeRead() && - (gyroscope_active = gyroscope_.reading.timestamp() != 0.0)) { - data->rotation_rate_alpha = gfx::RadToDeg(gyroscope_.reading.gyro.x); - data->rotation_rate_beta = gfx::RadToDeg(gyroscope_.reading.gyro.y); - data->rotation_rate_gamma = gfx::RadToDeg(gyroscope_.reading.gyro.z); - data->has_rotation_rate_alpha = - !std::isnan(gyroscope_.reading.gyro.x.value()); - data->has_rotation_rate_beta = - !std::isnan(gyroscope_.reading.gyro.y.value()); - data->has_rotation_rate_gamma = - !std::isnan(gyroscope_.reading.gyro.z.value()); - } - - data->all_available_sensors_are_active = accelerometer_active && - linear_acceleration_sensor_active && - gyroscope_active; -} // namespace content - -bool DeviceMotionEventPump::ShouldFireEvent( - const device::MotionData& data) const { - return data.all_available_sensors_are_active; -} - -} // namespace content diff --git a/chromium/content/renderer/device_sensors/device_motion_event_pump.h b/chromium/content/renderer/device_sensors/device_motion_event_pump.h deleted file mode 100644 index e7bb8e6026e..00000000000 --- a/chromium/content/renderer/device_sensors/device_motion_event_pump.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_DEVICE_SENSORS_DEVICE_MOTION_EVENT_PUMP_H_ -#define CONTENT_RENDERER_DEVICE_SENSORS_DEVICE_MOTION_EVENT_PUMP_H_ - -#include "base/macros.h" -#include "content/renderer/device_sensors/device_sensor_event_pump.h" -#include "third_party/blink/public/platform/modules/device_orientation/web_device_motion_listener.h" - -namespace device { -class MotionData; -} - -namespace content { - -class RenderThread; - -class CONTENT_EXPORT DeviceMotionEventPump - : public DeviceSensorEventPump<blink::WebDeviceMotionListener> { - public: - explicit DeviceMotionEventPump(RenderThread* thread); - ~DeviceMotionEventPump() override; - - // PlatformEventObserver: - void SendStartMessage() override; - void SendStopMessage() override; - void SendFakeDataForTesting(void* fake_data) override; - - protected: - // DeviceSensorEventPump: - void FireEvent() override; - - void SendStartMessageImpl(); - - SensorEntry accelerometer_; - SensorEntry linear_acceleration_sensor_; - SensorEntry gyroscope_; - - private: - friend class DeviceMotionEventPumpTest; - - // DeviceSensorEventPump: - bool SensorsReadyOrErrored() const override; - - void GetDataFromSharedMemory(device::MotionData* data); - - bool ShouldFireEvent(const device::MotionData& data) const; - - DISALLOW_COPY_AND_ASSIGN(DeviceMotionEventPump); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_DEVICE_SENSORS_DEVICE_MOTION_EVENT_PUMP_H_ diff --git a/chromium/content/renderer/device_sensors/device_motion_event_pump_unittest.cc b/chromium/content/renderer/device_sensors/device_motion_event_pump_unittest.cc deleted file mode 100644 index 2d35111465a..00000000000 --- a/chromium/content/renderer/device_sensors/device_motion_event_pump_unittest.cc +++ /dev/null @@ -1,433 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/device_sensors/device_motion_event_pump.h" - -#include <string.h> - -#include <memory> - -#include "base/macros.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "base/time/time.h" -#include "content/public/test/test_utils.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "services/device/public/cpp/generic_sensor/motion_data.h" -#include "services/device/public/cpp/test/fake_sensor_and_provider.h" -#include "services/device/public/mojom/sensor.mojom.h" -#include "services/device/public/mojom/sensor_provider.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/public/platform/modules/device_orientation/web_device_motion_listener.h" -#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" -#include "ui/gfx/geometry/angle_conversions.h" - -namespace content { - -using device::FakeSensorProvider; - -class MockDeviceMotionListener : public blink::WebDeviceMotionListener { - public: - MockDeviceMotionListener() - : did_change_device_motion_(false), number_of_events_(0) { - memset(&data_, 0, sizeof(data_)); - } - ~MockDeviceMotionListener() override {} - - void DidChangeDeviceMotion(const device::MotionData& data) override { - memcpy(&data_, &data, sizeof(data)); - did_change_device_motion_ = true; - ++number_of_events_; - } - - bool did_change_device_motion() const { - return did_change_device_motion_; - } - - int number_of_events() const { return number_of_events_; } - - const device::MotionData& data() const { return data_; } - - private: - bool did_change_device_motion_; - int number_of_events_; - device::MotionData data_; - - DISALLOW_COPY_AND_ASSIGN(MockDeviceMotionListener); -}; - -class DeviceMotionEventPumpForTesting : public DeviceMotionEventPump { - public: - DeviceMotionEventPumpForTesting() : DeviceMotionEventPump(nullptr) {} - ~DeviceMotionEventPumpForTesting() override {} - - // DeviceMotionEventPump: - void SendStartMessage() override { - DeviceMotionEventPump::SendStartMessageImpl(); - } - - int pump_delay_microseconds() const { return kDefaultPumpDelayMicroseconds; } - - private: - DISALLOW_COPY_AND_ASSIGN(DeviceMotionEventPumpForTesting); -}; - -class DeviceMotionEventPumpTest : public testing::Test { - public: - DeviceMotionEventPumpTest() = default; - - protected: - void SetUp() override { - motion_pump_.reset(new DeviceMotionEventPumpForTesting()); - device::mojom::SensorProviderPtr sensor_provider_ptr; - sensor_provider_.Bind(mojo::MakeRequest(&sensor_provider_ptr)); - motion_pump_->SetSensorProviderForTesting(std::move(sensor_provider_ptr)); - - listener_.reset(new MockDeviceMotionListener); - - ExpectAllThreeSensorsStateToBe( - DeviceMotionEventPump::SensorState::NOT_INITIALIZED); - EXPECT_EQ(DeviceMotionEventPump::PumpState::STOPPED, - motion_pump()->GetPumpStateForTesting()); - } - - void FireEvent() { motion_pump_->FireEvent(); } - - void ExpectAccelerometerStateToBe( - DeviceMotionEventPump::SensorState expected_sensor_state) { - EXPECT_EQ(expected_sensor_state, motion_pump_->accelerometer_.sensor_state); - } - - void ExpectLinearAccelerationSensorStateToBe( - DeviceMotionEventPump::SensorState expected_sensor_state) { - EXPECT_EQ(expected_sensor_state, - motion_pump_->linear_acceleration_sensor_.sensor_state); - } - - void ExpectGyroscopeStateToBe( - DeviceMotionEventPump::SensorState expected_sensor_state) { - EXPECT_EQ(expected_sensor_state, motion_pump_->gyroscope_.sensor_state); - } - - void ExpectAllThreeSensorsStateToBe( - DeviceMotionEventPump::SensorState expected_sensor_state) { - ExpectAccelerometerStateToBe(expected_sensor_state); - ExpectLinearAccelerationSensorStateToBe(expected_sensor_state); - ExpectGyroscopeStateToBe(expected_sensor_state); - } - - DeviceMotionEventPumpForTesting* motion_pump() { return motion_pump_.get(); } - - MockDeviceMotionListener* listener() { return listener_.get(); } - - FakeSensorProvider* sensor_provider() { return &sensor_provider_; } - - private: - base::MessageLoop loop_; - std::unique_ptr<DeviceMotionEventPumpForTesting> motion_pump_; - std::unique_ptr<MockDeviceMotionListener> listener_; - FakeSensorProvider sensor_provider_; - - DISALLOW_COPY_AND_ASSIGN(DeviceMotionEventPumpTest); -}; - -TEST_F(DeviceMotionEventPumpTest, MultipleStartAndStopWithWait) { - motion_pump()->Start(listener()); - base::RunLoop().RunUntilIdle(); - - ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::ACTIVE); - EXPECT_EQ(DeviceMotionEventPump::PumpState::RUNNING, - motion_pump()->GetPumpStateForTesting()); - - motion_pump()->Stop(); - base::RunLoop().RunUntilIdle(); - - ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED); - EXPECT_EQ(DeviceMotionEventPump::PumpState::STOPPED, - motion_pump()->GetPumpStateForTesting()); - - motion_pump()->Start(listener()); - base::RunLoop().RunUntilIdle(); - - ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::ACTIVE); - EXPECT_EQ(DeviceMotionEventPump::PumpState::RUNNING, - motion_pump()->GetPumpStateForTesting()); - - motion_pump()->Stop(); - base::RunLoop().RunUntilIdle(); - - ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED); - EXPECT_EQ(DeviceMotionEventPump::PumpState::STOPPED, - motion_pump()->GetPumpStateForTesting()); -} - -TEST_F(DeviceMotionEventPumpTest, CallStop) { - motion_pump()->Stop(); - base::RunLoop().RunUntilIdle(); - - ExpectAllThreeSensorsStateToBe( - DeviceMotionEventPump::SensorState::NOT_INITIALIZED); -} - -TEST_F(DeviceMotionEventPumpTest, CallStartAndStop) { - motion_pump()->Start(listener()); - motion_pump()->Stop(); - base::RunLoop().RunUntilIdle(); - - ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED); -} - -TEST_F(DeviceMotionEventPumpTest, CallStartMultipleTimes) { - motion_pump()->Start(listener()); - motion_pump()->Start(listener()); - motion_pump()->Stop(); - base::RunLoop().RunUntilIdle(); - - ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED); -} - -TEST_F(DeviceMotionEventPumpTest, CallStopMultipleTimes) { - motion_pump()->Start(listener()); - motion_pump()->Stop(); - motion_pump()->Stop(); - base::RunLoop().RunUntilIdle(); - - ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED); -} - -// Test multiple DeviceSensorEventPump::Start() calls only bind sensor once. -TEST_F(DeviceMotionEventPumpTest, SensorOnlyBindOnce) { - motion_pump()->Start(listener()); - motion_pump()->Stop(); - motion_pump()->Start(listener()); - base::RunLoop().RunUntilIdle(); - - ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::ACTIVE); - - motion_pump()->Stop(); - - ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED); -} - -TEST_F(DeviceMotionEventPumpTest, AllSensorsAreActive) { - motion_pump()->Start(listener()); - base::RunLoop().RunUntilIdle(); - - ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::ACTIVE); - - sensor_provider()->UpdateAccelerometerData(1, 2, 3); - sensor_provider()->UpdateLinearAccelerationSensorData(4, 5, 6); - sensor_provider()->UpdateGyroscopeData(7, 8, 9); - - FireEvent(); - - device::MotionData received_data = listener()->data(); - EXPECT_TRUE(listener()->did_change_device_motion()); - - EXPECT_TRUE(received_data.has_acceleration_including_gravity_x); - EXPECT_EQ(1, received_data.acceleration_including_gravity_x); - EXPECT_TRUE(received_data.has_acceleration_including_gravity_y); - EXPECT_EQ(2, received_data.acceleration_including_gravity_y); - EXPECT_TRUE(received_data.has_acceleration_including_gravity_z); - EXPECT_EQ(3, received_data.acceleration_including_gravity_z); - - EXPECT_TRUE(received_data.has_acceleration_x); - EXPECT_EQ(4, received_data.acceleration_x); - EXPECT_TRUE(received_data.has_acceleration_y); - EXPECT_EQ(5, received_data.acceleration_y); - EXPECT_TRUE(received_data.has_acceleration_z); - EXPECT_EQ(6, received_data.acceleration_z); - - EXPECT_TRUE(received_data.has_rotation_rate_alpha); - EXPECT_EQ(gfx::RadToDeg(7.0), received_data.rotation_rate_alpha); - EXPECT_TRUE(received_data.has_rotation_rate_beta); - EXPECT_EQ(gfx::RadToDeg(8.0), received_data.rotation_rate_beta); - EXPECT_TRUE(received_data.has_rotation_rate_gamma); - EXPECT_EQ(gfx::RadToDeg(9.0), received_data.rotation_rate_gamma); - - motion_pump()->Stop(); - - ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED); -} - -TEST_F(DeviceMotionEventPumpTest, TwoSensorsAreActive) { - sensor_provider()->set_linear_acceleration_sensor_is_available(false); - - motion_pump()->Start(listener()); - base::RunLoop().RunUntilIdle(); - - ExpectAccelerometerStateToBe(DeviceMotionEventPump::SensorState::ACTIVE); - ExpectLinearAccelerationSensorStateToBe( - DeviceMotionEventPump::SensorState::NOT_INITIALIZED); - ExpectGyroscopeStateToBe(DeviceMotionEventPump::SensorState::ACTIVE); - - sensor_provider()->UpdateAccelerometerData(1, 2, 3); - sensor_provider()->UpdateGyroscopeData(7, 8, 9); - - FireEvent(); - - device::MotionData received_data = listener()->data(); - EXPECT_TRUE(listener()->did_change_device_motion()); - - EXPECT_TRUE(received_data.has_acceleration_including_gravity_x); - EXPECT_EQ(1, received_data.acceleration_including_gravity_x); - EXPECT_TRUE(received_data.has_acceleration_including_gravity_y); - EXPECT_EQ(2, received_data.acceleration_including_gravity_y); - EXPECT_TRUE(received_data.has_acceleration_including_gravity_z); - EXPECT_EQ(3, received_data.acceleration_including_gravity_z); - - EXPECT_FALSE(received_data.has_acceleration_x); - EXPECT_FALSE(received_data.has_acceleration_y); - EXPECT_FALSE(received_data.has_acceleration_z); - - EXPECT_TRUE(received_data.has_rotation_rate_alpha); - EXPECT_EQ(gfx::RadToDeg(7.0), received_data.rotation_rate_alpha); - EXPECT_TRUE(received_data.has_rotation_rate_beta); - EXPECT_EQ(gfx::RadToDeg(8.0), received_data.rotation_rate_beta); - EXPECT_TRUE(received_data.has_rotation_rate_gamma); - EXPECT_EQ(gfx::RadToDeg(9.0), received_data.rotation_rate_gamma); - - motion_pump()->Stop(); - - ExpectAccelerometerStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED); - ExpectLinearAccelerationSensorStateToBe( - DeviceMotionEventPump::SensorState::NOT_INITIALIZED); - ExpectGyroscopeStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED); -} - -TEST_F(DeviceMotionEventPumpTest, SomeSensorDataFieldsNotAvailable) { - motion_pump()->Start(listener()); - base::RunLoop().RunUntilIdle(); - - ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::ACTIVE); - - sensor_provider()->UpdateAccelerometerData(NAN, 2, 3); - sensor_provider()->UpdateLinearAccelerationSensorData(4, NAN, 6); - sensor_provider()->UpdateGyroscopeData(7, 8, NAN); - - FireEvent(); - - device::MotionData received_data = listener()->data(); - EXPECT_TRUE(listener()->did_change_device_motion()); - - EXPECT_FALSE(received_data.has_acceleration_including_gravity_x); - EXPECT_TRUE(received_data.has_acceleration_including_gravity_y); - EXPECT_EQ(2, received_data.acceleration_including_gravity_y); - EXPECT_TRUE(received_data.has_acceleration_including_gravity_z); - EXPECT_EQ(3, received_data.acceleration_including_gravity_z); - - EXPECT_TRUE(received_data.has_acceleration_x); - EXPECT_EQ(4, received_data.acceleration_x); - EXPECT_FALSE(received_data.has_acceleration_y); - EXPECT_TRUE(received_data.has_acceleration_z); - EXPECT_EQ(6, received_data.acceleration_z); - - EXPECT_TRUE(received_data.has_rotation_rate_alpha); - EXPECT_EQ(gfx::RadToDeg(7.0), received_data.rotation_rate_alpha); - EXPECT_TRUE(received_data.has_rotation_rate_beta); - EXPECT_EQ(gfx::RadToDeg(8.0), received_data.rotation_rate_beta); - EXPECT_FALSE(received_data.has_rotation_rate_gamma); - - motion_pump()->Stop(); - - ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED); -} - -TEST_F(DeviceMotionEventPumpTest, FireAllNullEvent) { - // No active sensors. - sensor_provider()->set_accelerometer_is_available(false); - sensor_provider()->set_linear_acceleration_sensor_is_available(false); - sensor_provider()->set_gyroscope_is_available(false); - - motion_pump()->Start(listener()); - base::RunLoop().RunUntilIdle(); - - ExpectAllThreeSensorsStateToBe( - DeviceMotionEventPump::SensorState::NOT_INITIALIZED); - - FireEvent(); - - device::MotionData received_data = listener()->data(); - EXPECT_TRUE(listener()->did_change_device_motion()); - - EXPECT_FALSE(received_data.has_acceleration_x); - EXPECT_FALSE(received_data.has_acceleration_y); - EXPECT_FALSE(received_data.has_acceleration_z); - - EXPECT_FALSE(received_data.has_acceleration_including_gravity_x); - EXPECT_FALSE(received_data.has_acceleration_including_gravity_y); - EXPECT_FALSE(received_data.has_acceleration_including_gravity_z); - - EXPECT_FALSE(received_data.has_rotation_rate_alpha); - EXPECT_FALSE(received_data.has_rotation_rate_beta); - EXPECT_FALSE(received_data.has_rotation_rate_gamma); - - motion_pump()->Stop(); - - ExpectAllThreeSensorsStateToBe( - DeviceMotionEventPump::SensorState::NOT_INITIALIZED); -} - -TEST_F(DeviceMotionEventPumpTest, - NotFireEventWhenSensorReadingTimeStampIsZero) { - motion_pump()->Start(listener()); - base::RunLoop().RunUntilIdle(); - - ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::ACTIVE); - - FireEvent(); - EXPECT_FALSE(listener()->did_change_device_motion()); - - sensor_provider()->UpdateAccelerometerData(1, 2, 3); - FireEvent(); - EXPECT_FALSE(listener()->did_change_device_motion()); - - sensor_provider()->UpdateLinearAccelerationSensorData(4, 5, 6); - FireEvent(); - EXPECT_FALSE(listener()->did_change_device_motion()); - - sensor_provider()->UpdateGyroscopeData(7, 8, 9); - FireEvent(); - // Event is fired only after all the available sensors have data. - EXPECT_TRUE(listener()->did_change_device_motion()); - - motion_pump()->Stop(); - - ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED); -} - -// Confirm that the frequency of pumping events is not greater than 60Hz. -// A rate above 60Hz would allow for the detection of keystrokes. -// (crbug.com/421691) -TEST_F(DeviceMotionEventPumpTest, PumpThrottlesEventRate) { - // Confirm that the delay for pumping events is 60 Hz. - EXPECT_GE(60, base::Time::kMicrosecondsPerSecond / - motion_pump()->pump_delay_microseconds()); - - motion_pump()->Start(listener()); - base::RunLoop().RunUntilIdle(); - - ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::ACTIVE); - - sensor_provider()->UpdateAccelerometerData(1, 2, 3); - sensor_provider()->UpdateLinearAccelerationSensorData(4, 5, 6); - sensor_provider()->UpdateGyroscopeData(7, 8, 9); - - blink::scheduler::GetSingleThreadTaskRunnerForTesting()->PostDelayedTask( - FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated(), - base::TimeDelta::FromMilliseconds(100)); - base::RunLoop().Run(); - motion_pump()->Stop(); - - ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED); - - // Check that the blink::WebDeviceMotionListener does not receive excess - // events. - EXPECT_TRUE(listener()->did_change_device_motion()); - EXPECT_GE(6, listener()->number_of_events()); -} - -} // namespace content diff --git a/chromium/content/renderer/device_sensors/device_orientation_event_pump.cc b/chromium/content/renderer/device_sensors/device_orientation_event_pump.cc deleted file mode 100644 index f2c7d89f96b..00000000000 --- a/chromium/content/renderer/device_sensors/device_orientation_event_pump.cc +++ /dev/null @@ -1,235 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/device_sensors/device_orientation_event_pump.h" - -#include <cmath> - -#include "base/logging.h" -#include "content/public/renderer/render_frame.h" -#include "content/public/renderer/render_thread.h" -#include "content/renderer/render_thread_impl.h" -#include "services/device/public/mojom/sensor.mojom.h" -#include "services/service_manager/public/cpp/interface_provider.h" - -namespace { - -bool IsAngleDifferentThreshold(bool has_angle1, - double angle1, - bool has_angle2, - double angle2) { - if (has_angle1 != has_angle2) - return true; - - return (has_angle1 && - std::fabs(angle1 - angle2) >= - content::DeviceOrientationEventPump::kOrientationThreshold); -} - -bool IsSignificantlyDifferent(const device::OrientationData& data1, - const device::OrientationData& data2) { - return IsAngleDifferentThreshold(data1.has_alpha, data1.alpha, - data2.has_alpha, data2.alpha) || - IsAngleDifferentThreshold(data1.has_beta, data1.beta, data2.has_beta, - data2.beta) || - IsAngleDifferentThreshold(data1.has_gamma, data1.gamma, - data2.has_gamma, data2.gamma); -} - -} // namespace - -namespace content { - -template class DeviceSensorEventPump<blink::WebDeviceOrientationListener>; - -const double DeviceOrientationEventPump::kOrientationThreshold = 0.1; - -DeviceOrientationEventPump::DeviceOrientationEventPump(RenderThread* thread, - bool absolute) - : DeviceSensorEventPump<blink::WebDeviceOrientationListener>(thread), - relative_orientation_sensor_( - this, - device::mojom::SensorType::RELATIVE_ORIENTATION_EULER_ANGLES), - absolute_orientation_sensor_( - this, - device::mojom::SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES), - absolute_(absolute), - fall_back_to_absolute_orientation_sensor_(!absolute) {} - -DeviceOrientationEventPump::~DeviceOrientationEventPump() {} - -void DeviceOrientationEventPump::SendStartMessage() { - // When running layout tests, those observers should not listen to the - // actual hardware changes. In order to make that happen, don't connect - // the other end of the mojo pipe to anything. - // - // TODO(sammc): Remove this when JS layout test support for shared buffers - // is ready and the layout tests are converted to use that for mocking. - // https://crbug.com/774183 - if (!RenderThreadImpl::current() || - RenderThreadImpl::current()->layout_test_mode()) { - return; - } - - SendStartMessageImpl(); -} - -void DeviceOrientationEventPump::SendStopMessage() { - // SendStopMessage() gets called both when the page visibility changes and if - // all device orientation event listeners are unregistered. Since removing - // the event listener is more rare than the page visibility changing, - // Sensor::Suspend() is used to optimize this case for not doing extra work. - - relative_orientation_sensor_.Stop(); - // This is needed in case we fallback to using the absolute orientation - // sensor. In this case, the relative orientation sensor is marked as - // SensorState::SHOULD_SUSPEND, and if the relative orientation sensor - // is not available, the absolute orientation sensor should also be marked as - // SensorState::SHOULD_SUSPEND, but only after the - // absolute_orientation_sensor_.Start() is called for initializing - // the absolute orientation sensor in - // DeviceOrientationEventPump::DidStartIfPossible(). - if (relative_orientation_sensor_.sensor_state == - SensorState::SHOULD_SUSPEND && - fall_back_to_absolute_orientation_sensor_) { - should_suspend_absolute_orientation_sensor_ = true; - } - - absolute_orientation_sensor_.Stop(); -} - -void DeviceOrientationEventPump::SendFakeDataForTesting(void* fake_data) { - if (!listener()) - return; - - device::OrientationData data = - *static_cast<device::OrientationData*>(fake_data); - listener()->DidChangeDeviceOrientation(data); -} - -void DeviceOrientationEventPump::FireEvent() { - device::OrientationData data; - - DCHECK(listener()); - - GetDataFromSharedMemory(&data); - - if (ShouldFireEvent(data)) { - data_ = data; - listener()->DidChangeDeviceOrientation(data); - } -} - -void DeviceOrientationEventPump::DidStartIfPossible() { - if (!absolute_ && !relative_orientation_sensor_.sensor && - fall_back_to_absolute_orientation_sensor_ && sensor_provider_) { - // When relative orientation sensor is not available fall back to using - // the absolute orientation sensor but only on the first failure. - fall_back_to_absolute_orientation_sensor_ = false; - absolute_orientation_sensor_.Start(sensor_provider_.get()); - if (should_suspend_absolute_orientation_sensor_) { - // The absolute orientation sensor needs to be marked as - // SensorState::SUSPENDED when it is successfully initialized. - absolute_orientation_sensor_.sensor_state = SensorState::SHOULD_SUSPEND; - should_suspend_absolute_orientation_sensor_ = false; - } - return; - } - DeviceSensorEventPump::DidStartIfPossible(); -} - -void DeviceOrientationEventPump::SendStartMessageImpl() { - if (!sensor_provider_) { - RenderFrame* const render_frame = GetRenderFrame(); - if (!render_frame) - return; - - render_frame->GetRemoteInterfaces()->GetInterface( - mojo::MakeRequest(&sensor_provider_)); - sensor_provider_.set_connection_error_handler( - base::BindOnce(&DeviceSensorEventPump::HandleSensorProviderError, - base::Unretained(this))); - } - - if (absolute_) { - absolute_orientation_sensor_.Start(sensor_provider_.get()); - } else { - fall_back_to_absolute_orientation_sensor_ = true; - should_suspend_absolute_orientation_sensor_ = false; - relative_orientation_sensor_.Start(sensor_provider_.get()); - } -} - -bool DeviceOrientationEventPump::SensorsReadyOrErrored() const { - if (!relative_orientation_sensor_.ReadyOrErrored() || - !absolute_orientation_sensor_.ReadyOrErrored()) { - return false; - } - - // At most one sensor can be successfully initialized. - DCHECK(!relative_orientation_sensor_.sensor || - !absolute_orientation_sensor_.sensor); - - return true; -} - -void DeviceOrientationEventPump::GetDataFromSharedMemory( - device::OrientationData* data) { - data->all_available_sensors_are_active = true; - - if (!absolute_ && relative_orientation_sensor_.SensorReadingCouldBeRead()) { - // For DeviceOrientation Event, this provides relative orientation data. - data->all_available_sensors_are_active = - relative_orientation_sensor_.reading.timestamp() != 0.0; - if (!data->all_available_sensors_are_active) - return; - data->alpha = relative_orientation_sensor_.reading.orientation_euler.z; - data->beta = relative_orientation_sensor_.reading.orientation_euler.x; - data->gamma = relative_orientation_sensor_.reading.orientation_euler.y; - data->has_alpha = !std::isnan( - relative_orientation_sensor_.reading.orientation_euler.z.value()); - data->has_beta = !std::isnan( - relative_orientation_sensor_.reading.orientation_euler.x.value()); - data->has_gamma = !std::isnan( - relative_orientation_sensor_.reading.orientation_euler.y.value()); - data->absolute = false; - } else if (absolute_orientation_sensor_.SensorReadingCouldBeRead()) { - // For DeviceOrientationAbsolute Event, this provides absolute orientation - // data. - // - // For DeviceOrientation Event, this provides absolute orientation data if - // relative orientation data is not available. - data->all_available_sensors_are_active = - absolute_orientation_sensor_.reading.timestamp() != 0.0; - if (!data->all_available_sensors_are_active) - return; - data->alpha = absolute_orientation_sensor_.reading.orientation_euler.z; - data->beta = absolute_orientation_sensor_.reading.orientation_euler.x; - data->gamma = absolute_orientation_sensor_.reading.orientation_euler.y; - data->has_alpha = !std::isnan( - absolute_orientation_sensor_.reading.orientation_euler.z.value()); - data->has_beta = !std::isnan( - absolute_orientation_sensor_.reading.orientation_euler.x.value()); - data->has_gamma = !std::isnan( - absolute_orientation_sensor_.reading.orientation_euler.y.value()); - data->absolute = true; - } else { - data->absolute = absolute_; - } -} - -bool DeviceOrientationEventPump::ShouldFireEvent( - const device::OrientationData& data) const { - if (!data.all_available_sensors_are_active) - return false; - - if (!data.has_alpha && !data.has_beta && !data.has_gamma) { - // no data can be provided, this is an all-null event. - return true; - } - - return IsSignificantlyDifferent(data_, data); -} - -} // namespace content diff --git a/chromium/content/renderer/device_sensors/device_orientation_event_pump.h b/chromium/content/renderer/device_sensors/device_orientation_event_pump.h deleted file mode 100644 index 6ec081eb5e4..00000000000 --- a/chromium/content/renderer/device_sensors/device_orientation_event_pump.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_DEVICE_SENSORS_DEVICE_ORIENTATION_EVENT_PUMP_H_ -#define CONTENT_RENDERER_DEVICE_SENSORS_DEVICE_ORIENTATION_EVENT_PUMP_H_ - -#include "base/macros.h" -#include "content/renderer/device_sensors/device_sensor_event_pump.h" -#include "services/device/public/cpp/generic_sensor/orientation_data.h" -#include "third_party/blink/public/platform/modules/device_orientation/web_device_orientation_listener.h" - -namespace content { - -class RenderThread; - -class CONTENT_EXPORT DeviceOrientationEventPump - : public DeviceSensorEventPump<blink::WebDeviceOrientationListener> { - public: - // Angle threshold beyond which two orientation events are considered - // sufficiently different. - static const double kOrientationThreshold; - - DeviceOrientationEventPump(RenderThread* thread, bool absolute); - ~DeviceOrientationEventPump() override; - - // PlatformEventObserver: - void SendStartMessage() override; - void SendStopMessage() override; - void SendFakeDataForTesting(void* fake_data) override; - - protected: - // DeviceSensorEventPump: - void FireEvent() override; - void DidStartIfPossible() override; - - void SendStartMessageImpl(); - - SensorEntry relative_orientation_sensor_; - SensorEntry absolute_orientation_sensor_; - - private: - friend class DeviceOrientationEventPumpTest; - friend class DeviceAbsoluteOrientationEventPumpTest; - - // DeviceSensorEventPump: - bool SensorsReadyOrErrored() const override; - - void GetDataFromSharedMemory(device::OrientationData* data); - - bool ShouldFireEvent(const device::OrientationData& data) const; - - bool absolute_; - bool fall_back_to_absolute_orientation_sensor_; - bool should_suspend_absolute_orientation_sensor_ = false; - device::OrientationData data_; - - DISALLOW_COPY_AND_ASSIGN(DeviceOrientationEventPump); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_DEVICE_SENSORS_DEVICE_ORIENTATION_EVENT_PUMP_H_ diff --git a/chromium/content/renderer/device_sensors/device_orientation_event_pump_unittest.cc b/chromium/content/renderer/device_sensors/device_orientation_event_pump_unittest.cc deleted file mode 100644 index a445b6af3a3..00000000000 --- a/chromium/content/renderer/device_sensors/device_orientation_event_pump_unittest.cc +++ /dev/null @@ -1,1018 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/device_sensors/device_orientation_event_pump.h" - -#include <string.h> - -#include <memory> - -#include "base/macros.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "content/public/test/test_utils.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "services/device/public/cpp/generic_sensor/orientation_data.h" -#include "services/device/public/cpp/test/fake_sensor_and_provider.h" -#include "services/device/public/mojom/sensor.mojom.h" -#include "services/device/public/mojom/sensor_provider.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/public/platform/modules/device_orientation/web_device_orientation_listener.h" -#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" - -namespace { - -constexpr double kEpsilon = 1e-8; - -} // namespace - -namespace content { - -using device::FakeSensorProvider; - -class MockDeviceOrientationListener - : public blink::WebDeviceOrientationListener { - public: - MockDeviceOrientationListener() : did_change_device_orientation_(false) { - memset(&data_, 0, sizeof(data_)); - } - ~MockDeviceOrientationListener() override {} - - void DidChangeDeviceOrientation( - const device::OrientationData& data) override { - memcpy(&data_, &data, sizeof(data)); - did_change_device_orientation_ = true; - } - - bool did_change_device_orientation() const { - return did_change_device_orientation_; - } - void set_did_change_device_orientation(bool value) { - did_change_device_orientation_ = value; - } - const device::OrientationData& data() const { return data_; } - - private: - bool did_change_device_orientation_; - device::OrientationData data_; - - DISALLOW_COPY_AND_ASSIGN(MockDeviceOrientationListener); -}; - -class DeviceOrientationEventPumpForTesting : public DeviceOrientationEventPump { - public: - DeviceOrientationEventPumpForTesting(bool absolute) - : DeviceOrientationEventPump(nullptr, absolute) {} - ~DeviceOrientationEventPumpForTesting() override {} - - // DeviceOrientationEventPump: - void SendStartMessage() override { - DeviceOrientationEventPump::SendStartMessageImpl(); - } - - private: - DISALLOW_COPY_AND_ASSIGN(DeviceOrientationEventPumpForTesting); -}; - -class DeviceOrientationEventPumpTest : public testing::Test { - public: - DeviceOrientationEventPumpTest() = default; - - protected: - void SetUp() override { - orientation_pump_.reset( - new DeviceOrientationEventPumpForTesting(false /* absolute */)); - device::mojom::SensorProviderPtr sensor_provider_ptr; - sensor_provider_.Bind(mojo::MakeRequest(&sensor_provider_ptr)); - orientation_pump_->SetSensorProviderForTesting( - std::move(sensor_provider_ptr)); - - listener_.reset(new MockDeviceOrientationListener); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::NOT_INITIALIZED); - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::NOT_INITIALIZED); - EXPECT_EQ(DeviceOrientationEventPump::PumpState::STOPPED, - orientation_pump()->GetPumpStateForTesting()); - } - - void FireEvent() { orientation_pump_->FireEvent(); } - - void ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState expected_sensor_state) { - EXPECT_EQ(expected_sensor_state, - orientation_pump_->relative_orientation_sensor_.sensor_state); - } - - void ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState expected_sensor_state) { - EXPECT_EQ(expected_sensor_state, - orientation_pump_->absolute_orientation_sensor_.sensor_state); - } - - DeviceOrientationEventPump* orientation_pump() { - return orientation_pump_.get(); - } - - MockDeviceOrientationListener* listener() { return listener_.get(); } - - FakeSensorProvider* sensor_provider() { return &sensor_provider_; } - - private: - base::MessageLoop loop_; - std::unique_ptr<DeviceOrientationEventPumpForTesting> orientation_pump_; - std::unique_ptr<MockDeviceOrientationListener> listener_; - FakeSensorProvider sensor_provider_; - - DISALLOW_COPY_AND_ASSIGN(DeviceOrientationEventPumpTest); -}; - -TEST_F(DeviceOrientationEventPumpTest, MultipleStartAndStopWithWait) { - orientation_pump()->Start(listener()); - base::RunLoop().RunUntilIdle(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::ACTIVE); - EXPECT_EQ(DeviceOrientationEventPump::PumpState::RUNNING, - orientation_pump()->GetPumpStateForTesting()); - - orientation_pump()->Stop(); - base::RunLoop().RunUntilIdle(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::SUSPENDED); - EXPECT_EQ(DeviceOrientationEventPump::PumpState::STOPPED, - orientation_pump()->GetPumpStateForTesting()); - - orientation_pump()->Start(listener()); - base::RunLoop().RunUntilIdle(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::ACTIVE); - EXPECT_EQ(DeviceOrientationEventPump::PumpState::RUNNING, - orientation_pump()->GetPumpStateForTesting()); - - orientation_pump()->Stop(); - base::RunLoop().RunUntilIdle(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::SUSPENDED); - EXPECT_EQ(DeviceOrientationEventPump::PumpState::STOPPED, - orientation_pump()->GetPumpStateForTesting()); -} - -TEST_F(DeviceOrientationEventPumpTest, - MultipleStartAndStopWithWaitWithSensorFallback) { - sensor_provider()->set_relative_orientation_sensor_is_available(false); - - orientation_pump()->Start(listener()); - base::RunLoop().RunUntilIdle(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::NOT_INITIALIZED); - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::ACTIVE); - EXPECT_EQ(DeviceOrientationEventPump::PumpState::RUNNING, - orientation_pump()->GetPumpStateForTesting()); - - orientation_pump()->Stop(); - base::RunLoop().RunUntilIdle(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::NOT_INITIALIZED); - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::SUSPENDED); - EXPECT_EQ(DeviceOrientationEventPump::PumpState::STOPPED, - orientation_pump()->GetPumpStateForTesting()); - - orientation_pump()->Start(listener()); - base::RunLoop().RunUntilIdle(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::NOT_INITIALIZED); - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::ACTIVE); - EXPECT_EQ(DeviceOrientationEventPump::PumpState::RUNNING, - orientation_pump()->GetPumpStateForTesting()); - - orientation_pump()->Stop(); - base::RunLoop().RunUntilIdle(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::NOT_INITIALIZED); - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::SUSPENDED); - EXPECT_EQ(DeviceOrientationEventPump::PumpState::STOPPED, - orientation_pump()->GetPumpStateForTesting()); -} - -TEST_F(DeviceOrientationEventPumpTest, CallStop) { - orientation_pump()->Stop(); - base::RunLoop().RunUntilIdle(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::NOT_INITIALIZED); -} - -TEST_F(DeviceOrientationEventPumpTest, CallStopWithSensorFallback) { - sensor_provider()->set_relative_orientation_sensor_is_available(false); - - orientation_pump()->Stop(); - base::RunLoop().RunUntilIdle(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::NOT_INITIALIZED); - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::NOT_INITIALIZED); -} - -TEST_F(DeviceOrientationEventPumpTest, CallStartAndStop) { - orientation_pump()->Start(listener()); - orientation_pump()->Stop(); - base::RunLoop().RunUntilIdle(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::SUSPENDED); -} - -TEST_F(DeviceOrientationEventPumpTest, CallStartAndStopWithSensorFallback) { - sensor_provider()->set_relative_orientation_sensor_is_available(false); - - orientation_pump()->Start(listener()); - orientation_pump()->Stop(); - base::RunLoop().RunUntilIdle(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::NOT_INITIALIZED); - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::SUSPENDED); -} - -TEST_F(DeviceOrientationEventPumpTest, CallStartMultipleTimes) { - orientation_pump()->Start(listener()); - orientation_pump()->Start(listener()); - orientation_pump()->Stop(); - base::RunLoop().RunUntilIdle(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::SUSPENDED); -} - -TEST_F(DeviceOrientationEventPumpTest, - CallStartMultipleTimesWithSensorFallback) { - sensor_provider()->set_relative_orientation_sensor_is_available(false); - - orientation_pump()->Start(listener()); - orientation_pump()->Start(listener()); - orientation_pump()->Stop(); - base::RunLoop().RunUntilIdle(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::NOT_INITIALIZED); - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::SUSPENDED); -} - -TEST_F(DeviceOrientationEventPumpTest, CallStopMultipleTimes) { - orientation_pump()->Start(listener()); - orientation_pump()->Stop(); - orientation_pump()->Stop(); - base::RunLoop().RunUntilIdle(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::SUSPENDED); -} - -TEST_F(DeviceOrientationEventPumpTest, - CallStopMultipleTimesWithSensorFallback) { - sensor_provider()->set_relative_orientation_sensor_is_available(false); - - orientation_pump()->Start(listener()); - orientation_pump()->Stop(); - orientation_pump()->Stop(); - base::RunLoop().RunUntilIdle(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::NOT_INITIALIZED); - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::SUSPENDED); -} - -// Test a sequence of Start(), Stop(), Start() calls only bind sensor once. -TEST_F(DeviceOrientationEventPumpTest, SensorOnlyBindOnce) { - orientation_pump()->Start(listener()); - orientation_pump()->Stop(); - orientation_pump()->Start(listener()); - base::RunLoop().RunUntilIdle(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::ACTIVE); - - orientation_pump()->Stop(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::SUSPENDED); -} - -// Test when using fallback from relative orientation to absolute orientation, -// a sequence of Start(), Stop(), Start() calls only bind sensor once. -TEST_F(DeviceOrientationEventPumpTest, SensorOnlyBindOnceWithSensorFallback) { - sensor_provider()->set_relative_orientation_sensor_is_available(false); - - orientation_pump()->Start(listener()); - orientation_pump()->Stop(); - orientation_pump()->Start(listener()); - base::RunLoop().RunUntilIdle(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::NOT_INITIALIZED); - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::ACTIVE); - - orientation_pump()->Stop(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::NOT_INITIALIZED); - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::SUSPENDED); -} - -TEST_F(DeviceOrientationEventPumpTest, SensorIsActive) { - orientation_pump()->Start(listener()); - base::RunLoop().RunUntilIdle(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::ACTIVE); - - sensor_provider()->UpdateRelativeOrientationSensorData( - 1 /* alpha */, 2 /* beta */, 3 /* gamma */); - - FireEvent(); - - device::OrientationData received_data = listener()->data(); - EXPECT_TRUE(listener()->did_change_device_orientation()); - - // DeviceOrientation Event provides relative orientation data when it is - // available. - EXPECT_DOUBLE_EQ(1, received_data.alpha); - EXPECT_TRUE(received_data.has_alpha); - EXPECT_DOUBLE_EQ(2, received_data.beta); - EXPECT_TRUE(received_data.has_beta); - EXPECT_DOUBLE_EQ(3, received_data.gamma); - EXPECT_TRUE(received_data.has_gamma); - EXPECT_FALSE(received_data.absolute); - - orientation_pump()->Stop(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::SUSPENDED); -} - -TEST_F(DeviceOrientationEventPumpTest, SensorIsActiveWithSensorFallback) { - sensor_provider()->set_relative_orientation_sensor_is_available(false); - - orientation_pump()->Start(listener()); - base::RunLoop().RunUntilIdle(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::NOT_INITIALIZED); - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::ACTIVE); - - sensor_provider()->UpdateAbsoluteOrientationSensorData( - 4 /* alpha */, 5 /* beta */, 6 /* gamma */); - - FireEvent(); - - device::OrientationData received_data = listener()->data(); - EXPECT_TRUE(listener()->did_change_device_orientation()); - - // DeviceOrientation Event provides absolute orientation data when relative - // orientation data is not available but absolute orientation data is - // available. - EXPECT_DOUBLE_EQ(4, received_data.alpha); - EXPECT_TRUE(received_data.has_alpha); - EXPECT_DOUBLE_EQ(5, received_data.beta); - EXPECT_TRUE(received_data.has_beta); - EXPECT_DOUBLE_EQ(6, received_data.gamma); - EXPECT_TRUE(received_data.has_gamma); - // Since no relative orientation data is available, DeviceOrientationEvent - // fallback to provide absolute orientation data. - EXPECT_TRUE(received_data.absolute); - - orientation_pump()->Stop(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::NOT_INITIALIZED); - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::SUSPENDED); -} - -TEST_F(DeviceOrientationEventPumpTest, SomeSensorDataFieldsNotAvailable) { - orientation_pump()->Start(listener()); - base::RunLoop().RunUntilIdle(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::ACTIVE); - - sensor_provider()->UpdateRelativeOrientationSensorData( - NAN /* alpha */, 2 /* beta */, 3 /* gamma */); - - FireEvent(); - - device::OrientationData received_data = listener()->data(); - EXPECT_TRUE(listener()->did_change_device_orientation()); - - EXPECT_FALSE(received_data.has_alpha); - EXPECT_DOUBLE_EQ(2, received_data.beta); - EXPECT_TRUE(received_data.has_beta); - EXPECT_DOUBLE_EQ(3, received_data.gamma); - EXPECT_TRUE(received_data.has_gamma); - EXPECT_FALSE(received_data.absolute); - - orientation_pump()->Stop(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::SUSPENDED); -} - -TEST_F(DeviceOrientationEventPumpTest, - SomeSensorDataFieldsNotAvailableWithSensorFallback) { - sensor_provider()->set_relative_orientation_sensor_is_available(false); - - orientation_pump()->Start(listener()); - base::RunLoop().RunUntilIdle(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::NOT_INITIALIZED); - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::ACTIVE); - - sensor_provider()->UpdateAbsoluteOrientationSensorData( - 4 /* alpha */, NAN /* beta */, 6 /* gamma */); - - FireEvent(); - - device::OrientationData received_data = listener()->data(); - EXPECT_TRUE(listener()->did_change_device_orientation()); - - // DeviceOrientation Event provides absolute orientation data when relative - // orientation data is not available but absolute orientation data is - // available. - EXPECT_DOUBLE_EQ(4, received_data.alpha); - EXPECT_TRUE(received_data.has_alpha); - EXPECT_FALSE(received_data.has_beta); - EXPECT_DOUBLE_EQ(6, received_data.gamma); - EXPECT_TRUE(received_data.has_gamma); - // Since no relative orientation data is available, DeviceOrientationEvent - // fallback to provide absolute orientation data. - EXPECT_TRUE(received_data.absolute); - - orientation_pump()->Stop(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::NOT_INITIALIZED); - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::SUSPENDED); -} - -TEST_F(DeviceOrientationEventPumpTest, FireAllNullEvent) { - // No active sensors. - sensor_provider()->set_relative_orientation_sensor_is_available(false); - sensor_provider()->set_absolute_orientation_sensor_is_available(false); - - orientation_pump()->Start(listener()); - base::RunLoop().RunUntilIdle(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::NOT_INITIALIZED); - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::NOT_INITIALIZED); - - FireEvent(); - - device::OrientationData received_data = listener()->data(); - EXPECT_TRUE(listener()->did_change_device_orientation()); - - EXPECT_FALSE(received_data.has_alpha); - EXPECT_FALSE(received_data.has_beta); - EXPECT_FALSE(received_data.has_gamma); - EXPECT_FALSE(received_data.absolute); - - orientation_pump()->Stop(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::NOT_INITIALIZED); - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::NOT_INITIALIZED); -} - -TEST_F(DeviceOrientationEventPumpTest, - NotFireEventWhenSensorReadingTimeStampIsZero) { - orientation_pump()->Start(listener()); - base::RunLoop().RunUntilIdle(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::ACTIVE); - - FireEvent(); - - EXPECT_FALSE(listener()->did_change_device_orientation()); - - orientation_pump()->Stop(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::SUSPENDED); -} - -TEST_F(DeviceOrientationEventPumpTest, - NotFireEventWhenSensorReadingTimeStampIsZeroWithSensorFallback) { - sensor_provider()->set_relative_orientation_sensor_is_available(false); - - orientation_pump()->Start(listener()); - base::RunLoop().RunUntilIdle(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::NOT_INITIALIZED); - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::ACTIVE); - - FireEvent(); - - EXPECT_FALSE(listener()->did_change_device_orientation()); - - orientation_pump()->Stop(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::NOT_INITIALIZED); - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::SUSPENDED); -} - -TEST_F(DeviceOrientationEventPumpTest, UpdateRespectsOrientationThreshold) { - orientation_pump()->Start(listener()); - base::RunLoop().RunUntilIdle(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::ACTIVE); - - sensor_provider()->UpdateRelativeOrientationSensorData( - 1 /* alpha */, 2 /* beta */, 3 /* gamma */); - - FireEvent(); - - device::OrientationData received_data = listener()->data(); - EXPECT_TRUE(listener()->did_change_device_orientation()); - - // DeviceOrientation Event provides relative orientation data when it is - // available. - EXPECT_DOUBLE_EQ(1, received_data.alpha); - EXPECT_TRUE(received_data.has_alpha); - EXPECT_DOUBLE_EQ(2, received_data.beta); - EXPECT_TRUE(received_data.has_beta); - EXPECT_DOUBLE_EQ(3, received_data.gamma); - EXPECT_TRUE(received_data.has_gamma); - EXPECT_FALSE(received_data.absolute); - - listener()->set_did_change_device_orientation(false); - - sensor_provider()->UpdateRelativeOrientationSensorData( - 1 + DeviceOrientationEventPump::kOrientationThreshold / 2.0 /* alpha */, - 2 /* beta */, 3 /* gamma */); - - FireEvent(); - - received_data = listener()->data(); - EXPECT_FALSE(listener()->did_change_device_orientation()); - - EXPECT_DOUBLE_EQ(1, received_data.alpha); - EXPECT_TRUE(received_data.has_alpha); - EXPECT_DOUBLE_EQ(2, received_data.beta); - EXPECT_TRUE(received_data.has_beta); - EXPECT_DOUBLE_EQ(3, received_data.gamma); - EXPECT_TRUE(received_data.has_gamma); - EXPECT_FALSE(received_data.absolute); - - listener()->set_did_change_device_orientation(false); - - sensor_provider()->UpdateRelativeOrientationSensorData( - 1 + DeviceOrientationEventPump::kOrientationThreshold /* alpha */, - 2 /* beta */, 3 /* gamma */); - - FireEvent(); - - received_data = listener()->data(); - EXPECT_TRUE(listener()->did_change_device_orientation()); - - EXPECT_DOUBLE_EQ(1 + DeviceOrientationEventPump::kOrientationThreshold, - received_data.alpha); - EXPECT_TRUE(received_data.has_alpha); - EXPECT_DOUBLE_EQ(2, received_data.beta); - EXPECT_TRUE(received_data.has_beta); - EXPECT_DOUBLE_EQ(3, received_data.gamma); - EXPECT_TRUE(received_data.has_gamma); - EXPECT_FALSE(received_data.absolute); - - orientation_pump()->Stop(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::SUSPENDED); -} - -TEST_F(DeviceOrientationEventPumpTest, - UpdateRespectsOrientationThresholdWithSensorFallback) { - sensor_provider()->set_relative_orientation_sensor_is_available(false); - - orientation_pump()->Start(listener()); - base::RunLoop().RunUntilIdle(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::NOT_INITIALIZED); - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::ACTIVE); - - sensor_provider()->UpdateAbsoluteOrientationSensorData( - 4 /* alpha */, 5 /* beta */, 6 /* gamma */); - - FireEvent(); - - device::OrientationData received_data = listener()->data(); - EXPECT_TRUE(listener()->did_change_device_orientation()); - - // DeviceOrientation Event provides absolute orientation data when relative - // orientation data is not available but absolute orientation data is - // available. - EXPECT_DOUBLE_EQ(4, received_data.alpha); - EXPECT_TRUE(received_data.has_alpha); - EXPECT_DOUBLE_EQ(5, received_data.beta); - EXPECT_TRUE(received_data.has_beta); - EXPECT_DOUBLE_EQ(6, received_data.gamma); - EXPECT_TRUE(received_data.has_gamma); - // Since no relative orientation data is available, DeviceOrientationEvent - // fallback to provide absolute orientation data. - EXPECT_TRUE(received_data.absolute); - - listener()->set_did_change_device_orientation(false); - - sensor_provider()->UpdateAbsoluteOrientationSensorData( - 4 /* alpha */, - 5 + DeviceOrientationEventPump::kOrientationThreshold / 2.0 /* beta */, - 6 /* gamma */); - - FireEvent(); - - received_data = listener()->data(); - EXPECT_FALSE(listener()->did_change_device_orientation()); - - EXPECT_DOUBLE_EQ(4, received_data.alpha); - EXPECT_TRUE(received_data.has_alpha); - EXPECT_DOUBLE_EQ(5, received_data.beta); - EXPECT_TRUE(received_data.has_beta); - EXPECT_DOUBLE_EQ(6, received_data.gamma); - EXPECT_TRUE(received_data.has_gamma); - EXPECT_TRUE(received_data.absolute); - - listener()->set_did_change_device_orientation(false); - - sensor_provider()->UpdateAbsoluteOrientationSensorData( - 4 /* alpha */, - 5 + DeviceOrientationEventPump::kOrientationThreshold + - kEpsilon /* beta */, - 6 /* gamma */); - - FireEvent(); - - received_data = listener()->data(); - EXPECT_TRUE(listener()->did_change_device_orientation()); - - EXPECT_DOUBLE_EQ(4, received_data.alpha); - EXPECT_TRUE(received_data.has_alpha); - EXPECT_DOUBLE_EQ( - 5 + DeviceOrientationEventPump::kOrientationThreshold + kEpsilon, - received_data.beta); - EXPECT_TRUE(received_data.has_beta); - EXPECT_DOUBLE_EQ(6, received_data.gamma); - EXPECT_TRUE(received_data.has_gamma); - EXPECT_TRUE(received_data.absolute); - - orientation_pump()->Stop(); - - ExpectRelativeOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::NOT_INITIALIZED); - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::SUSPENDED); -} - -class DeviceAbsoluteOrientationEventPumpTest : public testing::Test { - public: - DeviceAbsoluteOrientationEventPumpTest() = default; - - protected: - void SetUp() override { - absolute_orientation_pump_.reset( - new DeviceOrientationEventPumpForTesting(true /* absolute */)); - device::mojom::SensorProviderPtr sensor_provider_ptr; - sensor_provider_.Bind(mojo::MakeRequest(&sensor_provider_ptr)); - absolute_orientation_pump_->SetSensorProviderForTesting( - std::move(sensor_provider_ptr)); - - listener_.reset(new MockDeviceOrientationListener); - - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::NOT_INITIALIZED); - EXPECT_EQ(DeviceOrientationEventPump::PumpState::STOPPED, - absolute_orientation_pump()->GetPumpStateForTesting()); - } - - void FireEvent() { absolute_orientation_pump_->FireEvent(); } - - void ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState expected_sensor_state) { - EXPECT_EQ( - expected_sensor_state, - absolute_orientation_pump_->absolute_orientation_sensor_.sensor_state); - } - - DeviceOrientationEventPump* absolute_orientation_pump() { - return absolute_orientation_pump_.get(); - } - - MockDeviceOrientationListener* listener() { return listener_.get(); } - - FakeSensorProvider* sensor_provider() { return &sensor_provider_; } - - private: - base::MessageLoop loop_; - std::unique_ptr<DeviceOrientationEventPumpForTesting> - absolute_orientation_pump_; - std::unique_ptr<MockDeviceOrientationListener> listener_; - FakeSensorProvider sensor_provider_; - - DISALLOW_COPY_AND_ASSIGN(DeviceAbsoluteOrientationEventPumpTest); -}; - -TEST_F(DeviceAbsoluteOrientationEventPumpTest, MultipleStartAndStopWithWait) { - absolute_orientation_pump()->Start(listener()); - base::RunLoop().RunUntilIdle(); - - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::ACTIVE); - EXPECT_EQ(DeviceOrientationEventPump::PumpState::RUNNING, - absolute_orientation_pump()->GetPumpStateForTesting()); - - absolute_orientation_pump()->Stop(); - base::RunLoop().RunUntilIdle(); - - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::SUSPENDED); - EXPECT_EQ(DeviceOrientationEventPump::PumpState::STOPPED, - absolute_orientation_pump()->GetPumpStateForTesting()); - - absolute_orientation_pump()->Start(listener()); - base::RunLoop().RunUntilIdle(); - - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::ACTIVE); - EXPECT_EQ(DeviceOrientationEventPump::PumpState::RUNNING, - absolute_orientation_pump()->GetPumpStateForTesting()); - - absolute_orientation_pump()->Stop(); - base::RunLoop().RunUntilIdle(); - - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::SUSPENDED); - EXPECT_EQ(DeviceOrientationEventPump::PumpState::STOPPED, - absolute_orientation_pump()->GetPumpStateForTesting()); -} - -TEST_F(DeviceAbsoluteOrientationEventPumpTest, CallStop) { - absolute_orientation_pump()->Stop(); - base::RunLoop().RunUntilIdle(); - - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::NOT_INITIALIZED); -} - -TEST_F(DeviceAbsoluteOrientationEventPumpTest, CallStartAndStop) { - absolute_orientation_pump()->Start(listener()); - absolute_orientation_pump()->Stop(); - base::RunLoop().RunUntilIdle(); - - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::SUSPENDED); -} - -TEST_F(DeviceAbsoluteOrientationEventPumpTest, CallStartMultipleTimes) { - absolute_orientation_pump()->Start(listener()); - absolute_orientation_pump()->Start(listener()); - absolute_orientation_pump()->Stop(); - base::RunLoop().RunUntilIdle(); - - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::SUSPENDED); -} - -TEST_F(DeviceAbsoluteOrientationEventPumpTest, CallStopMultipleTimes) { - absolute_orientation_pump()->Start(listener()); - absolute_orientation_pump()->Stop(); - absolute_orientation_pump()->Stop(); - base::RunLoop().RunUntilIdle(); - - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::SUSPENDED); -} - -// Test multiple DeviceSensorEventPump::Start() calls only bind sensor once. -TEST_F(DeviceAbsoluteOrientationEventPumpTest, SensorOnlyBindOnce) { - absolute_orientation_pump()->Start(listener()); - absolute_orientation_pump()->Stop(); - absolute_orientation_pump()->Start(listener()); - base::RunLoop().RunUntilIdle(); - - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::ACTIVE); - - absolute_orientation_pump()->Stop(); - - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::SUSPENDED); -} - -TEST_F(DeviceAbsoluteOrientationEventPumpTest, SensorIsActive) { - absolute_orientation_pump()->Start(listener()); - base::RunLoop().RunUntilIdle(); - - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::ACTIVE); - - sensor_provider()->UpdateAbsoluteOrientationSensorData( - 4 /* alpha */, 5 /* beta */, 6 /* gamma */); - - FireEvent(); - - device::OrientationData received_data = listener()->data(); - EXPECT_TRUE(listener()->did_change_device_orientation()); - - EXPECT_DOUBLE_EQ(4, received_data.alpha); - EXPECT_TRUE(received_data.has_alpha); - EXPECT_DOUBLE_EQ(5, received_data.beta); - EXPECT_TRUE(received_data.has_beta); - EXPECT_DOUBLE_EQ(6, received_data.gamma); - EXPECT_TRUE(received_data.has_gamma); - EXPECT_TRUE(received_data.absolute); - - absolute_orientation_pump()->Stop(); - - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::SUSPENDED); -} - -TEST_F(DeviceAbsoluteOrientationEventPumpTest, - SomeSensorDataFieldsNotAvailable) { - absolute_orientation_pump()->Start(listener()); - base::RunLoop().RunUntilIdle(); - - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::ACTIVE); - - sensor_provider()->UpdateAbsoluteOrientationSensorData( - 4 /* alpha */, NAN /* beta */, 6 /* gamma */); - - FireEvent(); - - device::OrientationData received_data = listener()->data(); - EXPECT_TRUE(listener()->did_change_device_orientation()); - - EXPECT_DOUBLE_EQ(4, received_data.alpha); - EXPECT_TRUE(received_data.has_alpha); - EXPECT_FALSE(received_data.has_beta); - EXPECT_DOUBLE_EQ(6, received_data.gamma); - EXPECT_TRUE(received_data.has_gamma); - EXPECT_TRUE(received_data.absolute); - - absolute_orientation_pump()->Stop(); - - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::SUSPENDED); -} - -TEST_F(DeviceAbsoluteOrientationEventPumpTest, FireAllNullEvent) { - // No active sensor. - sensor_provider()->set_absolute_orientation_sensor_is_available(false); - - absolute_orientation_pump()->Start(listener()); - base::RunLoop().RunUntilIdle(); - - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::NOT_INITIALIZED); - - FireEvent(); - - device::OrientationData received_data = listener()->data(); - EXPECT_TRUE(listener()->did_change_device_orientation()); - - EXPECT_FALSE(received_data.has_alpha); - EXPECT_FALSE(received_data.has_beta); - EXPECT_FALSE(received_data.has_gamma); - EXPECT_TRUE(received_data.absolute); - - absolute_orientation_pump()->Stop(); - - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::NOT_INITIALIZED); -} - -TEST_F(DeviceAbsoluteOrientationEventPumpTest, - NotFireEventWhenSensorReadingTimeStampIsZero) { - absolute_orientation_pump()->Start(listener()); - base::RunLoop().RunUntilIdle(); - - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::ACTIVE); - - FireEvent(); - - EXPECT_FALSE(listener()->did_change_device_orientation()); - - absolute_orientation_pump()->Stop(); - - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::SUSPENDED); -} - -TEST_F(DeviceAbsoluteOrientationEventPumpTest, - UpdateRespectsOrientationThreshold) { - absolute_orientation_pump()->Start(listener()); - base::RunLoop().RunUntilIdle(); - - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::ACTIVE); - - sensor_provider()->UpdateAbsoluteOrientationSensorData( - 4 /* alpha */, 5 /* beta */, 6 /* gamma */); - - FireEvent(); - - device::OrientationData received_data = listener()->data(); - EXPECT_TRUE(listener()->did_change_device_orientation()); - - EXPECT_DOUBLE_EQ(4, received_data.alpha); - EXPECT_TRUE(received_data.has_alpha); - EXPECT_DOUBLE_EQ(5, received_data.beta); - EXPECT_TRUE(received_data.has_beta); - EXPECT_DOUBLE_EQ(6, received_data.gamma); - EXPECT_TRUE(received_data.has_gamma); - EXPECT_TRUE(received_data.absolute); - - listener()->set_did_change_device_orientation(false); - - sensor_provider()->UpdateAbsoluteOrientationSensorData( - 4 /* alpha */, - 5 + DeviceOrientationEventPump::kOrientationThreshold / 2.0 /* beta */, - 6 /* gamma */); - - FireEvent(); - - received_data = listener()->data(); - EXPECT_FALSE(listener()->did_change_device_orientation()); - - EXPECT_DOUBLE_EQ(4, received_data.alpha); - EXPECT_TRUE(received_data.has_alpha); - EXPECT_DOUBLE_EQ(5, received_data.beta); - EXPECT_TRUE(received_data.has_beta); - EXPECT_DOUBLE_EQ(6, received_data.gamma); - EXPECT_TRUE(received_data.has_gamma); - EXPECT_TRUE(received_data.absolute); - - listener()->set_did_change_device_orientation(false); - - sensor_provider()->UpdateAbsoluteOrientationSensorData( - 4 /* alpha */, - 5 + DeviceOrientationEventPump::kOrientationThreshold + - kEpsilon /* beta */, - 6 /* gamma */); - - FireEvent(); - - received_data = listener()->data(); - EXPECT_TRUE(listener()->did_change_device_orientation()); - - EXPECT_DOUBLE_EQ(4, received_data.alpha); - EXPECT_TRUE(received_data.has_alpha); - EXPECT_DOUBLE_EQ( - 5 + DeviceOrientationEventPump::kOrientationThreshold + kEpsilon, - received_data.beta); - EXPECT_TRUE(received_data.has_beta); - EXPECT_DOUBLE_EQ(6, received_data.gamma); - EXPECT_TRUE(received_data.has_gamma); - EXPECT_TRUE(received_data.absolute); - - absolute_orientation_pump()->Stop(); - - ExpectAbsoluteOrientationSensorStateToBe( - DeviceOrientationEventPump::SensorState::SUSPENDED); -} - -} // namespace content diff --git a/chromium/content/renderer/device_sensors/device_sensor_event_pump.h b/chromium/content/renderer/device_sensors/device_sensor_event_pump.h deleted file mode 100644 index 98d846bc08e..00000000000 --- a/chromium/content/renderer/device_sensors/device_sensor_event_pump.h +++ /dev/null @@ -1,329 +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_DEVICE_SENSORS_DEVICE_SENSOR_EVENT_PUMP_H_ -#define CONTENT_RENDERER_DEVICE_SENSORS_DEVICE_SENSOR_EVENT_PUMP_H_ - -#include <algorithm> -#include <memory> -#include <utility> -#include <vector> - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/macros.h" -#include "base/time/time.h" -#include "base/timer/timer.h" -#include "content/public/common/service_names.mojom.h" -#include "content/public/renderer/platform_event_observer.h" -#include "content/public/renderer/render_frame.h" -#include "content/public/renderer/render_thread.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "services/device/public/cpp/generic_sensor/sensor_reading.h" -#include "services/device/public/cpp/generic_sensor/sensor_reading_shared_buffer_reader.h" -#include "services/device/public/cpp/generic_sensor/sensor_traits.h" -#include "services/device/public/mojom/constants.mojom.h" -#include "services/device/public/mojom/sensor_provider.mojom.h" -#include "third_party/blink/public/platform/modules/device_orientation/web_device_motion_listener.h" -#include "third_party/blink/public/platform/modules/device_orientation/web_device_orientation_listener.h" -#include "third_party/blink/public/web/web_local_frame.h" - -namespace content { - -template <typename ListenerType> -class CONTENT_EXPORT DeviceSensorEventPump - : public PlatformEventObserver<ListenerType> { - public: - // Default rate for firing events. - static constexpr int kDefaultPumpFrequencyHz = 60; - static constexpr int kDefaultPumpDelayMicroseconds = - base::Time::kMicrosecondsPerSecond / kDefaultPumpFrequencyHz; - - // The pump is a tri-state automaton with allowed transitions as follows: - // STOPPED -> PENDING_START - // PENDING_START -> RUNNING - // PENDING_START -> STOPPED - // RUNNING -> STOPPED - enum class PumpState { STOPPED, RUNNING, PENDING_START }; - - // The sensor state is an automaton with allowed transitions as follows: - // NOT_INITIALIZED -> INITIALIZING - // INITIALIZING -> ACTIVE - // INITIALIZING -> SHOULD_SUSPEND - // ACTIVE -> SUSPENDED - // SHOULD_SUSPEND -> INITIALIZING - // SHOULD_SUSPEND -> SUSPENDED - // SUSPENDED -> ACTIVE - // { INITIALIZING, ACTIVE, SHOULD_SUSPEND, SUSPENDED } -> NOT_INITIALIZED - enum class SensorState { - NOT_INITIALIZED, - INITIALIZING, - ACTIVE, - SHOULD_SUSPEND, - SUSPENDED - }; - - // PlatformEventObserver: - void Start(blink::WebPlatformEventListener* listener) override { - DVLOG(2) << "requested start"; - - if (state_ != PumpState::STOPPED) - return; - - DCHECK(!timer_.IsRunning()); - - state_ = PumpState::PENDING_START; - PlatformEventObserver<ListenerType>::Start(listener); - } - - // PlatformEventObserver: - void Stop() override { - DVLOG(2) << "requested stop"; - - if (state_ == PumpState::STOPPED) - return; - - DCHECK((state_ == PumpState::PENDING_START && !timer_.IsRunning()) || - (state_ == PumpState::RUNNING && timer_.IsRunning())); - - if (timer_.IsRunning()) - timer_.Stop(); - - PlatformEventObserver<ListenerType>::Stop(); - state_ = PumpState::STOPPED; - } - - void HandleSensorProviderError() { sensor_provider_.reset(); } - - void SetSensorProviderForTesting( - device::mojom::SensorProviderPtr sensor_provider) { - sensor_provider_ = std::move(sensor_provider); - } - - PumpState GetPumpStateForTesting() { return state_; } - - protected: - explicit DeviceSensorEventPump(RenderThread* thread) - : PlatformEventObserver<ListenerType>(thread), - state_(PumpState::STOPPED) {} - - ~DeviceSensorEventPump() override { - PlatformEventObserver<ListenerType>::StopIfObserving(); - } - - virtual void FireEvent() = 0; - - struct SensorEntry : public device::mojom::SensorClient { - SensorEntry(DeviceSensorEventPump* pump, - device::mojom::SensorType sensor_type) - : event_pump(pump), - sensor_state(SensorState::NOT_INITIALIZED), - type(sensor_type), - client_binding(this) {} - - ~SensorEntry() override {} - - // device::mojom::SensorClient: - void RaiseError() override { HandleSensorError(); } - - // device::mojom::SensorClient: - void SensorReadingChanged() override { - // Since DeviceSensorEventPump::FireEvent is called in a fixed - // frequency, the |shared_buffer| is read frequently, and - // Sensor::ConfigureReadingChangeNotifications() is set to false, - // so this method is not called and doesn't need to be implemented. - NOTREACHED(); - } - - // Mojo callback for SensorProvider::GetSensor(). - void OnSensorCreated(device::mojom::SensorCreationResult result, - device::mojom::SensorInitParamsPtr params) { - // |sensor_state| can be SensorState::SHOULD_SUSPEND if Stop() is called - // before OnSensorCreated() is called. - DCHECK(sensor_state == SensorState::INITIALIZING || - sensor_state == SensorState::SHOULD_SUSPEND); - - if (!params) { - HandleSensorError(); - event_pump->DidStartIfPossible(); - return; - } - DCHECK_EQ(device::mojom::SensorCreationResult::SUCCESS, result); - - constexpr size_t kReadBufferSize = - sizeof(device::SensorReadingSharedBuffer); - - DCHECK_EQ(0u, params->buffer_offset % kReadBufferSize); - - mode = params->mode; - default_config = params->default_configuration; - - sensor.Bind(std::move(params->sensor)); - client_binding.Bind(std::move(params->client_request)); - - shared_buffer_handle = std::move(params->memory); - DCHECK(!shared_buffer); - shared_buffer = shared_buffer_handle->MapAtOffset(kReadBufferSize, - params->buffer_offset); - if (!shared_buffer) { - HandleSensorError(); - event_pump->DidStartIfPossible(); - return; - } - - const device::SensorReadingSharedBuffer* buffer = - static_cast<const device::SensorReadingSharedBuffer*>( - shared_buffer.get()); - shared_buffer_reader.reset( - new device::SensorReadingSharedBufferReader(buffer)); - - default_config.set_frequency( - std::min(static_cast<double>(kDefaultPumpFrequencyHz), - params->maximum_frequency)); - - sensor.set_connection_error_handler(base::BindOnce( - &SensorEntry::HandleSensorError, base::Unretained(this))); - sensor->ConfigureReadingChangeNotifications(false /* disabled */); - sensor->AddConfiguration( - default_config, base::BindOnce(&SensorEntry::OnSensorAddConfiguration, - base::Unretained(this))); - } - - // Mojo callback for Sensor::AddConfiguration(). - void OnSensorAddConfiguration(bool success) { - if (!success) - HandleSensorError(); - - if (sensor_state == SensorState::INITIALIZING) { - sensor_state = SensorState::ACTIVE; - event_pump->DidStartIfPossible(); - } else if (sensor_state == SensorState::SHOULD_SUSPEND) { - sensor->Suspend(); - sensor_state = SensorState::SUSPENDED; - } - } - - void HandleSensorError() { - sensor.reset(); - sensor_state = SensorState::NOT_INITIALIZED; - shared_buffer_handle.reset(); - shared_buffer.reset(); - client_binding.Close(); - } - - bool SensorReadingCouldBeRead() { - if (!sensor) - return false; - - DCHECK(shared_buffer); - - if (!shared_buffer_handle->is_valid() || - !shared_buffer_reader->GetReading(&reading)) { - HandleSensorError(); - return false; - } - - return true; - } - - bool ReadyOrErrored() const { - // When some sensors are not available, the pump still needs to fire - // events which set the unavailable sensor data fields to null. - return sensor_state == SensorState::ACTIVE || - sensor_state == SensorState::NOT_INITIALIZED; - } - - void Start(device::mojom::SensorProvider* sensor_provider) { - if (sensor_state == SensorState::NOT_INITIALIZED) { - sensor_state = SensorState::INITIALIZING; - sensor_provider->GetSensor(type, - base::BindOnce(&SensorEntry::OnSensorCreated, - base::Unretained(this))); - } else if (sensor_state == SensorState::SUSPENDED) { - sensor->Resume(); - sensor_state = SensorState::ACTIVE; - event_pump->DidStartIfPossible(); - } else if (sensor_state == SensorState::SHOULD_SUSPEND) { - // This can happen when calling Start(), Stop(), Start() in a sequence: - // After the first Start() call, the sensor state is - // SensorState::INITIALIZING. Then after the Stop() call, the sensor - // state is SensorState::SHOULD_SUSPEND, and the next Start() call needs - // to set the sensor state to be SensorState::INITIALIZING again. - sensor_state = SensorState::INITIALIZING; - } else { - NOTREACHED(); - } - } - - void Stop() { - if (sensor) { - sensor->Suspend(); - sensor_state = SensorState::SUSPENDED; - } else if (sensor_state == SensorState::INITIALIZING) { - // When the sensor needs to be suspended, and it is still in the - // SensorState::INITIALIZING state, the sensor creation is not affected - // (the SensorEntry::OnSensorCreated() callback will run as usual), but - // the sensor is marked as SensorState::SHOULD_SUSPEND, and when the - // sensor is created successfully, it will be suspended and its state - // will be marked as SensorState::SUSPENDED in the - // SensorEntry::OnSensorAddConfiguration(). - sensor_state = SensorState::SHOULD_SUSPEND; - } - } - - DeviceSensorEventPump* event_pump; - device::mojom::SensorPtr sensor; - SensorState sensor_state; - device::mojom::SensorType type; - device::mojom::ReportingMode mode; - device::PlatformSensorConfiguration default_config; - mojo::ScopedSharedBufferHandle shared_buffer_handle; - mojo::ScopedSharedBufferMapping shared_buffer; - std::unique_ptr<device::SensorReadingSharedBufferReader> - shared_buffer_reader; - device::SensorReading reading; - mojo::Binding<device::mojom::SensorClient> client_binding; - }; - - friend struct SensorEntry; - - virtual void DidStartIfPossible() { - DVLOG(2) << "did start sensor event pump"; - - if (state_ != PumpState::PENDING_START) - return; - - if (!SensorsReadyOrErrored()) - return; - - DCHECK(!timer_.IsRunning()); - - timer_.Start( - FROM_HERE, - base::TimeDelta::FromMicroseconds(kDefaultPumpDelayMicroseconds), this, - &DeviceSensorEventPump::FireEvent); - state_ = PumpState::RUNNING; - } - - static RenderFrame* GetRenderFrame() { - blink::WebLocalFrame* const web_frame = - blink::WebLocalFrame::FrameForCurrentContext(); - - return RenderFrame::FromWebFrame(web_frame); - } - - device::mojom::SensorProviderPtr sensor_provider_; - - private: - virtual bool SensorsReadyOrErrored() const = 0; - - PumpState state_; - base::RepeatingTimer timer_; - - DISALLOW_COPY_AND_ASSIGN(DeviceSensorEventPump); -}; -} // namespace content - -#endif // CONTENT_RENDERER_DEVICE_SENSORS_DEVICE_SENSOR_EVENT_PUMP_H_ diff --git a/chromium/content/renderer/dom_serializer_browsertest.cc b/chromium/content/renderer/dom_serializer_browsertest.cc index fc8ff6e4ebd..2b188608b53 100644 --- a/chromium/content/renderer/dom_serializer_browsertest.cc +++ b/chromium/content/renderer/dom_serializer_browsertest.cc @@ -138,7 +138,11 @@ class MAYBE_DomSerializerTests : public ContentBrowserTest, // Do not use WebFrame.LoadHTMLString because it assumes that input // html contents use UTF-8 encoding. WebData data(contents.data(), contents.length()); - GetMainFrame()->LoadData(data, "text/html", encoding_info, base_url); + GetMainFrame()->CommitDataNavigation( + data, "text/html", encoding_info, base_url, WebURL(), + false /* replace */, blink::WebFrameLoadType::kStandard, + blink::WebHistoryItem(), false /* is_client_redirect */, + nullptr /* navigation_data */, blink::WebNavigationTimings()); } base::MessageLoopCurrent::ScopedNestableTaskAllower allow; waiter.Wait(); diff --git a/chromium/content/renderer/dom_storage/dom_storage_cached_area.cc b/chromium/content/renderer/dom_storage/dom_storage_cached_area.cc index f21e958f7d7..402c27727ff 100644 --- a/chromium/content/renderer/dom_storage/dom_storage_cached_area.cc +++ b/chromium/content/renderer/dom_storage/dom_storage_cached_area.cc @@ -11,7 +11,7 @@ #include "build/build_config.h" #include "content/common/dom_storage/dom_storage_map.h" #include "content/renderer/dom_storage/dom_storage_proxy.h" -#include "third_party/blink/public/platform/scheduler/web_main_thread_scheduler.h" +#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h" namespace content { @@ -19,7 +19,7 @@ DOMStorageCachedArea::DOMStorageCachedArea( const std::string& namespace_id, const GURL& origin, DOMStorageProxy* proxy, - blink::scheduler::WebMainThreadScheduler* main_thread_scheduler) + blink::scheduler::WebThreadScheduler* main_thread_scheduler) : ignore_all_mutations_(false), namespace_id_(namespace_id), origin_(origin), @@ -34,10 +34,12 @@ unsigned DOMStorageCachedArea::GetLength(int connection_id) { return map_->Length(); } -base::NullableString16 DOMStorageCachedArea::GetKey(int connection_id, - unsigned index) { +base::NullableString16 DOMStorageCachedArea::GetKey( + int connection_id, + unsigned index, + bool* did_decrease_iterator) { PrimeIfNeeded(connection_id); - return map_->Key(index); + return map_->Key(index, did_decrease_iterator); } base::NullableString16 DOMStorageCachedArea::GetItem( diff --git a/chromium/content/renderer/dom_storage/dom_storage_cached_area.h b/chromium/content/renderer/dom_storage/dom_storage_cached_area.h index a7ebb1dd0c2..dacf2da744f 100644 --- a/chromium/content/renderer/dom_storage/dom_storage_cached_area.h +++ b/chromium/content/renderer/dom_storage/dom_storage_cached_area.h @@ -19,7 +19,7 @@ namespace blink { namespace scheduler { -class WebMainThreadScheduler; +class WebThreadScheduler; } } // namespace blink @@ -41,13 +41,16 @@ class CONTENT_EXPORT DOMStorageCachedArea const std::string& namespace_id, const GURL& origin, DOMStorageProxy* proxy, - blink::scheduler::WebMainThreadScheduler* main_thread_scheduler); + blink::scheduler::WebThreadScheduler* main_thread_scheduler); const std::string& namespace_id() const { return namespace_id_; } const GURL& origin() const { return origin_; } unsigned GetLength(int connection_id); - base::NullableString16 GetKey(int connection_id, unsigned index); + // See DOMStorageMap for the meaning of |did_decrease_iterator|. + base::NullableString16 GetKey(int connection_id, + unsigned index, + bool* did_decrease_iterator = nullptr); base::NullableString16 GetItem(int connection_id, const base::string16& key); bool SetItem(int connection_id, const base::string16& key, @@ -104,7 +107,7 @@ class CONTENT_EXPORT DOMStorageCachedArea scoped_refptr<DOMStorageProxy> proxy_; // Not owned. - blink::scheduler::WebMainThreadScheduler* main_thread_scheduler_; + blink::scheduler::WebThreadScheduler* main_thread_scheduler_; base::WeakPtrFactory<DOMStorageCachedArea> weak_factory_; }; diff --git a/chromium/content/renderer/dom_storage/dom_storage_cached_area_unittest.cc b/chromium/content/renderer/dom_storage/dom_storage_cached_area_unittest.cc index 1c0afc9434d..f4d390d0a07 100644 --- a/chromium/content/renderer/dom_storage/dom_storage_cached_area_unittest.cc +++ b/chromium/content/renderer/dom_storage/dom_storage_cached_area_unittest.cc @@ -160,8 +160,7 @@ class DOMStorageCachedAreaTest : public testing::Test { protected: base::MessageLoop message_loop_; // Needed to construct a RendererScheduler. - std::unique_ptr<blink::scheduler::WebMainThreadScheduler> - main_thread_scheduler_; + std::unique_ptr<blink::scheduler::WebThreadScheduler> main_thread_scheduler_; scoped_refptr<MockProxy> mock_proxy_; }; diff --git a/chromium/content/renderer/dom_storage/local_storage_area.cc b/chromium/content/renderer/dom_storage/local_storage_area.cc index af5fe91bcc8..9aae8851998 100644 --- a/chromium/content/renderer/dom_storage/local_storage_area.cc +++ b/chromium/content/renderer/dom_storage/local_storage_area.cc @@ -28,8 +28,9 @@ unsigned LocalStorageArea::length() { return cached_area_->GetLength(); } -WebString LocalStorageArea::Key(unsigned index) { - return WebString::FromUTF16(cached_area_->GetKey(index)); +WebString LocalStorageArea::Key(unsigned index, bool* did_decrease_iterator) { + return WebString::FromUTF16( + cached_area_->GetKey(index, did_decrease_iterator)); } WebString LocalStorageArea::GetItem(const WebString& key) { diff --git a/chromium/content/renderer/dom_storage/local_storage_area.h b/chromium/content/renderer/dom_storage/local_storage_area.h index 55967276a12..01ed6f22673 100644 --- a/chromium/content/renderer/dom_storage/local_storage_area.h +++ b/chromium/content/renderer/dom_storage/local_storage_area.h @@ -22,7 +22,7 @@ class LocalStorageArea : public blink::WebStorageArea { // blink::WebStorageArea: unsigned length() override; - blink::WebString Key(unsigned index) override; + blink::WebString Key(unsigned index, bool* did_decrease_iterator) override; blink::WebString GetItem(const blink::WebString& key) override; void SetItem(const blink::WebString& key, const blink::WebString& value, 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 a56c6def416..ffa21c9200d 100644 --- a/chromium/content/renderer/dom_storage/local_storage_cached_area.cc +++ b/chromium/content/renderer/dom_storage/local_storage_cached_area.cc @@ -15,12 +15,13 @@ #include "base/time/time.h" #include "components/services/leveldb/public/cpp/util.h" #include "content/common/dom_storage/dom_storage_map.h" -#include "content/common/storage_partition_service.mojom.h" #include "content/renderer/dom_storage/local_storage_area.h" #include "content/renderer/dom_storage/local_storage_cached_areas.h" #include "content/renderer/dom_storage/session_web_storage_namespace_impl.h" #include "content/renderer/render_thread_impl.h" #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/web_url.h" #include "third_party/blink/public/web/web_storage_event_dispatcher.h" @@ -32,11 +33,11 @@ namespace { // are serialized on disk. enum class StorageFormat : uint8_t { UTF16 = 0, Latin1 = 1 }; -class GetAllCallback : public mojom::LevelDBWrapperGetAllCallback { +class GetAllCallback : public blink::mojom::StorageAreaGetAllCallback { public: - static mojom::LevelDBWrapperGetAllCallbackAssociatedPtrInfo CreateAndBind( + static blink::mojom::StorageAreaGetAllCallbackAssociatedPtrInfo CreateAndBind( base::OnceCallback<void(bool)> callback) { - mojom::LevelDBWrapperGetAllCallbackAssociatedPtrInfo ptr_info; + blink::mojom::StorageAreaGetAllCallbackAssociatedPtrInfo ptr_info; auto request = mojo::MakeRequest(&ptr_info); mojo::MakeStrongAssociatedBinding( base::WrapUnique(new GetAllCallback(std::move(callback))), @@ -74,9 +75,9 @@ void UnpackSource(const std::string& source, LocalStorageCachedArea::LocalStorageCachedArea( const std::string& namespace_id, const url::Origin& origin, - mojom::SessionStorageNamespace* session_namespace, + blink::mojom::SessionStorageNamespace* session_namespace, LocalStorageCachedAreas* cached_areas, - blink::scheduler::WebMainThreadScheduler* main_thread_scheduler) + blink::scheduler::WebThreadScheduler* main_thread_scheduler) : namespace_id_(namespace_id), origin_(origin), binding_(this), @@ -84,33 +85,33 @@ LocalStorageCachedArea::LocalStorageCachedArea( main_thread_scheduler_(main_thread_scheduler), weak_factory_(this) { DCHECK(!namespace_id_.empty()); - - mojom::LevelDBWrapperAssociatedPtrInfo wrapper_ptr_info; + blink::mojom::StorageAreaAssociatedPtrInfo wrapper_ptr_info; session_namespace->OpenArea(origin_, mojo::MakeRequest(&wrapper_ptr_info)); leveldb_.Bind(std::move(wrapper_ptr_info), main_thread_scheduler->IPCTaskRunner()); - mojom::LevelDBObserverAssociatedPtrInfo ptr_info; + blink::mojom::StorageAreaObserverAssociatedPtrInfo ptr_info; binding_.Bind(mojo::MakeRequest(&ptr_info), main_thread_scheduler->IPCTaskRunner()); + leveldb_->AddObserver(std::move(ptr_info)); } LocalStorageCachedArea::LocalStorageCachedArea( const url::Origin& origin, - mojom::StoragePartitionService* storage_partition_service, + blink::mojom::StoragePartitionService* storage_partition_service, LocalStorageCachedAreas* cached_areas, - blink::scheduler::WebMainThreadScheduler* main_thread_scheduler) + blink::scheduler::WebThreadScheduler* main_thread_scheduler) : origin_(origin), binding_(this), cached_areas_(cached_areas), main_thread_scheduler_(main_thread_scheduler), weak_factory_(this) { DCHECK(namespace_id_.empty()); - mojom::LevelDBWrapperPtrInfo wrapper_ptr_info; + blink::mojom::StorageAreaPtrInfo wrapper_ptr_info; storage_partition_service->OpenLocalStorage( origin_, mojo::MakeRequest(&wrapper_ptr_info)); leveldb_.Bind(std::move(wrapper_ptr_info), main_thread_scheduler->IPCTaskRunner()); - mojom::LevelDBObserverAssociatedPtrInfo ptr_info; + blink::mojom::StorageAreaObserverAssociatedPtrInfo ptr_info; binding_.Bind(mojo::MakeRequest(&ptr_info), main_thread_scheduler->IPCTaskRunner()); leveldb_->AddObserver(std::move(ptr_info)); @@ -123,9 +124,11 @@ unsigned LocalStorageCachedArea::GetLength() { return map_->Length(); } -base::NullableString16 LocalStorageCachedArea::GetKey(unsigned index) { +base::NullableString16 LocalStorageCachedArea::GetKey( + unsigned index, + bool* did_decrease_iterator) { EnsureLoaded(); - return map_->Key(index); + return map_->Key(index, did_decrease_iterator); } base::NullableString16 LocalStorageCachedArea::GetItem( @@ -433,7 +436,6 @@ void LocalStorageCachedArea::KeyDeleted(const std::vector<uint8_t>& key, } void LocalStorageCachedArea::AllDeleted(const std::string& source) { - DCHECK(!IsSessionStorage()); GURL page_url; std::string storage_area_id; UnpackSource(source, &page_url, &storage_area_id); @@ -457,9 +459,18 @@ void LocalStorageCachedArea::AllDeleted(const std::string& source) { } } - blink::WebStorageEventDispatcher::DispatchLocalStorageEvent( - blink::WebString(), blink::WebString(), blink::WebString(), - origin_.GetURL(), page_url, originating_area); + if (IsSessionStorage()) { + SessionWebStorageNamespaceImpl session_namespace_for_event_dispatch( + namespace_id_, nullptr); + blink::WebStorageEventDispatcher::DispatchSessionStorageEvent( + blink::WebString(), blink::WebString(), blink::WebString(), + origin_.GetURL(), page_url, session_namespace_for_event_dispatch, + originating_area); + } else { + blink::WebStorageEventDispatcher::DispatchLocalStorageEvent( + blink::WebString(), blink::WebString(), blink::WebString(), + origin_.GetURL(), page_url, originating_area); + } } void LocalStorageCachedArea::ShouldSendOldValueOnMutations(bool value) { @@ -513,12 +524,12 @@ void LocalStorageCachedArea::EnsureLoaded() { base::TimeTicks before = base::TimeTicks::Now(); ignore_all_mutations_ = true; - leveldb::mojom::DatabaseError status = leveldb::mojom::DatabaseError::OK; - std::vector<content::mojom::KeyValuePtr> data; + bool success = false; + std::vector<blink::mojom::KeyValuePtr> data; leveldb_->GetAll(GetAllCallback::CreateAndBind( base::BindOnce(&LocalStorageCachedArea::OnGetAllComplete, weak_factory_.GetWeakPtr())), - &status, &data); + &success, &data); DOMStorageValuesMap values; bool is_session_storage = IsSessionStorage(); diff --git a/chromium/content/renderer/dom_storage/local_storage_cached_area.h b/chromium/content/renderer/dom_storage/local_storage_cached_area.h index a4b8b03b4a8..9780e7ad402 100644 --- a/chromium/content/renderer/dom_storage/local_storage_cached_area.h +++ b/chromium/content/renderer/dom_storage/local_storage_cached_area.h @@ -12,16 +12,21 @@ #include "base/strings/nullable_string16.h" #include "content/common/content_export.h" #include "content/common/dom_storage/dom_storage_map.h" -#include "content/common/leveldb_wrapper.mojom.h" #include "content/common/possibly_associated_interface_ptr.h" #include "mojo/public/cpp/bindings/associated_binding.h" +#include "third_party/blink/public/mojom/dom_storage/storage_area.mojom.h" #include "third_party/blink/public/platform/web_scoped_virtual_time_pauser.h" #include "url/gurl.h" #include "url/origin.h" namespace blink { +namespace mojom { +class SessionStorageNamespace; +class StoragePartitionService; +} // namespace mojom + namespace scheduler { -class WebMainThreadScheduler; +class WebThreadScheduler; } } // namespace blink @@ -29,11 +34,6 @@ namespace content { class LocalStorageArea; class LocalStorageCachedAreas; -namespace mojom { -class StoragePartitionService; -class SessionStorageNamespace; -} - // An in-process implementation of LocalStorage using a LevelDB Mojo service. // Maintains a complete cache of the origin's Map of key/value pairs for fast // access. The cache is primed on first access and changes are written to the @@ -44,24 +44,26 @@ class SessionStorageNamespace; // objects. // TODO(dmurph): Rename to remove LocalStorage. class CONTENT_EXPORT LocalStorageCachedArea - : public mojom::LevelDBObserver, + : public blink::mojom::StorageAreaObserver, public base::RefCounted<LocalStorageCachedArea> { public: LocalStorageCachedArea( const std::string& namespace_id, const url::Origin& origin, - mojom::SessionStorageNamespace* session_namespace, + blink::mojom::SessionStorageNamespace* session_namespace, LocalStorageCachedAreas* cached_areas, - blink::scheduler::WebMainThreadScheduler* main_thread_scheduler); + blink::scheduler::WebThreadScheduler* main_thread_scheduler); LocalStorageCachedArea( const url::Origin& origin, - mojom::StoragePartitionService* storage_partition_service, + blink::mojom::StoragePartitionService* storage_partition_service, LocalStorageCachedAreas* cached_areas, - blink::scheduler::WebMainThreadScheduler* main_thread_scheduler); + blink::scheduler::WebThreadScheduler* main_thread_scheduler); // These correspond to blink::WebStorageArea. unsigned GetLength(); - base::NullableString16 GetKey(unsigned index); + // See DOMStorageMap for the meaning of |did_decrease_iterator|. + base::NullableString16 GetKey(unsigned index, + bool* did_decrease_iterator = nullptr); base::NullableString16 GetItem(const base::string16& key); bool SetItem(const base::string16& key, const base::string16& value, @@ -146,13 +148,13 @@ class CONTENT_EXPORT LocalStorageCachedArea bool ignore_all_mutations_ = false; // See ShouldSendOldValueOnMutations(). bool should_send_old_value_on_mutations_ = true; - content::PossiblyAssociatedInterfacePtr<mojom::LevelDBWrapper> leveldb_; - mojo::AssociatedBinding<mojom::LevelDBObserver> binding_; + content::PossiblyAssociatedInterfacePtr<blink::mojom::StorageArea> leveldb_; + mojo::AssociatedBinding<blink::mojom::StorageAreaObserver> binding_; LocalStorageCachedAreas* cached_areas_; std::map<std::string, LocalStorageArea*> areas_; // Not owned. - blink::scheduler::WebMainThreadScheduler* main_thread_scheduler_; + blink::scheduler::WebThreadScheduler* main_thread_scheduler_; base::WeakPtrFactory<LocalStorageCachedArea> weak_factory_; diff --git a/chromium/content/renderer/dom_storage/local_storage_cached_area_unittest.cc b/chromium/content/renderer/dom_storage/local_storage_cached_area_unittest.cc index 341cbc23f33..2134e99cc92 100644 --- a/chromium/content/renderer/dom_storage/local_storage_cached_area_unittest.cc +++ b/chromium/content/renderer/dom_storage/local_storage_cached_area_unittest.cc @@ -10,7 +10,6 @@ #include "base/bind.h" #include "base/strings/utf_string_conversions.h" -#include "content/common/leveldb_wrapper.mojom.h" #include "content/public/test/test_browser_thread_bundle.h" #include "content/renderer/dom_storage/local_storage_cached_areas.h" #include "content/renderer/dom_storage/mock_leveldb_wrapper.h" @@ -77,7 +76,7 @@ class LocalStorageCachedAreaTest : public testing::Test { protected: TestBrowserThreadBundle test_browser_thread_bundle_; MockLevelDBWrapper mock_leveldb_wrapper_; - std::unique_ptr<blink::scheduler::WebMainThreadScheduler> renderer_scheduler_; + std::unique_ptr<blink::scheduler::WebThreadScheduler> renderer_scheduler_; LocalStorageCachedAreas cached_areas_; }; @@ -190,7 +189,7 @@ TEST_F(LocalStorageCachedAreaTest, Setters) { TEST_F(LocalStorageCachedAreaTest, MutationsAreIgnoredUntilLoadCompletion) { scoped_refptr<LocalStorageCachedArea> cached_area = cached_areas_.GetCachedArea(kOrigin); - mojom::LevelDBObserver* observer = cached_area.get(); + blink::mojom::StorageAreaObserver* observer = cached_area.get(); EXPECT_TRUE(cached_area->GetItem(kKey).is_null()); EXPECT_TRUE(IsCacheLoaded(cached_area.get())); @@ -243,7 +242,7 @@ TEST_F(LocalStorageCachedAreaTest, MutationsAreIgnoredUntilClearCompletion) { TEST_F(LocalStorageCachedAreaTest, KeyMutationsAreIgnoredUntilCompletion) { scoped_refptr<LocalStorageCachedArea> cached_area = cached_areas_.GetCachedArea(kOrigin); - mojom::LevelDBObserver* observer = cached_area.get(); + blink::mojom::StorageAreaObserver* observer = cached_area.get(); // SetItem EXPECT_TRUE(cached_area->SetItem(kKey, kValue, kPageUrl, kStorageAreaId)); 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 1f2133c87d6..7c2327ac3df 100644 --- a/chromium/content/renderer/dom_storage/local_storage_cached_areas.cc +++ b/chromium/content/renderer/dom_storage/local_storage_cached_areas.cc @@ -11,29 +11,36 @@ #include "content/public/common/content_features.h" #include "content/renderer/dom_storage/local_storage_cached_area.h" #include "content/renderer/render_thread_impl.h" +#include "third_party/blink/public/mojom/dom_storage/storage_partition_service.mojom.h" namespace content { namespace { const size_t kTotalCacheLimitInBytesLowEnd = 1 * 1024 * 1024; const size_t kTotalCacheLimitInBytes = 5 * 1024 * 1024; +const constexpr int64_t kDOMStorageObjectPrefix = 0x0001020304050607; +const constexpr int64_t kDOMStorageObjectPostfix = 0x08090a0b0c0d0e0f; + // An empty namespace is the local storage namespace. constexpr const char kLocalStorageNamespaceId[] = ""; } // namespace LocalStorageCachedAreas::LocalStorageCachedAreas( - mojom::StoragePartitionService* storage_partition_service, - blink::scheduler::WebMainThreadScheduler* main_thread_scheduler) + blink::mojom::StoragePartitionService* storage_partition_service, + blink::scheduler::WebThreadScheduler* main_thread_scheduler) : storage_partition_service_(storage_partition_service), total_cache_limit_(base::SysInfo::IsLowEndDevice() ? kTotalCacheLimitInBytesLowEnd : kTotalCacheLimitInBytes), main_thread_scheduler_(main_thread_scheduler) {} -LocalStorageCachedAreas::~LocalStorageCachedAreas() {} +LocalStorageCachedAreas::~LocalStorageCachedAreas() { + CHECK(sequence_checker_.CalledOnValidSequence()); +} scoped_refptr<LocalStorageCachedArea> LocalStorageCachedAreas::GetCachedArea( const url::Origin& origin) { + CHECK(sequence_checker_.CalledOnValidSequence()); return GetCachedArea(kLocalStorageNamespaceId, origin, main_thread_scheduler_); } @@ -42,6 +49,7 @@ scoped_refptr<LocalStorageCachedArea> LocalStorageCachedAreas::GetSessionStorageArea(const std::string& namespace_id, const url::Origin& origin) { DCHECK_NE(kLocalStorageNamespaceId, namespace_id); + CHECK(sequence_checker_.CalledOnValidSequence()); return GetCachedArea(namespace_id, origin, main_thread_scheduler_); } @@ -51,6 +59,7 @@ void LocalStorageCachedAreas::CloneNamespace( DCHECK(base::FeatureList::IsEnabled(features::kMojoSessionStorage)); DCHECK_EQ(kSessionStorageNamespaceIdLength, source_namespace.size()); DCHECK_EQ(kSessionStorageNamespaceIdLength, destination_namespace.size()); + CHECK(sequence_checker_.CalledOnValidSequence()); auto namespace_it = cached_namespaces_.find(source_namespace); if (namespace_it == cached_namespaces_.end()) { @@ -67,6 +76,7 @@ void LocalStorageCachedAreas::CloneNamespace( } size_t LocalStorageCachedAreas::TotalCacheSize() const { + CHECK(sequence_checker_.CalledOnValidSequence()); size_t total = 0; for (const auto& it : cached_namespaces_) total += it.second.TotalCacheSize(); @@ -74,6 +84,7 @@ size_t LocalStorageCachedAreas::TotalCacheSize() const { } void LocalStorageCachedAreas::ClearAreasIfNeeded() { + CHECK(sequence_checker_.CalledOnValidSequence()); if (TotalCacheSize() < total_cache_limit_) return; @@ -84,7 +95,8 @@ void LocalStorageCachedAreas::ClearAreasIfNeeded() { scoped_refptr<LocalStorageCachedArea> LocalStorageCachedAreas::GetCachedArea( const std::string& namespace_id, const url::Origin& origin, - blink::scheduler::WebMainThreadScheduler* scheduler) { + blink::scheduler::WebThreadScheduler* scheduler) { + CHECK(sequence_checker_.CalledOnValidSequence()); // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. enum class CacheMetrics { @@ -102,6 +114,7 @@ scoped_refptr<LocalStorageCachedArea> LocalStorageCachedAreas::GetCachedArea( metric = CacheMetrics::kMiss; } else { dom_namespace = &namespace_it->second; + dom_namespace->CheckPrefixes(); auto cache_it = dom_namespace->cached_areas.find(origin); if (cache_it == dom_namespace->cached_areas.end()) { metric = CacheMetrics::kMiss; @@ -124,6 +137,7 @@ scoped_refptr<LocalStorageCachedArea> LocalStorageCachedAreas::GetCachedArea( if (!dom_namespace) { dom_namespace = &cached_namespaces_[namespace_id]; } + dom_namespace->CheckPrefixes(); if (namespace_id == kLocalStorageNamespaceId) { result = base::MakeRefCounted<LocalStorageCachedArea>( origin, storage_partition_service_, this, scheduler); @@ -143,12 +157,21 @@ scoped_refptr<LocalStorageCachedArea> LocalStorageCachedAreas::GetCachedArea( return result; } -LocalStorageCachedAreas::DOMStorageNamespace::DOMStorageNamespace() {} -LocalStorageCachedAreas::DOMStorageNamespace::~DOMStorageNamespace() {} +LocalStorageCachedAreas::DOMStorageNamespace::DOMStorageNamespace() + : prefix(kDOMStorageObjectPrefix), postfix(kDOMStorageObjectPostfix) {} +LocalStorageCachedAreas::DOMStorageNamespace::~DOMStorageNamespace() { + CheckPrefixes(); +} LocalStorageCachedAreas::DOMStorageNamespace::DOMStorageNamespace( LocalStorageCachedAreas::DOMStorageNamespace&& other) = default; +void LocalStorageCachedAreas::DOMStorageNamespace::CheckPrefixes() const { + CHECK_EQ(kDOMStorageObjectPrefix, prefix) << "Memory corruption?"; + CHECK_EQ(kDOMStorageObjectPostfix, postfix) << "Memory corruption?"; +} + size_t LocalStorageCachedAreas::DOMStorageNamespace::TotalCacheSize() const { + CheckPrefixes(); size_t total = 0; for (const auto& it : cached_areas) total += it.second.get()->memory_used(); @@ -156,6 +179,7 @@ size_t LocalStorageCachedAreas::DOMStorageNamespace::TotalCacheSize() const { } bool LocalStorageCachedAreas::DOMStorageNamespace::CleanUpUnusedAreas() { + CheckPrefixes(); base::EraseIf(cached_areas, [](auto& pair) { return pair.second->HasOneRef(); }); return cached_areas.empty(); diff --git a/chromium/content/renderer/dom_storage/local_storage_cached_areas.h b/chromium/content/renderer/dom_storage/local_storage_cached_areas.h index 53ad4de71ce..390b7eddf4c 100644 --- a/chromium/content/renderer/dom_storage/local_storage_cached_areas.h +++ b/chromium/content/renderer/dom_storage/local_storage_cached_areas.h @@ -5,29 +5,31 @@ #ifndef CONTENT_RENDERER_DOM_STORAGE_LOCAL_STORAGE_CACHED_AREAS_H_ #define CONTENT_RENDERER_DOM_STORAGE_LOCAL_STORAGE_CACHED_AREAS_H_ +#include <array> #include <map> #include <string> #include "base/containers/flat_map.h" #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/sequence_checker.h" #include "content/common/content_export.h" -#include "content/common/storage_partition_service.mojom.h" +#include "third_party/blink/public/mojom/dom_storage/session_storage_namespace.mojom.h" #include "url/origin.h" namespace blink { +namespace mojom { +class StoragePartitionService; +} + namespace scheduler { -class WebMainThreadScheduler; +class WebThreadScheduler; } } // namespace blink namespace content { class LocalStorageCachedArea; -namespace mojom { -class StoragePartitionService; -} - // Keeps a map of all the LocalStorageCachedArea objects in a renderer. This is // needed because we can have n LocalStorageArea objects for the same origin but // we want just one LocalStorageCachedArea to service them (no point in having @@ -36,8 +38,8 @@ class StoragePartitionService; class CONTENT_EXPORT LocalStorageCachedAreas { public: LocalStorageCachedAreas( - mojom::StoragePartitionService* storage_partition_service, - blink::scheduler::WebMainThreadScheduler* main_thread_scheduler); + blink::mojom::StoragePartitionService* storage_partition_service, + blink::scheduler::WebThreadScheduler* main_thread_scheduler); ~LocalStorageCachedAreas(); // Returns, creating if necessary, a cached storage area for the given origin. @@ -53,7 +55,10 @@ class CONTENT_EXPORT LocalStorageCachedAreas { size_t TotalCacheSize() const; - void set_cache_limit_for_testing(size_t limit) { total_cache_limit_ = limit; } + void set_cache_limit_for_testing(size_t limit) { + CHECK(sequence_checker_.CalledOnValidSequence()); + total_cache_limit_ = limit; + } private: void ClearAreasIfNeeded(); @@ -61,9 +66,13 @@ class CONTENT_EXPORT LocalStorageCachedAreas { scoped_refptr<LocalStorageCachedArea> GetCachedArea( const std::string& namespace_id, const url::Origin& origin, - blink::scheduler::WebMainThreadScheduler* scheduler); + blink::scheduler::WebThreadScheduler* scheduler); - mojom::StoragePartitionService* const storage_partition_service_; + // TODO(dmurph): Remove release check when crashing has stopped. + // http://crbug.com/857464 + base::SequenceCheckerImpl sequence_checker_; + + blink::mojom::StoragePartitionService* const storage_partition_service_; struct DOMStorageNamespace { public: @@ -72,13 +81,19 @@ class CONTENT_EXPORT LocalStorageCachedAreas { DOMStorageNamespace(DOMStorageNamespace&& other); DOMStorageNamespace& operator=(DOMStorageNamespace&&) = default; + void CheckPrefixes() const; + size_t TotalCacheSize() const; // Returns true if this namespace is totally unused and can be deleted. bool CleanUpUnusedAreas(); - mojom::SessionStorageNamespacePtr session_storage_namespace; + // TODO(dmurph): Remove the prefix & postfix after memory corruption is + // solved. + int64_t prefix; + blink::mojom::SessionStorageNamespacePtr session_storage_namespace; base::flat_map<url::Origin, scoped_refptr<LocalStorageCachedArea>> cached_areas; + int64_t postfix; DISALLOW_COPY_AND_ASSIGN(DOMStorageNamespace); }; @@ -87,7 +102,7 @@ class CONTENT_EXPORT LocalStorageCachedAreas { size_t total_cache_limit_; // Not owned. - blink::scheduler::WebMainThreadScheduler* main_thread_scheduler_; + blink::scheduler::WebThreadScheduler* main_thread_scheduler_; DISALLOW_COPY_AND_ASSIGN(LocalStorageCachedAreas); }; diff --git a/chromium/content/renderer/dom_storage/local_storage_cached_areas_unittest.cc b/chromium/content/renderer/dom_storage/local_storage_cached_areas_unittest.cc index 15704b82293..70d5b0d97be 100644 --- a/chromium/content/renderer/dom_storage/local_storage_cached_areas_unittest.cc +++ b/chromium/content/renderer/dom_storage/local_storage_cached_areas_unittest.cc @@ -11,12 +11,25 @@ #include "content/public/common/content_features.h" #include "content/renderer/dom_storage/local_storage_cached_area.h" #include "content/renderer/dom_storage/mock_leveldb_wrapper.h" +#include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/platform/scheduler/test/fake_renderer_scheduler.h" namespace content { -TEST(LocalStorageCachedAreasTest, CacheLimit) { - base::test::ScopedTaskEnvironment scoped_task_environment; +class LocalStorageCachedAreasTest : public testing::Test { + // testing::Test: + void TearDown() override { + // Some of these tests close message pipes which serve as master interfaces + // to other associated interfaces; this in turn schedules tasks to invoke + // the associated interfaces' error handlers, and local storage code relies + // on those handlers running in order to avoid memory leaks at shutdown. + scoped_task_environment_.RunUntilIdle(); + } + + base::test::ScopedTaskEnvironment scoped_task_environment_; +}; + +TEST_F(LocalStorageCachedAreasTest, CacheLimit) { const url::Origin kOrigin = url::Origin::Create(GURL("http://dom_storage1/")); const url::Origin kOrigin2 = url::Origin::Create(GURL("http://dom_storage2/")); @@ -59,8 +72,7 @@ TEST(LocalStorageCachedAreasTest, CacheLimit) { EXPECT_EQ(cached_area2->memory_used(), cached_areas.TotalCacheSize()); } -TEST(LocalStorageCachedAreasTest, CloneBeforeGetArea) { - base::test::ScopedTaskEnvironment scoped_task_environment; +TEST_F(LocalStorageCachedAreasTest, CloneBeforeGetArea) { base::test::ScopedFeatureList feature_list; feature_list.InitAndEnableFeature(features::kMojoSessionStorage); const std::string kNamespace1 = base::GenerateGUID(); diff --git a/chromium/content/renderer/dom_storage/local_storage_namespace.cc b/chromium/content/renderer/dom_storage/local_storage_namespace.cc index d493cc4a3f1..8ec1992b762 100644 --- a/chromium/content/renderer/dom_storage/local_storage_namespace.cc +++ b/chromium/content/renderer/dom_storage/local_storage_namespace.cc @@ -24,6 +24,10 @@ LocalStorageNamespace::LocalStorageNamespace( LocalStorageNamespace::~LocalStorageNamespace() { } +blink::WebString LocalStorageNamespace::GetNamespaceId() const { + return blink::WebString(); +} + WebStorageArea* LocalStorageNamespace::CreateStorageArea( const blink::WebSecurityOrigin& origin) { return new LocalStorageArea( diff --git a/chromium/content/renderer/dom_storage/local_storage_namespace.h b/chromium/content/renderer/dom_storage/local_storage_namespace.h index 65fc4f17956..b0ce38458fe 100644 --- a/chromium/content/renderer/dom_storage/local_storage_namespace.h +++ b/chromium/content/renderer/dom_storage/local_storage_namespace.h @@ -22,6 +22,9 @@ class LocalStorageNamespace : public blink::WebStorageNamespace { // blink::WebStorageNamespace: blink::WebStorageArea* CreateStorageArea( const blink::WebSecurityOrigin& origin) override; + + blink::WebString GetNamespaceId() const override; + bool IsSameNamespace(const WebStorageNamespace&) const override; private: diff --git a/chromium/content/renderer/dom_storage/mock_leveldb_wrapper.cc b/chromium/content/renderer/dom_storage/mock_leveldb_wrapper.cc index 4dcdf113160..3cc34427cc4 100644 --- a/chromium/content/renderer/dom_storage/mock_leveldb_wrapper.cc +++ b/chromium/content/renderer/dom_storage/mock_leveldb_wrapper.cc @@ -11,14 +11,14 @@ namespace content { class MockLevelDBWrapper::MockSessionStorageNamespace - : public mojom::SessionStorageNamespace { + : public blink::mojom::SessionStorageNamespace { public: MockSessionStorageNamespace(std::string namespace_id, MockLevelDBWrapper* wrapper) : namespace_id_(std::move(namespace_id)), wrapper_(wrapper) {} void OpenArea(const url::Origin& origin, - mojom::LevelDBWrapperAssociatedRequest database) override { + blink::mojom::StorageAreaAssociatedRequest database) override { bindings_.AddBinding(wrapper_, std::move(database)); } @@ -31,7 +31,7 @@ class MockLevelDBWrapper::MockSessionStorageNamespace private: std::string namespace_id_; MockLevelDBWrapper* wrapper_; - mojo::AssociatedBindingSet<mojom::LevelDBWrapper> bindings_; + mojo::AssociatedBindingSet<blink::mojom::StorageArea> bindings_; }; MockLevelDBWrapper::MockLevelDBWrapper() {} @@ -39,20 +39,20 @@ MockLevelDBWrapper::~MockLevelDBWrapper() {} void MockLevelDBWrapper::OpenLocalStorage( const url::Origin& origin, - mojom::LevelDBWrapperRequest database) { + blink::mojom::StorageAreaRequest database) { bindings_.AddBinding(this, std::move(database)); } void MockLevelDBWrapper::OpenSessionStorage( const std::string& namespace_id, - mojom::SessionStorageNamespaceRequest request) { + blink::mojom::SessionStorageNamespaceRequest request) { namespace_bindings_.AddBinding( std::make_unique<MockSessionStorageNamespace>(namespace_id, this), std::move(request)); } void MockLevelDBWrapper::AddObserver( - mojom::LevelDBObserverAssociatedPtrInfo observer) {} + blink::mojom::StorageAreaObserverAssociatedPtrInfo observer) {} void MockLevelDBWrapper::Put( const std::vector<uint8_t>& key, @@ -89,22 +89,23 @@ void MockLevelDBWrapper::Get(const std::vector<uint8_t>& key, GetCallback callback) {} void MockLevelDBWrapper::GetAll( - mojom::LevelDBWrapperGetAllCallbackAssociatedPtrInfo complete_callback, + blink::mojom::StorageAreaGetAllCallbackAssociatedPtrInfo complete_callback, GetAllCallback callback) { - mojom::LevelDBWrapperGetAllCallbackAssociatedPtr complete_ptr; + blink::mojom::StorageAreaGetAllCallbackAssociatedPtr complete_ptr; complete_ptr.Bind(std::move(complete_callback)); - pending_callbacks_.push_back(base::BindOnce( - &mojom::LevelDBWrapperGetAllCallback::Complete, std::move(complete_ptr))); + pending_callbacks_.push_back( + base::BindOnce(&blink::mojom::StorageAreaGetAllCallback::Complete, + std::move(complete_ptr))); observed_get_all_ = true; - std::vector<mojom::KeyValuePtr> all; + std::vector<blink::mojom::KeyValuePtr> all; for (const auto& it : get_all_return_values_) { - mojom::KeyValuePtr kv = mojom::KeyValue::New(); + auto kv = blink::mojom::KeyValue::New(); kv->key = it.first; kv->value = it.second; all.push_back(std::move(kv)); } - std::move(callback).Run(leveldb::mojom::DatabaseError::OK, std::move(all)); + std::move(callback).Run(true, std::move(all)); } } // namespace content diff --git a/chromium/content/renderer/dom_storage/mock_leveldb_wrapper.h b/chromium/content/renderer/dom_storage/mock_leveldb_wrapper.h index 8c96fda2e03..d459ddbad73 100644 --- a/chromium/content/renderer/dom_storage/mock_leveldb_wrapper.h +++ b/chromium/content/renderer/dom_storage/mock_leveldb_wrapper.h @@ -5,18 +5,18 @@ #ifndef CONTENT_RENDERER_DOM_STORAGE_MOCK_LEVELDB_WRAPPER_H #define CONTENT_RENDERER_DOM_STORAGE_MOCK_LEVELDB_WRAPPER_H -#include "content/common/leveldb_wrapper.mojom.h" -#include "content/common/storage_partition_service.mojom.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "mojo/public/cpp/bindings/strong_binding_set.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/mojom/dom_storage/storage_area.mojom.h" +#include "third_party/blink/public/mojom/dom_storage/storage_partition_service.mojom.h" namespace content { // Mock LevelDBWrapper that records all read and write events. It also // implements a mock StoragePartitionService. -class MockLevelDBWrapper : public mojom::StoragePartitionService, - public mojom::LevelDBWrapper { +class MockLevelDBWrapper : public blink::mojom::StoragePartitionService, + public blink::mojom::StorageArea { public: using ResultCallback = base::OnceCallback<void(bool)>; @@ -25,13 +25,14 @@ class MockLevelDBWrapper : public mojom::StoragePartitionService, // StoragePartitionService implementation: void OpenLocalStorage(const url::Origin& origin, - mojom::LevelDBWrapperRequest database) override; + blink::mojom::StorageAreaRequest database) override; void OpenSessionStorage( const std::string& namespace_id, - mojom::SessionStorageNamespaceRequest request) override; + blink::mojom::SessionStorageNamespaceRequest request) override; - // LevelDBWrapper implementation: - void AddObserver(mojom::LevelDBObserverAssociatedPtrInfo observer) override; + // StorageArea implementation: + void AddObserver( + blink::mojom::StorageAreaObserverAssociatedPtrInfo observer) override; void Put(const std::vector<uint8_t>& key, const std::vector<uint8_t>& value, @@ -49,9 +50,9 @@ class MockLevelDBWrapper : public mojom::StoragePartitionService, void Get(const std::vector<uint8_t>& key, GetCallback callback) override; - void GetAll( - mojom::LevelDBWrapperGetAllCallbackAssociatedPtrInfo complete_callback, - GetAllCallback callback) override; + void GetAll(blink::mojom::StorageAreaGetAllCallbackAssociatedPtrInfo + complete_callback, + GetAllCallback callback) override; // Methods and members for use by test fixtures. bool HasBindings() { return !bindings_.empty(); } @@ -117,8 +118,9 @@ class MockLevelDBWrapper : public mojom::StoragePartitionService, std::map<std::vector<uint8_t>, std::vector<uint8_t>> get_all_return_values_; - mojo::BindingSet<mojom::LevelDBWrapper> bindings_; - mojo::StrongBindingSet<mojom::SessionStorageNamespace> namespace_bindings_; + mojo::BindingSet<blink::mojom::StorageArea> bindings_; + mojo::StrongBindingSet<blink::mojom::SessionStorageNamespace> + namespace_bindings_; }; } // namespace content diff --git a/chromium/content/renderer/dom_storage/session_web_storage_namespace_impl.cc b/chromium/content/renderer/dom_storage/session_web_storage_namespace_impl.cc index 8745849d9b3..b2d9c70b632 100644 --- a/chromium/content/renderer/dom_storage/session_web_storage_namespace_impl.cc +++ b/chromium/content/renderer/dom_storage/session_web_storage_namespace_impl.cc @@ -31,11 +31,13 @@ WebStorageArea* SessionWebStorageNamespaceImpl::CreateStorageArea( origin)); } +blink::WebString SessionWebStorageNamespaceImpl::GetNamespaceId() const { + return blink::WebString::FromASCII(namespace_id_); +} + bool SessionWebStorageNamespaceImpl::IsSameNamespace( const WebStorageNamespace& other) const { - const SessionWebStorageNamespaceImpl* other_impl = - static_cast<const SessionWebStorageNamespaceImpl*>(&other); - return namespace_id_ == other_impl->namespace_id_; + return GetNamespaceId() == other.GetNamespaceId(); } } // namespace content diff --git a/chromium/content/renderer/dom_storage/session_web_storage_namespace_impl.h b/chromium/content/renderer/dom_storage/session_web_storage_namespace_impl.h index d69b8f3e490..52830aa2cc7 100644 --- a/chromium/content/renderer/dom_storage/session_web_storage_namespace_impl.h +++ b/chromium/content/renderer/dom_storage/session_web_storage_namespace_impl.h @@ -23,6 +23,7 @@ class SessionWebStorageNamespaceImpl : public blink::WebStorageNamespace { // blink::WebStorageNamespace: blink::WebStorageArea* CreateStorageArea( const blink::WebSecurityOrigin& origin) override; + blink::WebString GetNamespaceId() const override; bool IsSameNamespace(const WebStorageNamespace&) const override; private: diff --git a/chromium/content/renderer/dom_storage/webstoragearea_impl.cc b/chromium/content/renderer/dom_storage/webstoragearea_impl.cc index e47617f860d..f3041216603 100644 --- a/chromium/content/renderer/dom_storage/webstoragearea_impl.cc +++ b/chromium/content/renderer/dom_storage/webstoragearea_impl.cc @@ -50,8 +50,9 @@ unsigned WebStorageAreaImpl::length() { return cached_area_->GetLength(connection_id_); } -WebString WebStorageAreaImpl::Key(unsigned index) { - return WebString::FromUTF16(cached_area_->GetKey(connection_id_, index)); +WebString WebStorageAreaImpl::Key(unsigned index, bool* did_decrease_iterator) { + return WebString::FromUTF16( + cached_area_->GetKey(connection_id_, index, did_decrease_iterator)); } WebString WebStorageAreaImpl::GetItem(const WebString& key) { diff --git a/chromium/content/renderer/dom_storage/webstoragearea_impl.h b/chromium/content/renderer/dom_storage/webstoragearea_impl.h index ca47ab4e485..e7c6bcdcd9d 100644 --- a/chromium/content/renderer/dom_storage/webstoragearea_impl.h +++ b/chromium/content/renderer/dom_storage/webstoragearea_impl.h @@ -27,7 +27,7 @@ class WebStorageAreaImpl : public blink::WebStorageArea { // See WebStorageArea.h for documentation on these functions. unsigned length() override; - blink::WebString Key(unsigned index) override; + blink::WebString Key(unsigned index, bool* did_decrease_iterator) override; blink::WebString GetItem(const blink::WebString& key) override; void SetItem(const blink::WebString& key, const blink::WebString& value, diff --git a/chromium/content/renderer/dom_storage/webstoragenamespace_impl.cc b/chromium/content/renderer/dom_storage/webstoragenamespace_impl.cc index 377d7961a16..cc8d7998d51 100644 --- a/chromium/content/renderer/dom_storage/webstoragenamespace_impl.cc +++ b/chromium/content/renderer/dom_storage/webstoragenamespace_impl.cc @@ -39,11 +39,13 @@ WebStorageNamespace* WebStorageNamespaceImpl::copy() { return nullptr; } +blink::WebString WebStorageNamespaceImpl::GetNamespaceId() const { + return blink::WebString::FromASCII(namespace_id_); +} + bool WebStorageNamespaceImpl::IsSameNamespace( const WebStorageNamespace& other) const { - const WebStorageNamespaceImpl* other_impl = - static_cast<const WebStorageNamespaceImpl*>(&other); - return namespace_id_ == other_impl->namespace_id_; + return GetNamespaceId() == other.GetNamespaceId(); } } // namespace content diff --git a/chromium/content/renderer/dom_storage/webstoragenamespace_impl.h b/chromium/content/renderer/dom_storage/webstoragenamespace_impl.h index b4b522b798c..15008e3bae2 100644 --- a/chromium/content/renderer/dom_storage/webstoragenamespace_impl.h +++ b/chromium/content/renderer/dom_storage/webstoragenamespace_impl.h @@ -21,6 +21,7 @@ class WebStorageNamespaceImpl : public blink::WebStorageNamespace { blink::WebStorageArea* CreateStorageArea( const blink::WebSecurityOrigin& origin) override; virtual blink::WebStorageNamespace* copy(); + blink::WebString GetNamespaceId() const override; bool IsSameNamespace(const WebStorageNamespace&) const override; private: diff --git a/chromium/content/renderer/fetchers/resource_fetcher_impl.cc b/chromium/content/renderer/fetchers/resource_fetcher_impl.cc index 56aca6e806d..98c8c10ed36 100644 --- a/chromium/content/renderer/fetchers/resource_fetcher_impl.cc +++ b/chromium/content/renderer/fetchers/resource_fetcher_impl.cc @@ -175,8 +175,7 @@ class ResourceFetcherImpl::ClientImpl : public network::mojom::URLLoaderClient { // network::mojom::URLLoaderClient overrides: void OnReceiveResponse( - const network::ResourceResponseHead& response_head, - network::mojom::DownloadedTempFilePtr downloaded_file) override { + const network::ResourceResponseHead& response_head) override { DCHECK_EQ(Status::kStarted, status_); // Existing callers need URL and HTTP status code. URL is already set in // Start(). @@ -187,10 +186,9 @@ class ResourceFetcherImpl::ClientImpl : public network::mojom::URLLoaderClient { const net::RedirectInfo& redirect_info, const network::ResourceResponseHead& response_head) override { DCHECK_EQ(Status::kStarted, status_); - loader_->FollowRedirect(base::nullopt); + loader_->FollowRedirect(base::nullopt, base::nullopt); response_.SetURL(redirect_info.new_url); } - void OnDataDownloaded(int64_t data_len, int64_t encoded_data_len) override {} void OnUploadProgress(int64_t current_position, int64_t total_size, OnUploadProgressCallback ack_callback) override {} diff --git a/chromium/content/renderer/gamepad_shared_memory_reader.cc b/chromium/content/renderer/gamepad_shared_memory_reader.cc deleted file mode 100644 index fe68df67ae3..00000000000 --- a/chromium/content/renderer/gamepad_shared_memory_reader.cc +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/gamepad_shared_memory_reader.h" - -#include "base/metrics/histogram_macros.h" -#include "base/trace_event/trace_event.h" -#include "content/public/common/service_names.mojom.h" -#include "content/public/renderer/render_thread.h" -#include "content/renderer/renderer_blink_platform_impl.h" -#include "ipc/ipc_sync_message_filter.h" -#include "services/service_manager/public/cpp/connector.h" -#include "third_party/blink/public/platform/web_gamepad_listener.h" -#include "third_party/blink/public/platform/web_platform_event_listener.h" - -namespace content { - -GamepadSharedMemoryReader::GamepadSharedMemoryReader(RenderThread* thread) - : RendererGamepadProvider(thread), - gamepad_hardware_buffer_(nullptr), - ever_interacted_with_(false), - binding_(this) { - if (thread) { - thread->GetConnector()->BindInterface(mojom::kBrowserServiceName, - mojo::MakeRequest(&gamepad_monitor_)); - device::mojom::GamepadObserverPtr observer; - binding_.Bind(mojo::MakeRequest(&observer)); - gamepad_monitor_->SetObserver(std::move(observer)); - } -} - -void GamepadSharedMemoryReader::SendStartMessage() { - if (gamepad_monitor_) { - gamepad_monitor_->GamepadStartPolling(&renderer_shared_buffer_handle_); - } -} - -void GamepadSharedMemoryReader::SendStopMessage() { - if (gamepad_monitor_) { - gamepad_monitor_->GamepadStopPolling(); - } -} - -void GamepadSharedMemoryReader::Start( - blink::WebPlatformEventListener* listener) { - PlatformEventObserver::Start(listener); - - // If we don't get a valid handle from the browser, don't try to Map (we're - // probably out of memory or file handles). - bool valid_handle = renderer_shared_buffer_handle_.is_valid(); - UMA_HISTOGRAM_BOOLEAN("Gamepad.ValidSharedMemoryHandle", valid_handle); - if (!valid_handle) - return; - - renderer_shared_buffer_mapping_ = - renderer_shared_buffer_handle_->Map(sizeof(GamepadHardwareBuffer)); - CHECK(renderer_shared_buffer_mapping_); - void* memory = renderer_shared_buffer_mapping_.get(); - CHECK(memory); - gamepad_hardware_buffer_ = - static_cast<GamepadHardwareBuffer*>(memory); -} - -void GamepadSharedMemoryReader::SampleGamepads(device::Gamepads& gamepads) { - // Blink should have started observing at that point. - CHECK(is_observing()); - - // ========== - // DANGER - // ========== - // - // This logic is duplicated in Pepper as well. If you change it, that also - // needs to be in sync. See ppapi/proxy/gamepad_resource.cc. - device::Gamepads read_into; - TRACE_EVENT0("GAMEPAD", "SampleGamepads"); - - if (!renderer_shared_buffer_handle_.is_valid()) - return; - - // Only try to read this many times before failing to avoid waiting here - // very long in case of contention with the writer. TODO(scottmg) Tune this - // number (as low as 1?) if histogram shows distribution as mostly - // 0-and-maximum. - const int kMaximumContentionCount = 10; - int contention_count = -1; - base::subtle::Atomic32 version; - do { - version = gamepad_hardware_buffer_->seqlock.ReadBegin(); - memcpy(&read_into, &gamepad_hardware_buffer_->data, sizeof(read_into)); - ++contention_count; - if (contention_count == kMaximumContentionCount) - break; - } while (gamepad_hardware_buffer_->seqlock.ReadRetry(version)); - UMA_HISTOGRAM_COUNTS("Gamepad.ReadContentionCount", contention_count); - - if (contention_count >= kMaximumContentionCount) { - // We failed to successfully read, presumably because the hardware - // thread was taking unusually long. Don't copy the data to the output - // buffer, and simply leave what was there before. - return; - } - - // New data was read successfully, copy it into the output buffer. - memcpy(&gamepads, &read_into, sizeof(gamepads)); - - if (!ever_interacted_with_) { - // Clear the connected flag if the user hasn't interacted with any of the - // gamepads to prevent fingerprinting. The actual data is not cleared. - // WebKit will only copy out data into the JS buffers for connected - // gamepads so this is sufficient. - for (unsigned i = 0; i < device::Gamepads::kItemsLengthCap; i++) - gamepads.items[i].connected = false; - } -} - -GamepadSharedMemoryReader::~GamepadSharedMemoryReader() { - StopIfObserving(); -} - -void GamepadSharedMemoryReader::GamepadConnected( - int index, - const device::Gamepad& gamepad) { - // The browser already checks if the user actually interacted with a device. - ever_interacted_with_ = true; - - if (listener()) - listener()->DidConnectGamepad(index, gamepad); -} - -void GamepadSharedMemoryReader::GamepadDisconnected( - int index, - const device::Gamepad& gamepad) { - if (listener()) - listener()->DidDisconnectGamepad(index, gamepad); -} - -} // namespace content diff --git a/chromium/content/renderer/gamepad_shared_memory_reader.h b/chromium/content/renderer/gamepad_shared_memory_reader.h deleted file mode 100644 index 384c38d878f..00000000000 --- a/chromium/content/renderer/gamepad_shared_memory_reader.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_GAMEPAD_SHARED_MEMORY_READER_H_ -#define CONTENT_RENDERER_GAMEPAD_SHARED_MEMORY_READER_H_ - -#include <memory> - -#include "base/macros.h" -#include "content/public/renderer/renderer_gamepad_provider.h" -#include "device/base/synchronization/shared_memory_seqlock_buffer.h" -#include "device/gamepad/public/cpp/gamepads.h" -#include "device/gamepad/public/mojom/gamepad.mojom.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/system/buffer.h" - -namespace content { - -typedef device::SharedMemorySeqLockBuffer<device::Gamepads> - GamepadHardwareBuffer; - -class GamepadSharedMemoryReader : public RendererGamepadProvider, - public device::mojom::GamepadObserver { - public: - explicit GamepadSharedMemoryReader(RenderThread* thread); - ~GamepadSharedMemoryReader() override; - - // RendererGamepadProvider implementation. - void SampleGamepads(device::Gamepads& gamepads) override; - void Start(blink::WebPlatformEventListener* listener) override; - - protected: - // PlatformEventObserver protected methods. - void SendStartMessage() override; - void SendStopMessage() override; - - private: - // device::mojom::GamepadObserver methods. - void GamepadConnected(int index, const device::Gamepad& gamepad) override; - void GamepadDisconnected(int index, const device::Gamepad& gamepad) override; - - mojo::ScopedSharedBufferHandle renderer_shared_buffer_handle_; - mojo::ScopedSharedBufferMapping renderer_shared_buffer_mapping_; - GamepadHardwareBuffer* gamepad_hardware_buffer_; - - bool ever_interacted_with_; - - mojo::Binding<device::mojom::GamepadObserver> binding_; - device::mojom::GamepadMonitorPtr gamepad_monitor_; - - DISALLOW_COPY_AND_ASSIGN(GamepadSharedMemoryReader); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_GAMEPAD_SHARED_MEMORY_READER_H_ diff --git a/chromium/content/renderer/gpu/compositor_dependencies.h b/chromium/content/renderer/gpu/compositor_dependencies.h index 4fc1825ead3..74da8435707 100644 --- a/chromium/content/renderer/gpu/compositor_dependencies.h +++ b/chromium/content/renderer/gpu/compositor_dependencies.h @@ -22,7 +22,7 @@ class UkmRecorderFactory; namespace blink { namespace scheduler { -class WebMainThreadScheduler; +class WebThreadScheduler; } } @@ -37,20 +37,23 @@ class CompositorDependencies { virtual bool IsPartialRasterEnabled() = 0; virtual bool IsGpuMemoryBufferCompositorResourcesEnabled() = 0; virtual bool IsElasticOverscrollEnabled() = 0; + virtual bool IsUseZoomForDSFEnabled() = 0; virtual scoped_refptr<base::SingleThreadTaskRunner> GetCompositorMainThreadTaskRunner() = 0; // Returns null if the compositor is in single-threaded mode (ie. there is no // compositor thread). virtual scoped_refptr<base::SingleThreadTaskRunner> GetCompositorImplThreadTaskRunner() = 0; - virtual blink::scheduler::WebMainThreadScheduler* - GetWebMainThreadScheduler() = 0; + virtual blink::scheduler::WebThreadScheduler* GetWebMainThreadScheduler() = 0; virtual cc::TaskGraphRunner* GetTaskGraphRunner() = 0; - virtual bool IsThreadedAnimationEnabled() = 0; virtual bool IsScrollAnimatorEnabled() = 0; virtual std::unique_ptr<cc::UkmRecorderFactory> CreateUkmRecorderFactory() = 0; +#ifdef OS_ANDROID + virtual bool UsingSynchronousCompositing() = 0; +#endif + virtual ~CompositorDependencies() {} }; diff --git a/chromium/content/renderer/gpu/gpu_benchmarking_extension.cc b/chromium/content/renderer/gpu/gpu_benchmarking_extension.cc index cedd8d4ca36..0b2b903d230 100644 --- a/chromium/content/renderer/gpu/gpu_benchmarking_extension.cc +++ b/chromium/content/renderer/gpu/gpu_benchmarking_extension.cc @@ -33,7 +33,7 @@ #include "content/public/renderer/render_thread.h" #include "content/public/renderer/v8_value_converter.h" #include "content/renderer/gpu/actions_parser.h" -#include "content/renderer/gpu/render_widget_compositor.h" +#include "content/renderer/gpu/layer_tree_view.h" #include "content/renderer/render_thread_impl.h" #include "content/renderer/render_view_impl.h" #include "content/renderer/skia_benchmarking_extension.h" @@ -61,12 +61,16 @@ #include "v8/include/v8.h" #if defined(OS_WIN) && !defined(NDEBUG) +// XpsObjectModel.h indirectly includes <wincrypt.h> which is +// incompatible with Chromium's OpenSSL. By including wincrypt_shim.h +// first, problems are avoided. +#include "crypto/wincrypt_shim.h" + #include <XpsObjectModel.h> #include <objbase.h> #include <wrl/client.h> #endif -using blink::WebCanvas; using blink::WebLocalFrame; using blink::WebImageCache; using blink::WebPrivatePtr; @@ -183,11 +187,7 @@ class CallbackAndContext : public base::RefCounted<CallbackAndContext> { class GpuBenchmarkingContext { public: - GpuBenchmarkingContext() - : web_frame_(nullptr), - web_view_(nullptr), - render_view_impl_(nullptr), - compositor_(nullptr) {} + GpuBenchmarkingContext() = default; bool Init(bool init_compositor) { web_frame_ = WebLocalFrame::FrameForCurrentContext(); @@ -210,8 +210,8 @@ class GpuBenchmarkingContext { if (!init_compositor) return true; - compositor_ = render_view_impl_->GetWidget()->compositor(); - if (!compositor_) { + layer_tree_view_ = render_view_impl_->GetWidget()->layer_tree_view(); + if (!layer_tree_view_) { web_frame_ = nullptr; web_view_ = nullptr; render_view_impl_ = nullptr; @@ -233,16 +233,16 @@ class GpuBenchmarkingContext { DCHECK(render_view_impl_ != nullptr); return render_view_impl_; } - RenderWidgetCompositor* compositor() const { - DCHECK(compositor_ != nullptr); - return compositor_; + LayerTreeView* layer_tree_view() const { + DCHECK(layer_tree_view_ != nullptr); + return layer_tree_view_; } private: - WebLocalFrame* web_frame_; - WebView* web_view_; - RenderViewImpl* render_view_impl_; - RenderWidgetCompositor* compositor_; + WebLocalFrame* web_frame_ = nullptr; + WebView* web_view_ = nullptr; + RenderViewImpl* render_view_impl_ = nullptr; + LayerTreeView* layer_tree_view_ = nullptr; DISALLOW_COPY_AND_ASSIGN(GpuBenchmarkingContext); }; @@ -550,7 +550,8 @@ gin::ObjectTemplateBuilder GpuBenchmarking::GetObjectTemplateBuilder( .SetMethod("getGpuDriverBugWorkarounds", &GpuBenchmarking::GetGpuDriverBugWorkarounds) .SetMethod("startProfiling", &GpuBenchmarking::StartProfiling) - .SetMethod("stopProfiling", &GpuBenchmarking::StopProfiling); + .SetMethod("stopProfiling", &GpuBenchmarking::StopProfiling) + .SetMethod("freeze", &GpuBenchmarking::Freeze); } void GpuBenchmarking::SetNeedsDisplayOnAllLayers() { @@ -558,7 +559,7 @@ void GpuBenchmarking::SetNeedsDisplayOnAllLayers() { if (!context.Init(true)) return; - context.compositor()->SetNeedsDisplayOnAllLayers(); + context.layer_tree_view()->SetNeedsDisplayOnAllLayers(); } void GpuBenchmarking::SetRasterizeOnlyVisibleContent() { @@ -566,7 +567,7 @@ void GpuBenchmarking::SetRasterizeOnlyVisibleContent() { if (!context.Init(true)) return; - context.compositor()->SetRasterizeOnlyVisibleContent(); + context.layer_tree_view()->SetRasterizeOnlyVisibleContent(); } namespace { @@ -596,7 +597,7 @@ void GpuBenchmarking::PrintToSkPicture(v8::Isolate* isolate, if (!context.Init(true)) return; - const cc::Layer* root_layer = context.compositor()->GetRootLayer(); + const cc::Layer* root_layer = context.layer_tree_view()->GetRootLayer(); if (!root_layer) return; @@ -874,8 +875,9 @@ void GpuBenchmarking::SetBrowserControlsShown(bool show) { if (!context.Init(false)) return; context.web_view()->UpdateBrowserControlsState( - blink::kWebBrowserControlsBoth, - show ? blink::kWebBrowserControlsShown : blink::kWebBrowserControlsHidden, + cc::BrowserControlsState::kBoth, + show ? cc::BrowserControlsState::kShown + : cc::BrowserControlsState::kHidden, false); } @@ -885,7 +887,7 @@ float GpuBenchmarking::VisualViewportY() { return 0.0; float y = context.web_view()->VisualViewportOffset().y; blink::WebRect rect(0, y, 0, 0); - context.render_view_impl()->ConvertViewportToWindow(&rect); + context.render_view_impl()->WidgetClient()->ConvertViewportToWindow(&rect); return rect.y; } @@ -895,7 +897,7 @@ float GpuBenchmarking::VisualViewportX() { return 0.0; float x = context.web_view()->VisualViewportOffset().x; blink::WebRect rect(x, 0, 0, 0); - context.render_view_impl()->ConvertViewportToWindow(&rect); + context.render_view_impl()->WidgetClient()->ConvertViewportToWindow(&rect); return rect.x; } @@ -905,7 +907,7 @@ float GpuBenchmarking::VisualViewportHeight() { return 0.0; float height = context.web_view()->VisualViewportSize().height; blink::WebRect rect(0, 0, 0, height); - context.render_view_impl()->ConvertViewportToWindow(&rect); + context.render_view_impl()->WidgetClient()->ConvertViewportToWindow(&rect); return rect.height; } @@ -915,7 +917,7 @@ float GpuBenchmarking::VisualViewportWidth() { return 0.0; float width = context.web_view()->VisualViewportSize().width; blink::WebRect rect(0, 0, width, 0); - context.render_view_impl()->ConvertViewportToWindow(&rect); + context.render_view_impl()->WidgetClient()->ConvertViewportToWindow(&rect); return rect.width; } @@ -1040,10 +1042,10 @@ int GpuBenchmarking::RunMicroBenchmark(gin::Arguments* args) { std::unique_ptr<base::Value> value = V8ValueConverter::Create()->FromV8Value(arguments, v8_context); - return context.compositor()->ScheduleMicroBenchmark( + return context.layer_tree_view()->ScheduleMicroBenchmark( name, std::move(value), - base::Bind(&OnMicroBenchmarkCompleted, - base::RetainedRef(callback_and_context))); + base::BindOnce(&OnMicroBenchmarkCompleted, + base::RetainedRef(callback_and_context))); } bool GpuBenchmarking::SendMessageToMicroBenchmark( @@ -1058,8 +1060,8 @@ bool GpuBenchmarking::SendMessageToMicroBenchmark( std::unique_ptr<base::Value> value = V8ValueConverter::Create()->FromV8Value(message, v8_context); - return context.compositor()->SendMessageToMicroBenchmark(id, - std::move(value)); + return context.layer_tree_view()->SendMessageToMicroBenchmark( + id, std::move(value)); } bool GpuBenchmarking::HasGpuChannel() { @@ -1113,4 +1115,15 @@ void GpuBenchmarking::StopProfiling() { base::debug::StopProfiling(); } +void GpuBenchmarking::Freeze() { + GpuBenchmarkingContext context; + if (!context.Init(true)) + return; + // TODO(fmeawad): Instead of forcing a visibility change, only allow + // freezing a page if it was already hidden. + context.web_view()->SetVisibilityState( + blink::mojom::PageVisibilityState::kHidden, false); + context.web_view()->SetPageFrozen(true); +} + } // namespace content diff --git a/chromium/content/renderer/gpu/gpu_benchmarking_extension.h b/chromium/content/renderer/gpu/gpu_benchmarking_extension.h index 15b285cf7de..f423142cda6 100644 --- a/chromium/content/renderer/gpu/gpu_benchmarking_extension.h +++ b/chromium/content/renderer/gpu/gpu_benchmarking_extension.h @@ -91,6 +91,9 @@ class GpuBenchmarking : public gin::Wrappable<GpuBenchmarking> { void StartProfiling(gin::Arguments* args); void StopProfiling(); + // Freezes a page, used to transition the page to the FROZEN lifecycle state. + void Freeze(); + RenderFrameImpl* render_frame_; mojom::InputInjectorPtr input_injector_; DISALLOW_COPY_AND_ASSIGN(GpuBenchmarking); diff --git a/chromium/content/renderer/gpu/layer_tree_view.cc b/chromium/content/renderer/gpu/layer_tree_view.cc new file mode 100644 index 00000000000..511f04a5cac --- /dev/null +++ b/chromium/content/renderer/gpu/layer_tree_view.cc @@ -0,0 +1,742 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/renderer/gpu/layer_tree_view.h" + +#include <stddef.h> +#include <string> +#include <utility> + +#include "base/auto_reset.h" +#include "base/callback.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/time/time.h" +#include "base/values.h" +#include "cc/animation/animation_host.h" +#include "cc/animation/animation_timeline.h" +#include "cc/base/region.h" +#include "cc/benchmarks/micro_benchmark.h" +#include "cc/debug/layer_tree_debug_state.h" +#include "cc/input/layer_selection_bound.h" +#include "cc/layers/layer.h" +#include "cc/trees/latency_info_swap_promise.h" +#include "cc/trees/latency_info_swap_promise_monitor.h" +#include "cc/trees/layer_tree_host.h" +#include "cc/trees/layer_tree_mutator.h" +#include "cc/trees/render_frame_metadata_observer.h" +#include "cc/trees/swap_promise.h" +#include "cc/trees/ukm_manager.h" +#include "components/viz/common/frame_sinks/begin_frame_args.h" +#include "components/viz/common/frame_sinks/begin_frame_source.h" +#include "components/viz/common/frame_sinks/copy_output_request.h" +#include "components/viz/common/frame_sinks/copy_output_result.h" +#include "components/viz/common/quads/compositor_frame_metadata.h" +#include "components/viz/common/resources/single_release_callback.h" +#include "content/renderer/gpu/layer_tree_view_delegate.h" +#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h" +#include "third_party/blink/public/platform/web_runtime_features.h" +#include "third_party/blink/public/platform/web_size.h" +#include "third_party/blink/public/web/blink.h" +#include "ui/gfx/presentation_feedback.h" + +namespace base { +class Value; +} + +namespace cc { +class Layer; +} + +namespace content { +namespace { + +using ReportTimeCallback = blink::WebLayerTreeView::ReportTimeCallback; + +class ReportTimeSwapPromise : public cc::SwapPromise { + public: + ReportTimeSwapPromise(ReportTimeCallback callback, + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + base::WeakPtr<LayerTreeView> layer_tree_view); + ~ReportTimeSwapPromise() override; + + void DidActivate() override {} + void WillSwap(viz::CompositorFrameMetadata* metadata) override; + void DidSwap() override; + void DidNotSwap(DidNotSwapReason reason) override; + int64_t TraceId() const override; + + private: + ReportTimeCallback callback_; + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + base::WeakPtr<LayerTreeView> layer_tree_view_; + + DISALLOW_COPY_AND_ASSIGN(ReportTimeSwapPromise); +}; + +ReportTimeSwapPromise::ReportTimeSwapPromise( + ReportTimeCallback callback, + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + base::WeakPtr<LayerTreeView> layer_tree_view) + : callback_(std::move(callback)), + task_runner_(std::move(task_runner)), + layer_tree_view_(std::move(layer_tree_view)) {} + +ReportTimeSwapPromise::~ReportTimeSwapPromise() {} + +void ReportTimeSwapPromise::WillSwap(viz::CompositorFrameMetadata* metadata) { + DCHECK_GT(metadata->frame_token, 0u); + metadata->request_presentation_feedback = true; + auto* task_runner = task_runner_.get(); + task_runner->PostTask( + FROM_HERE, + base::BindOnce( + &LayerTreeView::AddPresentationCallback, layer_tree_view_, + metadata->frame_token, + base::BindOnce(std::move(callback_), + blink::WebLayerTreeView::SwapResult::kDidSwap))); +} + +void ReportTimeSwapPromise::DidSwap() { + // If swap did happen, then the paint-time will be reported when the + // presentation feedback is received. +} + +void ReportTimeSwapPromise::DidNotSwap( + cc::SwapPromise::DidNotSwapReason reason) { + blink::WebLayerTreeView::SwapResult result; + switch (reason) { + case cc::SwapPromise::DidNotSwapReason::SWAP_FAILS: + result = blink::WebLayerTreeView::SwapResult::kDidNotSwapSwapFails; + break; + case cc::SwapPromise::DidNotSwapReason::COMMIT_FAILS: + result = blink::WebLayerTreeView::SwapResult::kDidNotSwapCommitFails; + break; + case cc::SwapPromise::DidNotSwapReason::COMMIT_NO_UPDATE: + result = blink::WebLayerTreeView::SwapResult::kDidNotSwapCommitNoUpdate; + break; + case cc::SwapPromise::DidNotSwapReason::ACTIVATION_FAILS: + result = blink::WebLayerTreeView::SwapResult::kDidNotSwapActivationFails; + break; + } + task_runner_->PostTask(FROM_HERE, base::BindOnce(std::move(callback_), result, + base::TimeTicks::Now())); +} + +int64_t ReportTimeSwapPromise::TraceId() const { + return 0; +} + +} // namespace + +LayerTreeView::LayerTreeView( + LayerTreeViewDelegate* delegate, + scoped_refptr<base::SingleThreadTaskRunner> main_thread, + scoped_refptr<base::SingleThreadTaskRunner> compositor_thread, + cc::TaskGraphRunner* task_graph_runner, + blink::scheduler::WebThreadScheduler* scheduler) + : delegate_(delegate), + main_thread_(std::move(main_thread)), + compositor_thread_(std::move(compositor_thread)), + task_graph_runner_(task_graph_runner), + web_main_thread_scheduler_(scheduler), + animation_host_(cc::AnimationHost::CreateMainInstance()), + weak_factory_(this) {} + +LayerTreeView::~LayerTreeView() = default; + +void LayerTreeView::Initialize( + const cc::LayerTreeSettings& settings, + std::unique_ptr<cc::UkmRecorderFactory> ukm_recorder_factory) { + const bool is_threaded = !!compositor_thread_; + + cc::LayerTreeHost::InitParams params; + params.client = this; + params.settings = &settings; + params.task_graph_runner = task_graph_runner_; + params.main_task_runner = main_thread_; + params.mutator_host = animation_host_.get(); + params.ukm_recorder_factory = std::move(ukm_recorder_factory); + if (base::TaskScheduler::GetInstance()) { + // The image worker thread needs to allow waiting since it makes discardable + // shared memory allocations which need to make synchronous calls to the + // IO thread. + params.image_worker_task_runner = base::CreateSequencedTaskRunnerWithTraits( + {base::WithBaseSyncPrimitives(), base::TaskPriority::USER_VISIBLE, + base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}); + } + if (!is_threaded) { + // Single-threaded layout tests, and unit tests. + layer_tree_host_ = cc::LayerTreeHost::CreateSingleThreaded(this, ¶ms); + } else { + layer_tree_host_ = + cc::LayerTreeHost::CreateThreaded(compositor_thread_, ¶ms); + } +} + +void LayerTreeView::SetNeverVisible() { + DCHECK(!layer_tree_host_->IsVisible()); + never_visible_ = true; +} + +const base::WeakPtr<cc::InputHandler>& LayerTreeView::GetInputHandler() { + return layer_tree_host_->GetInputHandler(); +} + +void LayerTreeView::SetNeedsDisplayOnAllLayers() { + layer_tree_host_->SetNeedsDisplayOnAllLayers(); +} + +void LayerTreeView::SetRasterizeOnlyVisibleContent() { + cc::LayerTreeDebugState current = layer_tree_host_->GetDebugState(); + current.rasterize_only_visible_content = true; + layer_tree_host_->SetDebugState(current); +} + +void LayerTreeView::SetNeedsRedrawRect(gfx::Rect damage_rect) { + layer_tree_host_->SetNeedsRedrawRect(damage_rect); +} + +bool LayerTreeView::IsSurfaceSynchronizationEnabled() const { + return layer_tree_host_->GetSettings().enable_surface_synchronization; +} + +void LayerTreeView::SetNeedsForcedRedraw() { + layer_tree_host_->SetNeedsCommitWithForcedRedraw(); +} + +std::unique_ptr<cc::SwapPromiseMonitor> +LayerTreeView::CreateLatencyInfoSwapPromiseMonitor(ui::LatencyInfo* latency) { + return std::make_unique<cc::LatencyInfoSwapPromiseMonitor>( + latency, layer_tree_host_->GetSwapPromiseManager(), nullptr); +} + +void LayerTreeView::QueueSwapPromise( + std::unique_ptr<cc::SwapPromise> swap_promise) { + layer_tree_host_->QueueSwapPromise(std::move(swap_promise)); +} + +int LayerTreeView::GetSourceFrameNumber() const { + return layer_tree_host_->SourceFrameNumber(); +} + +void LayerTreeView::NotifyInputThrottledUntilCommit() { + layer_tree_host_->NotifyInputThrottledUntilCommit(); +} + +const cc::Layer* LayerTreeView::GetRootLayer() const { + return layer_tree_host_->root_layer(); +} + +int LayerTreeView::ScheduleMicroBenchmark( + const std::string& name, + std::unique_ptr<base::Value> value, + base::OnceCallback<void(std::unique_ptr<base::Value>)> callback) { + return layer_tree_host_->ScheduleMicroBenchmark(name, std::move(value), + std::move(callback)); +} + +bool LayerTreeView::SendMessageToMicroBenchmark( + int id, + std::unique_ptr<base::Value> value) { + return layer_tree_host_->SendMessageToMicroBenchmark(id, std::move(value)); +} + +void LayerTreeView::SetViewportSizeAndScale( + const gfx::Size& device_viewport_size, + float device_scale_factor, + const viz::LocalSurfaceId& local_surface_id) { + layer_tree_host_->SetViewportSizeAndScale( + device_viewport_size, device_scale_factor, local_surface_id); +} + +void LayerTreeView::RequestNewLocalSurfaceId() { + layer_tree_host_->RequestNewLocalSurfaceId(); +} + +void LayerTreeView::SetViewportVisibleRect(const gfx::Rect& visible_rect) { + layer_tree_host_->SetViewportVisibleRect(visible_rect); +} + +viz::FrameSinkId LayerTreeView::GetFrameSinkId() { + return frame_sink_id_; +} + +void LayerTreeView::SetRootLayer(scoped_refptr<cc::Layer> layer) { + layer_tree_host_->SetRootLayer(std::move(layer)); +} + +void LayerTreeView::ClearRootLayer() { + layer_tree_host_->SetRootLayer(nullptr); +} + +cc::AnimationHost* LayerTreeView::CompositorAnimationHost() { + return animation_host_.get(); +} + +gfx::Size LayerTreeView::GetViewportSize() const { + return layer_tree_host_->device_viewport_size(); +} + +void LayerTreeView::SetBackgroundColor(SkColor color) { + layer_tree_host_->set_background_color(color); +} + +void LayerTreeView::SetVisible(bool visible) { + if (never_visible_) + return; + + layer_tree_host_->SetVisible(visible); + + if (visible && layer_tree_frame_sink_request_failed_while_invisible_) + DidFailToInitializeLayerTreeFrameSink(); +} + +void LayerTreeView::SetPageScaleFactorAndLimits(float page_scale_factor, + float minimum, + float maximum) { + layer_tree_host_->SetPageScaleFactorAndLimits(page_scale_factor, minimum, + maximum); +} + +void LayerTreeView::StartPageScaleAnimation(const gfx::Vector2d& target_offset, + bool use_anchor, + float new_page_scale, + double duration_sec) { + base::TimeDelta duration = base::TimeDelta::FromMicroseconds( + duration_sec * base::Time::kMicrosecondsPerSecond); + layer_tree_host_->StartPageScaleAnimation(target_offset, use_anchor, + new_page_scale, duration); +} + +bool LayerTreeView::HasPendingPageScaleAnimation() const { + return layer_tree_host_->HasPendingPageScaleAnimation(); +} + +void LayerTreeView::HeuristicsForGpuRasterizationUpdated( + bool matches_heuristics) { + layer_tree_host_->SetHasGpuRasterizationTrigger(matches_heuristics); +} + +void LayerTreeView::SetNeedsBeginFrame() { + layer_tree_host_->SetNeedsAnimate(); +} + +void LayerTreeView::RegisterViewportLayers(const ViewportLayers& layers) { + cc::LayerTreeHost::ViewportLayers viewport_layers; + viewport_layers.overscroll_elasticity = layers.overscroll_elasticity; + 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; + viewport_layers.inner_viewport_scroll = layers.inner_viewport_scroll; + viewport_layers.outer_viewport_scroll = layers.outer_viewport_scroll; + layer_tree_host_->RegisterViewportLayers(viewport_layers); +} + +void LayerTreeView::ClearViewportLayers() { + layer_tree_host_->RegisterViewportLayers(cc::LayerTreeHost::ViewportLayers()); +} + +void LayerTreeView::RegisterSelection(const cc::LayerSelection& selection) { + layer_tree_host_->RegisterSelection(selection); +} + +void LayerTreeView::ClearSelection() { + layer_tree_host_->RegisterSelection(cc::LayerSelection()); +} + +void LayerTreeView::SetMutatorClient( + std::unique_ptr<cc::LayerTreeMutator> client) { + TRACE_EVENT0("cc", "LayerTreeView::setMutatorClient"); + layer_tree_host_->SetLayerTreeMutator(std::move(client)); +} + +void LayerTreeView::ForceRecalculateRasterScales() { + layer_tree_host_->SetNeedsRecalculateRasterScales(); +} + +void LayerTreeView::SetEventListenerProperties( + cc::EventListenerClass event_class, + cc::EventListenerProperties properties) { + layer_tree_host_->SetEventListenerProperties(event_class, properties); +} + +cc::EventListenerProperties LayerTreeView::EventListenerProperties( + cc::EventListenerClass event_class) const { + return layer_tree_host_->event_listener_properties(event_class); +} + +void LayerTreeView::SetHaveScrollEventHandlers(bool has_handlers) { + layer_tree_host_->SetHaveScrollEventHandlers(has_handlers); +} + +bool LayerTreeView::HaveScrollEventHandlers() const { + return layer_tree_host_->have_scroll_event_handlers(); +} + +bool LayerTreeView::CompositeIsSynchronous() const { + if (!compositor_thread_) { + DCHECK(!layer_tree_host_->GetSettings().single_thread_proxy_scheduler); + return true; + } + return false; +} + +void LayerTreeView::LayoutAndPaintAsync(base::OnceClosure callback) { + DCHECK(layout_and_paint_async_callback_.is_null()); + layout_and_paint_async_callback_ = std::move(callback); + + if (CompositeIsSynchronous()) { + // The LayoutAndPaintAsyncCallback is invoked in WillCommit, which is + // dispatched after layout and paint for all compositing modes. + const bool raster = false; + layer_tree_host_->GetTaskRunnerProvider()->MainThreadTaskRunner()->PostTask( + FROM_HERE, base::BindOnce(&LayerTreeView::SynchronouslyComposite, + weak_factory_.GetWeakPtr(), raster, nullptr)); + } else { + layer_tree_host_->SetNeedsCommit(); + } +} + +void LayerTreeView::SetLayerTreeFrameSink( + std::unique_ptr<cc::LayerTreeFrameSink> layer_tree_frame_sink) { + if (!layer_tree_frame_sink) { + DidFailToInitializeLayerTreeFrameSink(); + return; + } + layer_tree_host_->SetLayerTreeFrameSink(std::move(layer_tree_frame_sink)); +} + +void LayerTreeView::InvokeLayoutAndPaintCallback() { + if (!layout_and_paint_async_callback_.is_null()) + std::move(layout_and_paint_async_callback_).Run(); +} + +void LayerTreeView::CompositeAndReadbackAsync( + base::OnceCallback<void(const SkBitmap&)> callback) { + DCHECK(layout_and_paint_async_callback_.is_null()); + scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner = + layer_tree_host_->GetTaskRunnerProvider()->MainThreadTaskRunner(); + std::unique_ptr<viz::CopyOutputRequest> request = + std::make_unique<viz::CopyOutputRequest>( + viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP, + base::BindOnce( + [](base::OnceCallback<void(const SkBitmap&)> callback, + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + std::unique_ptr<viz::CopyOutputResult> result) { + task_runner->PostTask( + FROM_HERE, + base::BindOnce(std::move(callback), result->AsSkBitmap())); + }, + std::move(callback), std::move(main_thread_task_runner))); + auto swap_promise = + delegate_->RequestCopyOfOutputForLayoutTest(std::move(request)); + + // Force a commit to happen. The temporary copy output request will + // be installed after layout which will happen as a part of the commit, for + // widgets that delay the creation of their output surface. + if (CompositeIsSynchronous()) { + // Since the composite is required for a pixel dump, we need to raster. + // Note that we defer queuing the SwapPromise until the requested Composite + // with rasterization is done. + const bool raster = true; + layer_tree_host_->GetTaskRunnerProvider()->MainThreadTaskRunner()->PostTask( + FROM_HERE, base::BindOnce(&LayerTreeView::SynchronouslyComposite, + weak_factory_.GetWeakPtr(), raster, + std::move(swap_promise))); + } else { + // Force a redraw to ensure that the copy swap promise isn't cancelled due + // to no damage. + SetNeedsForcedRedraw(); + layer_tree_host_->QueueSwapPromise(std::move(swap_promise)); + layer_tree_host_->SetNeedsCommit(); + } +} + +void LayerTreeView::SynchronouslyCompositeNoRasterForTesting() { + SynchronouslyComposite(false /* raster */, nullptr /* swap_promise */); +} + +void LayerTreeView::CompositeWithRasterForTesting() { + SynchronouslyComposite(true /* raster */, nullptr /* swap_promise */); +} + +void LayerTreeView::SynchronouslyComposite( + bool raster, + std::unique_ptr<cc::SwapPromise> swap_promise) { + DCHECK(CompositeIsSynchronous()); + if (!layer_tree_host_->IsVisible()) + return; + + if (in_synchronous_compositor_update_) { + // LayoutTests can use a nested message loop to pump frames while inside a + // frame, but the compositor does not support this. In this case, we only + // run blink's lifecycle updates. + delegate_->BeginMainFrame(base::TimeTicks::Now()); + delegate_->UpdateVisualState( + cc::LayerTreeHostClient::VisualStateUpdate::kAll); + return; + } + + if (swap_promise) { + // Force a redraw to ensure that the copy swap promise isn't cancelled due + // to no damage. + SetNeedsForcedRedraw(); + layer_tree_host_->QueueSwapPromise(std::move(swap_promise)); + } + + DCHECK(!in_synchronous_compositor_update_); + base::AutoReset<bool> inside_composite(&in_synchronous_compositor_update_, + true); + layer_tree_host_->Composite(base::TimeTicks::Now(), raster); +} + +void LayerTreeView::SetDeferCommits(bool defer_commits) { + layer_tree_host_->SetDeferCommits(defer_commits); +} + +int LayerTreeView::LayerTreeId() const { + return layer_tree_host_->GetId(); +} + +void LayerTreeView::SetShowFPSCounter(bool show) { + cc::LayerTreeDebugState debug_state = layer_tree_host_->GetDebugState(); + debug_state.show_fps_counter = show; + layer_tree_host_->SetDebugState(debug_state); +} + +void LayerTreeView::SetShowPaintRects(bool show) { + cc::LayerTreeDebugState debug_state = layer_tree_host_->GetDebugState(); + debug_state.show_paint_rects = show; + layer_tree_host_->SetDebugState(debug_state); +} + +void LayerTreeView::SetShowDebugBorders(bool show) { + cc::LayerTreeDebugState debug_state = layer_tree_host_->GetDebugState(); + if (show) + debug_state.show_debug_borders.set(); + else + debug_state.show_debug_borders.reset(); + layer_tree_host_->SetDebugState(debug_state); +} + +void LayerTreeView::SetShowScrollBottleneckRects(bool show) { + cc::LayerTreeDebugState debug_state = layer_tree_host_->GetDebugState(); + debug_state.show_touch_event_handler_rects = show; + debug_state.show_wheel_event_handler_rects = show; + debug_state.show_non_fast_scrollable_rects = show; + layer_tree_host_->SetDebugState(debug_state); +} + +void LayerTreeView::UpdateBrowserControlsState( + cc::BrowserControlsState constraints, + cc::BrowserControlsState current, + bool animate) { + layer_tree_host_->UpdateBrowserControlsState(constraints, current, animate); +} + +void LayerTreeView::SetBrowserControlsHeight(float top_height, + float bottom_height, + bool shrink) { + layer_tree_host_->SetBrowserControlsHeight(top_height, bottom_height, shrink); +} + +void LayerTreeView::SetBrowserControlsShownRatio(float ratio) { + layer_tree_host_->SetBrowserControlsShownRatio(ratio); +} + +void LayerTreeView::RequestDecode(const cc::PaintImage& image, + base::OnceCallback<void(bool)> callback) { + layer_tree_host_->QueueImageDecode(image, std::move(callback)); + + // If we're compositing synchronously, the SetNeedsCommit call which will be + // issued by |layer_tree_host_| is not going to cause a commit, due to the + // fact that this would make layout tests slow and cause flakiness. However, + // in this case we actually need a commit to transfer the decode requests to + // the impl side. So, force a commit to happen. + if (CompositeIsSynchronous()) { + const bool raster = true; + layer_tree_host_->GetTaskRunnerProvider()->MainThreadTaskRunner()->PostTask( + FROM_HERE, base::BindOnce(&LayerTreeView::SynchronouslyComposite, + weak_factory_.GetWeakPtr(), raster, nullptr)); + } +} + +void LayerTreeView::SetOverscrollBehavior( + const cc::OverscrollBehavior& behavior) { + layer_tree_host_->SetOverscrollBehavior(behavior); +} + +void LayerTreeView::WillBeginMainFrame() { + delegate_->WillBeginCompositorFrame(); +} + +void LayerTreeView::DidBeginMainFrame() {} + +void LayerTreeView::BeginMainFrame(const viz::BeginFrameArgs& args) { + web_main_thread_scheduler_->WillBeginFrame(args); + delegate_->BeginMainFrame(args.frame_time); +} + +void LayerTreeView::BeginMainFrameNotExpectedSoon() { + web_main_thread_scheduler_->BeginFrameNotExpectedSoon(); +} + +void LayerTreeView::BeginMainFrameNotExpectedUntil(base::TimeTicks time) { + web_main_thread_scheduler_->BeginMainFrameNotExpectedUntil(time); +} + +void LayerTreeView::UpdateLayerTreeHost(VisualStateUpdate requested_update) { + delegate_->UpdateVisualState(requested_update); +} + +void LayerTreeView::ApplyViewportDeltas( + const gfx::Vector2dF& inner_delta, + const gfx::Vector2dF& outer_delta, + const gfx::Vector2dF& elastic_overscroll_delta, + float page_scale, + float top_controls_delta) { + delegate_->ApplyViewportDeltas(inner_delta, outer_delta, + elastic_overscroll_delta, page_scale, + top_controls_delta); +} + +void LayerTreeView::RecordWheelAndTouchScrollingCount( + bool has_scrolled_by_wheel, + bool has_scrolled_by_touch) { + delegate_->RecordWheelAndTouchScrollingCount(has_scrolled_by_wheel, + has_scrolled_by_touch); +} + +void LayerTreeView::RequestNewLayerTreeFrameSink() { + // If the host is closing, then no more compositing is possible. This + // prevents shutdown races between handling the close message and + // the CreateLayerTreeFrameSink task. + if (delegate_->IsClosing()) + return; + delegate_->RequestNewLayerTreeFrameSink(base::BindOnce( + &LayerTreeView::SetLayerTreeFrameSink, weak_factory_.GetWeakPtr())); +} + +void LayerTreeView::DidInitializeLayerTreeFrameSink() {} + +void LayerTreeView::DidFailToInitializeLayerTreeFrameSink() { + if (!layer_tree_host_->IsVisible()) { + layer_tree_frame_sink_request_failed_while_invisible_ = true; + return; + } + layer_tree_frame_sink_request_failed_while_invisible_ = false; + layer_tree_host_->GetTaskRunnerProvider()->MainThreadTaskRunner()->PostTask( + FROM_HERE, base::BindOnce(&LayerTreeView::RequestNewLayerTreeFrameSink, + weak_factory_.GetWeakPtr())); +} + +void LayerTreeView::WillCommit() { + InvokeLayoutAndPaintCallback(); +} + +void LayerTreeView::DidCommit() { + delegate_->DidCommitCompositorFrame(); + web_main_thread_scheduler_->DidCommitFrameToCompositor(); +} + +void LayerTreeView::DidCommitAndDrawFrame() { + delegate_->DidCommitAndDrawCompositorFrame(); +} + +void LayerTreeView::DidReceiveCompositorFrameAck() { + delegate_->DidReceiveCompositorFrameAck(); +} + +void LayerTreeView::DidCompletePageScaleAnimation() { + delegate_->DidCompletePageScaleAnimation(); +} + +void LayerTreeView::DidPresentCompositorFrame( + uint32_t frame_token, + const gfx::PresentationFeedback& feedback) { + DCHECK(layer_tree_host_->GetTaskRunnerProvider() + ->MainThreadTaskRunner() + ->RunsTasksInCurrentSequence()); + while (!presentation_callbacks_.empty()) { + const auto& front = presentation_callbacks_.begin(); + if (viz::FrameTokenGT(front->first, frame_token)) + break; + for (auto& callback : front->second) + std::move(callback).Run(feedback.timestamp); + presentation_callbacks_.erase(front); + } +} + +void LayerTreeView::RequestScheduleAnimation() { + delegate_->RequestScheduleAnimation(); +} + +void LayerTreeView::DidSubmitCompositorFrame() {} + +void LayerTreeView::DidLoseLayerTreeFrameSink() {} + +void LayerTreeView::SetFrameSinkId(const viz::FrameSinkId& frame_sink_id) { + frame_sink_id_ = frame_sink_id; +} + +void LayerTreeView::SetRasterColorSpace(const gfx::ColorSpace& color_space) { + layer_tree_host_->SetRasterColorSpace(color_space); +} + +void LayerTreeView::ClearCachesOnNextCommit() { + layer_tree_host_->ClearCachesOnNextCommit(); +} + +void LayerTreeView::SetContentSourceId(uint32_t id) { + layer_tree_host_->SetContentSourceId(id); +} + +void LayerTreeView::NotifySwapTime(ReportTimeCallback callback) { + QueueSwapPromise(std::make_unique<ReportTimeSwapPromise>( + std::move(callback), + layer_tree_host_->GetTaskRunnerProvider()->MainThreadTaskRunner(), + weak_factory_.GetWeakPtr())); +} + +void LayerTreeView::RequestBeginMainFrameNotExpected(bool new_state) { + layer_tree_host_->RequestBeginMainFrameNotExpected(new_state); +} + +const cc::LayerTreeSettings& LayerTreeView::GetLayerTreeSettings() const { + return layer_tree_host_->GetSettings(); +} + +void LayerTreeView::SetRenderFrameObserver( + std::unique_ptr<cc::RenderFrameMetadataObserver> observer) { + layer_tree_host_->SetRenderFrameObserver(std::move(observer)); +} + +void LayerTreeView::AddPresentationCallback( + uint32_t frame_token, + base::OnceCallback<void(base::TimeTicks)> callback) { + if (!presentation_callbacks_.empty()) { + auto& previous = presentation_callbacks_.back(); + uint32_t previous_frame_token = previous.first; + if (previous_frame_token == frame_token) { + previous.second.push_back(std::move(callback)); + DCHECK_LE(previous.second.size(), 250u); + return; + } + DCHECK(viz::FrameTokenGT(frame_token, previous_frame_token)); + } + std::vector<base::OnceCallback<void(base::TimeTicks)>> callbacks; + callbacks.push_back(std::move(callback)); + presentation_callbacks_.push_back({frame_token, std::move(callbacks)}); + DCHECK_LE(presentation_callbacks_.size(), 25u); +} + +void LayerTreeView::SetURLForUkm(const GURL& url) { + layer_tree_host_->SetURLForUkm(url); +} + +} // namespace content diff --git a/chromium/content/renderer/gpu/render_widget_compositor.h b/chromium/content/renderer/gpu/layer_tree_view.h index 933ed484cec..09dbf800511 100644 --- a/chromium/content/renderer/gpu/render_widget_compositor.h +++ b/chromium/content/renderer/gpu/layer_tree_view.h @@ -2,46 +2,49 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_RENDERER_GPU_RENDER_WIDGET_COMPOSITOR_H_ -#define CONTENT_RENDERER_GPU_RENDER_WIDGET_COMPOSITOR_H_ +#ifndef CONTENT_RENDERER_GPU_LAYER_TREE_VIEW_H_ +#define CONTENT_RENDERER_GPU_LAYER_TREE_VIEW_H_ #include <stdint.h> #include "base/callback.h" +#include "base/containers/circular_deque.h" #include "base/memory/weak_ptr.h" +#include "base/single_thread_task_runner.h" #include "base/time/time.h" #include "base/values.h" #include "cc/input/browser_controls_state.h" -#include "cc/trees/layer_tree_host.h" #include "cc/trees/layer_tree_host_client.h" #include "cc/trees/layer_tree_host_single_thread_client.h" -#include "cc/trees/layer_tree_settings.h" -#include "cc/trees/managed_memory_policy.h" #include "cc/trees/swap_promise.h" #include "cc/trees/swap_promise_monitor.h" #include "content/common/content_export.h" -#include "content/common/render_frame_metadata.mojom.h" -#include "content/renderer/gpu/compositor_dependencies.h" -#include "services/metrics/public/cpp/ukm_recorder.h" #include "third_party/blink/public/platform/web_layer_tree_view.h" #include "ui/gfx/geometry/rect.h" -namespace base { -class CommandLine; +class GURL; + +namespace blink { +namespace scheduler { +class WebThreadScheduler; } +} // namespace blink namespace cc { - class AnimationHost; class InputHandler; class Layer; class LayerTreeFrameSink; class LayerTreeHost; -class MutatorHost; -} +class LayerTreeSettings; +class RenderFrameMetadataObserver; +class TaskGraphRunner; +class UkmRecorderFactory; +} // namespace cc namespace gfx { class ColorSpace; +class Size; } namespace ui { @@ -49,41 +52,28 @@ class LatencyInfo; } namespace content { -class RenderWidgetCompositorDelegate; -struct ScreenInfo; +class LayerTreeViewDelegate; -class CONTENT_EXPORT RenderWidgetCompositor +class CONTENT_EXPORT LayerTreeView : public blink::WebLayerTreeView, public cc::LayerTreeHostClient, public cc::LayerTreeHostSingleThreadClient { public: - // Attempt to construct and initialize a compositor instance for the widget - // with the given settings. Returns NULL if initialization fails. - static std::unique_ptr<RenderWidgetCompositor> Create( - RenderWidgetCompositorDelegate* delegate, - CompositorDependencies* compositor_deps); - - ~RenderWidgetCompositor() override; - - static cc::LayerTreeSettings GenerateLayerTreeSettings( - const base::CommandLine& cmd, - CompositorDependencies* compositor_deps, - bool is_for_subframe, - const ScreenInfo& screen_info, - bool is_threaded); - static std::unique_ptr<cc::LayerTreeHost> CreateLayerTreeHost( - cc::LayerTreeHostClient* client, - cc::LayerTreeHostSingleThreadClient* single_thread_client, - cc::MutatorHost* mutator_host, - CompositorDependencies* deps, - const ScreenInfo& screen_info); - - void Initialize(std::unique_ptr<cc::LayerTreeHost> layer_tree_host, - std::unique_ptr<cc::AnimationHost> animation_host); - - static cc::ManagedMemoryPolicy GetGpuMemoryPolicy( - const cc::ManagedMemoryPolicy& policy, - const ScreenInfo& screen_info); + // The |main_thread| is the task runner that the compositor will use for the + // main thread (where it is constructed). The |compositor_thread| is the task + // runner for the compositor thread, but is null if the compositor will run in + // single-threaded mode (in tests only). + LayerTreeView(LayerTreeViewDelegate* delegate, + scoped_refptr<base::SingleThreadTaskRunner> main_thread, + scoped_refptr<base::SingleThreadTaskRunner> compositor_thread, + cc::TaskGraphRunner* task_graph_runner, + blink::scheduler::WebThreadScheduler* scheduler); + ~LayerTreeView() override; + + // The |ukm_recorder_factory| may be null to disable recording (in tests + // only). + void Initialize(const cc::LayerTreeSettings& settings, + std::unique_ptr<cc::UkmRecorderFactory> ukm_recorder_factory); void SetNeverVisible(); const base::WeakPtr<cc::InputHandler>& GetInputHandler(); @@ -112,59 +102,54 @@ class CONTENT_EXPORT RenderWidgetCompositor int ScheduleMicroBenchmark( const std::string& name, std::unique_ptr<base::Value> value, - const base::Callback<void(std::unique_ptr<base::Value>)>& callback); + base::OnceCallback<void(std::unique_ptr<base::Value>)> callback); bool SendMessageToMicroBenchmark(int id, std::unique_ptr<base::Value> value); void SetFrameSinkId(const viz::FrameSinkId& frame_sink_id); void SetRasterColorSpace(const gfx::ColorSpace& color_space); - void SetIsForOopif(bool is_for_oopif); + void ClearCachesOnNextCommit(); void SetContentSourceId(uint32_t source_id); void SetViewportSizeAndScale(const gfx::Size& device_viewport_size, float device_scale_factor, const viz::LocalSurfaceId& local_surface_id); void RequestNewLocalSurfaceId(); - bool HasNewLocalSurfaceIdRequest() const; void SetViewportVisibleRect(const gfx::Rect& visible_rect); void SetURLForUkm(const GURL& url); - // WebLayerTreeView implementation. + // blink::WebLayerTreeView implementation. viz::FrameSinkId GetFrameSinkId() override; void SetRootLayer(scoped_refptr<cc::Layer> layer) override; void ClearRootLayer() override; cc::AnimationHost* CompositorAnimationHost() override; - blink::WebSize GetViewportSize() const override; - virtual blink::WebFloatPoint adjustEventPointForPinchZoom( - const blink::WebFloatPoint& point) const; + gfx::Size GetViewportSize() const override; void SetBackgroundColor(SkColor color) override; void SetVisible(bool visible) override; void SetPageScaleFactorAndLimits(float page_scale_factor, float minimum, float maximum) override; - void StartPageScaleAnimation(const blink::WebPoint& destination, + void StartPageScaleAnimation(const gfx::Vector2d& target_offset, bool use_anchor, float new_page_scale, double duration_sec) override; bool HasPendingPageScaleAnimation() const override; void HeuristicsForGpuRasterizationUpdated(bool matches_heuristics) override; void SetNeedsBeginFrame() override; - void DidStopFlinging() override; void LayoutAndPaintAsync(base::OnceClosure callback) override; void CompositeAndReadbackAsync( base::OnceCallback<void(const SkBitmap&)> callback) override; void SynchronouslyCompositeNoRasterForTesting() override; void CompositeWithRasterForTesting() override; void SetDeferCommits(bool defer_commits) override; - void RegisterViewportLayers( - const blink::WebLayerTreeView::ViewportLayers& viewport_layers) override; + void RegisterViewportLayers(const ViewportLayers& viewport_layers) override; void ClearViewportLayers() override; - void RegisterSelection(const blink::WebSelection& selection) override; + void RegisterSelection(const cc::LayerSelection& selection) override; void ClearSelection() override; void SetMutatorClient(std::unique_ptr<cc::LayerTreeMutator>) override; void ForceRecalculateRasterScales() override; void SetEventListenerProperties( - blink::WebEventListenerClass eventClass, - blink::WebEventListenerProperties properties) override; - blink::WebEventListenerProperties EventListenerProperties( - blink::WebEventListenerClass eventClass) const override; + cc::EventListenerClass eventClass, + cc::EventListenerProperties properties) override; + cc::EventListenerProperties EventListenerProperties( + cc::EventListenerClass eventClass) const override; void SetHaveScrollEventHandlers(bool) override; bool HaveScrollEventHandlers() const override; int LayerTreeId() const override; @@ -174,8 +159,8 @@ class CONTENT_EXPORT RenderWidgetCompositor void SetShowScrollBottleneckRects(bool show) override; void NotifySwapTime(ReportTimeCallback callback) override; - void UpdateBrowserControlsState(blink::WebBrowserControlsState constraints, - blink::WebBrowserControlsState current, + void UpdateBrowserControlsState(cc::BrowserControlsState constraints, + cc::BrowserControlsState current, bool animate) override; void SetBrowserControlsHeight(float top_height, float bottom_height, @@ -208,7 +193,9 @@ class CONTENT_EXPORT RenderWidgetCompositor void DidCommitAndDrawFrame() override; void DidReceiveCompositorFrameAck() override; void DidCompletePageScaleAnimation() override; - bool IsForSubframe() override; + void DidPresentCompositorFrame( + uint32_t frame_token, + const gfx::PresentationFeedback& feedback) override; // cc::LayerTreeHostSingleThreadClient implementation. void RequestScheduleAnimation() override; @@ -216,24 +203,22 @@ class CONTENT_EXPORT RenderWidgetCompositor void DidLoseLayerTreeFrameSink() override; void RequestBeginMainFrameNotExpected(bool new_state) override; - const cc::LayerTreeSettings& GetLayerTreeSettings() const { - return layer_tree_host_->GetSettings(); - } + const cc::LayerTreeSettings& GetLayerTreeSettings() const; - // Creates a cc::RenderFrameMetadataObserver, which is sent to the compositor + // Sets the RenderFrameMetadataObserver, which is sent to the compositor // thread for binding. - void CreateRenderFrameObserver( - mojom::RenderFrameMetadataObserverRequest request, - mojom::RenderFrameMetadataObserverClientPtrInfo client_info); + void SetRenderFrameObserver( + std::unique_ptr<cc::RenderFrameMetadataObserver> observer); - protected: - friend class RenderViewImplScaleFactorTest; - - RenderWidgetCompositor(RenderWidgetCompositorDelegate* delegate, - CompositorDependencies* compositor_deps); + void AddPresentationCallback( + uint32_t frame_token, + base::OnceCallback<void(base::TimeTicks)> callback); cc::LayerTreeHost* layer_tree_host() { return layer_tree_host_.get(); } + protected: + friend class RenderViewImplScaleFactorTest; + private: void SetLayerTreeFrameSink( std::unique_ptr<cc::LayerTreeFrameSink> layer_tree_frame_sink); @@ -242,13 +227,14 @@ class CONTENT_EXPORT RenderWidgetCompositor void SynchronouslyComposite(bool raster, std::unique_ptr<cc::SwapPromise> swap_promise); - RenderWidgetCompositorDelegate* const delegate_; - CompositorDependencies* const compositor_deps_; - const bool threaded_; - std::unique_ptr<cc::AnimationHost> animation_host_; + LayerTreeViewDelegate* const delegate_; + const scoped_refptr<base::SingleThreadTaskRunner> main_thread_; + const scoped_refptr<base::SingleThreadTaskRunner> compositor_thread_; + cc::TaskGraphRunner* const task_graph_runner_; + blink::scheduler::WebThreadScheduler* const web_main_thread_scheduler_; + const std::unique_ptr<cc::AnimationHost> animation_host_; std::unique_ptr<cc::LayerTreeHost> layer_tree_host_; - bool never_visible_; - bool is_for_oopif_; + bool never_visible_ = false; bool layer_tree_frame_sink_request_failed_while_invisible_ = false; @@ -256,12 +242,16 @@ class CONTENT_EXPORT RenderWidgetCompositor base::OnceClosure layout_and_paint_async_callback_; viz::FrameSinkId frame_sink_id_; + base::circular_deque< + std::pair<uint32_t, + std::vector<base::OnceCallback<void(base::TimeTicks)>>>> + presentation_callbacks_; - base::WeakPtrFactory<RenderWidgetCompositor> weak_factory_; + base::WeakPtrFactory<LayerTreeView> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(RenderWidgetCompositor); + DISALLOW_COPY_AND_ASSIGN(LayerTreeView); }; } // namespace content -#endif // CONTENT_RENDERER_GPU_RENDER_WIDGET_COMPOSITOR_H_ +#endif // CONTENT_RENDERER_GPU_LAYER_TREE_VIEW_H_ diff --git a/chromium/content/renderer/gpu/render_widget_compositor_delegate.h b/chromium/content/renderer/gpu/layer_tree_view_delegate.h index 24e9453d6dc..51ab69aed61 100644 --- a/chromium/content/renderer/gpu/render_widget_compositor_delegate.h +++ b/chromium/content/renderer/gpu/layer_tree_view_delegate.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_RENDERER_GPU_RENDER_WIDGET_COMPOSITOR_DELEGATE_H_ -#define CONTENT_RENDERER_GPU_RENDER_WIDGET_COMPOSITOR_DELEGATE_H_ +#ifndef CONTENT_RENDERER_GPU_LAYER_TREE_VIEW_DELEGATE_H_ +#define CONTENT_RENDERER_GPU_LAYER_TREE_VIEW_DELEGATE_H_ #include <memory> #include <vector> @@ -11,12 +11,11 @@ #include "base/callback.h" #include "base/time/time.h" #include "cc/trees/layer_tree_host_client.h" -#include "content/common/content_export.h" namespace cc { class LayerTreeFrameSink; class SwapPromise; -} +} // namespace cc namespace gfx { class Vector2dF; @@ -28,13 +27,13 @@ class CopyOutputRequest; namespace content { -using LayerTreeFrameSinkCallback = - base::Callback<void(std::unique_ptr<cc::LayerTreeFrameSink>)>; - -// Consumers of RenderWidgetCompositor implement this delegate in order to +// Consumers of LayerTreeView implement this delegate in order to // transport compositing information across processes. -class CONTENT_EXPORT RenderWidgetCompositorDelegate { +class LayerTreeViewDelegate { public: + using LayerTreeFrameSinkCallback = + base::OnceCallback<void(std::unique_ptr<cc::LayerTreeFrameSink>)>; + // Report viewport related properties during a commit from the compositor // thread. virtual void ApplyViewportDeltas( @@ -55,7 +54,7 @@ class CONTENT_EXPORT RenderWidgetCompositorDelegate { // Requests a LayerTreeFrameSink to submit CompositorFrames to. virtual void RequestNewLayerTreeFrameSink( - const LayerTreeFrameSinkCallback& callback) = 0; + LayerTreeFrameSinkCallback callback) = 0; // Notifies that the draw commands for a committed frame have been issued. virtual void DidCommitAndDrawCompositorFrame() = 0; @@ -70,7 +69,7 @@ class CONTENT_EXPORT RenderWidgetCompositorDelegate { // will be displayed. virtual void DidReceiveCompositorFrameAck() = 0; - // Indicates whether the RenderWidgetCompositor is about to close. + // Indicates whether the LayerTreeView is about to close. virtual bool IsClosing() const = 0; // Requests that the client schedule a composite now, and calculate @@ -93,9 +92,9 @@ class CONTENT_EXPORT RenderWidgetCompositorDelegate { std::unique_ptr<viz::CopyOutputRequest> request) = 0; protected: - virtual ~RenderWidgetCompositorDelegate() {} + virtual ~LayerTreeViewDelegate() {} }; } // namespace content -#endif // CONTENT_RENDERER_GPU_RENDER_WIDGET_COMPOSITOR_DELEGATE_H_ +#endif // CONTENT_RENDERER_GPU_LAYER_TREE_VIEW_DELEGATE_H_ diff --git a/chromium/content/renderer/gpu/layer_tree_view_unittest.cc b/chromium/content/renderer/gpu/layer_tree_view_unittest.cc new file mode 100644 index 00000000000..abc55297718 --- /dev/null +++ b/chromium/content/renderer/gpu/layer_tree_view_unittest.cc @@ -0,0 +1,376 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/renderer/gpu/layer_tree_view.h" + +#include <utility> + +#include "base/location.h" +#include "base/macros.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "base/single_thread_task_runner.h" +#include "base/threading/thread_task_runner_handle.h" +#include "build/build_config.h" +#include "cc/test/fake_layer_tree_frame_sink.h" +#include "cc/test/test_task_graph_runner.h" +#include "cc/test/test_ukm_recorder_factory.h" +#include "cc/trees/layer_tree_host.h" +#include "components/viz/common/frame_sinks/copy_output_request.h" +#include "components/viz/test/test_context_provider.h" +#include "content/test/stub_layer_tree_view_delegate.h" +#include "gpu/GLES2/gl2extchromium.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/platform/scheduler/test/fake_renderer_scheduler.h" +#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" + +using testing::AllOf; +using testing::Field; + +namespace content { +namespace { + +enum FailureMode { + NO_FAILURE, + BIND_CONTEXT_FAILURE, + GPU_CHANNEL_FAILURE, +}; + +class FakeLayerTreeViewDelegate : public StubLayerTreeViewDelegate { + public: + FakeLayerTreeViewDelegate() = default; + + void RequestNewLayerTreeFrameSink( + LayerTreeFrameSinkCallback callback) override { + // Subtract one cuz the current request has already been counted but should + // not be included for this. + if (num_requests_since_last_success_ - 1 < num_requests_before_success_) { + std::move(callback).Run(nullptr); + return; + } + + auto context_provider = viz::TestContextProvider::Create(); + if (num_failures_since_last_success_ < num_failures_before_success_) { + context_provider->UnboundTestContextGL()->LoseContextCHROMIUM( + GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB); + } + std::move(callback).Run( + cc::FakeLayerTreeFrameSink::Create3d(std::move(context_provider))); + } + + void Reset() { + num_requests_ = 0; + num_requests_before_success_ = 0; + num_requests_since_last_success_ = 0; + num_failures_ = 0; + num_failures_before_success_ = 0; + num_failures_since_last_success_ = 0; + num_successes_ = 0; + } + + void add_success() { + ++num_successes_; + num_requests_since_last_success_ = 0; + num_failures_since_last_success_ = 0; + } + int num_successes() const { return num_successes_; } + + void add_request() { + ++num_requests_since_last_success_; + ++num_requests_; + } + int num_requests() const { return num_requests_; } + + void add_failure() { + ++num_failures_since_last_success_; + ++num_failures_; + } + int num_failures() const { return num_failures_; } + + void set_num_requests_before_success(int n) { + num_requests_before_success_ = n; + } + void set_num_failures_before_success(int n) { + num_failures_before_success_ = n; + } + int num_failures_before_success() const { + return num_failures_before_success_; + } + + private: + int num_requests_ = 0; + int num_requests_before_success_ = 0; + int num_requests_since_last_success_ = 0; + int num_failures_ = 0; + int num_failures_before_success_ = 0; + int num_failures_since_last_success_ = 0; + int num_successes_ = 0; + + DISALLOW_COPY_AND_ASSIGN(FakeLayerTreeViewDelegate); +}; + +// Verify that failing to create an output surface will cause the compositor +// to attempt to repeatedly create another output surface. +// The use null output surface parameter allows testing whether failures +// from RenderWidget (couldn't create an output surface) vs failures from +// the compositor (couldn't bind the output surface) are handled identically. +class LayerTreeViewWithFrameSinkTracking : public LayerTreeView { + public: + LayerTreeViewWithFrameSinkTracking( + FakeLayerTreeViewDelegate* delegate, + scoped_refptr<base::SingleThreadTaskRunner> main_thread, + scoped_refptr<base::SingleThreadTaskRunner> compositor_thread, + cc::TaskGraphRunner* task_graph_runner, + blink::scheduler::WebThreadScheduler* scheduler) + : LayerTreeView(delegate, + std::move(main_thread), + std::move(compositor_thread), + task_graph_runner, + scheduler), + delegate_(delegate) {} + + // Force a new output surface to be created. + void SynchronousComposite() { + layer_tree_host()->SetVisible(false); + layer_tree_host()->ReleaseLayerTreeFrameSink(); + layer_tree_host()->SetVisible(true); + + base::TimeTicks some_time; + layer_tree_host()->Composite(some_time, true /* raster */); + } + + void RequestNewLayerTreeFrameSink() override { + delegate_->add_request(); + LayerTreeView::RequestNewLayerTreeFrameSink(); + } + + void DidInitializeLayerTreeFrameSink() override { + LayerTreeView::DidInitializeLayerTreeFrameSink(); + delegate_->add_success(); + if (delegate_->num_successes() == expected_successes_) { + EXPECT_EQ(delegate_->num_requests(), expected_requests_); + EndTest(); + } else { + // Post the synchronous composite task so that it is not called + // reentrantly as a part of RequestNewLayerTreeFrameSink. + blink::scheduler::GetSingleThreadTaskRunnerForTesting()->PostTask( + FROM_HERE, + base::BindOnce( + &LayerTreeViewWithFrameSinkTracking::SynchronousComposite, + base::Unretained(this))); + } + } + + void DidFailToInitializeLayerTreeFrameSink() override { + LayerTreeView::DidFailToInitializeLayerTreeFrameSink(); + delegate_->add_failure(); + if (delegate_->num_requests() == expected_requests_) { + EXPECT_EQ(delegate_->num_successes(), expected_successes_); + EndTest(); + return; + } + } + + void SetUp(int expected_successes, + int num_tries, + FailureMode failure_mode, + base::RunLoop* run_loop) { + run_loop_ = run_loop; + failure_mode_ = failure_mode; + expected_successes_ = expected_successes; + switch (failure_mode_) { + case NO_FAILURE: + expected_requests_ = expected_successes; + break; + case BIND_CONTEXT_FAILURE: + case GPU_CHANNEL_FAILURE: + expected_requests_ = num_tries * std::max(1, expected_successes); + break; + } + } + + void EndTest() { run_loop_->Quit(); } + + private: + FakeLayerTreeViewDelegate* delegate_; + base::RunLoop* run_loop_ = nullptr; + int expected_successes_ = 0; + int expected_requests_ = 0; + FailureMode failure_mode_ = NO_FAILURE; + + DISALLOW_COPY_AND_ASSIGN(LayerTreeViewWithFrameSinkTracking); +}; + +class LayerTreeViewWithFrameSinkTrackingTest : public testing::Test { + public: + LayerTreeViewWithFrameSinkTrackingTest() + : layer_tree_view_( + &layer_tree_view_delegate_, + blink::scheduler::GetSingleThreadTaskRunnerForTesting(), + /*compositor_thread=*/nullptr, + &test_task_graph_runner_, + &fake_renderer_scheduler_) { + cc::LayerTreeSettings settings; + settings.single_thread_proxy_scheduler = false; + layer_tree_view_.Initialize(settings, + std::make_unique<cc::TestUkmRecorderFactory>()); + } + + void RunTest(int expected_successes, FailureMode failure_mode) { + layer_tree_view_delegate_.Reset(); + // 6 is just an artibrary "large" number to show it keeps trying. + const int kTries = 6; + // If it should fail, then it will fail every attempt, otherwise it fails + // until the last attempt. + int tries_before_success = kTries - (expected_successes ? 1 : 0); + switch (failure_mode) { + case NO_FAILURE: + layer_tree_view_delegate_.set_num_failures_before_success(0); + layer_tree_view_delegate_.set_num_requests_before_success(0); + break; + case BIND_CONTEXT_FAILURE: + layer_tree_view_delegate_.set_num_failures_before_success( + tries_before_success); + layer_tree_view_delegate_.set_num_requests_before_success(0); + break; + case GPU_CHANNEL_FAILURE: + layer_tree_view_delegate_.set_num_failures_before_success(0); + layer_tree_view_delegate_.set_num_requests_before_success( + tries_before_success); + break; + } + base::RunLoop run_loop; + layer_tree_view_.SetUp(expected_successes, kTries, failure_mode, &run_loop); + layer_tree_view_.SetVisible(true); + blink::scheduler::GetSingleThreadTaskRunnerForTesting()->PostTask( + FROM_HERE, + base::BindOnce( + &LayerTreeViewWithFrameSinkTracking::SynchronousComposite, + base::Unretained(&layer_tree_view_))); + run_loop.Run(); + } + + protected: + base::MessageLoop ye_olde_message_loope_; + cc::TestTaskGraphRunner test_task_graph_runner_; + blink::scheduler::FakeRendererScheduler fake_renderer_scheduler_; + FakeLayerTreeViewDelegate layer_tree_view_delegate_; + LayerTreeViewWithFrameSinkTracking layer_tree_view_; + + private: + DISALLOW_COPY_AND_ASSIGN(LayerTreeViewWithFrameSinkTrackingTest); +}; + +TEST_F(LayerTreeViewWithFrameSinkTrackingTest, SucceedOnce) { + RunTest(1, NO_FAILURE); +} + +TEST_F(LayerTreeViewWithFrameSinkTrackingTest, SucceedOnce_AfterNullChannel) { + RunTest(1, GPU_CHANNEL_FAILURE); +} + +TEST_F(LayerTreeViewWithFrameSinkTrackingTest, SucceedOnce_AfterLostContext) { + RunTest(1, BIND_CONTEXT_FAILURE); +} + +TEST_F(LayerTreeViewWithFrameSinkTrackingTest, SucceedTwice) { + RunTest(2, NO_FAILURE); +} + +TEST_F(LayerTreeViewWithFrameSinkTrackingTest, SucceedTwice_AfterNullChannel) { + RunTest(2, GPU_CHANNEL_FAILURE); +} + +TEST_F(LayerTreeViewWithFrameSinkTrackingTest, SucceedTwice_AfterLostContext) { + RunTest(2, BIND_CONTEXT_FAILURE); +} + +TEST_F(LayerTreeViewWithFrameSinkTrackingTest, FailWithNullChannel) { + RunTest(0, GPU_CHANNEL_FAILURE); +} + +TEST_F(LayerTreeViewWithFrameSinkTrackingTest, FailWithLostContext) { + RunTest(0, BIND_CONTEXT_FAILURE); +} + +class VisibilityTestLayerTreeView : public LayerTreeView { + public: + VisibilityTestLayerTreeView( + StubLayerTreeViewDelegate* delegate, + scoped_refptr<base::SingleThreadTaskRunner> main_thread, + scoped_refptr<base::SingleThreadTaskRunner> compositor_thread, + cc::TaskGraphRunner* task_graph_runner, + blink::scheduler::WebThreadScheduler* scheduler) + : LayerTreeView(delegate, + std::move(main_thread), + std::move(compositor_thread), + task_graph_runner, + scheduler) {} + + void RequestNewLayerTreeFrameSink() override { + LayerTreeView::RequestNewLayerTreeFrameSink(); + num_requests_sent_++; + if (run_loop_) + run_loop_->Quit(); + } + + void set_run_loop(base::RunLoop* run_loop) { run_loop_ = run_loop; } + int num_requests_sent() { return num_requests_sent_; } + + private: + int num_requests_sent_ = 0; + base::RunLoop* run_loop_; +}; + +TEST(LayerTreeViewTest, VisibilityTest) { + // Test that LayerTreeView does not retry FrameSink request while + // invisible. + + base::MessageLoop message_loop; + + cc::TestTaskGraphRunner test_task_graph_runner; + blink::scheduler::FakeRendererScheduler fake_renderer_scheduler; + // Synchronously callback with null FrameSink. + StubLayerTreeViewDelegate layer_tree_view_delegate; + VisibilityTestLayerTreeView layer_tree_view( + &layer_tree_view_delegate, + blink::scheduler::GetSingleThreadTaskRunnerForTesting(), + /*compositor_thread=*/nullptr, &test_task_graph_runner, + &fake_renderer_scheduler); + + layer_tree_view.Initialize(cc::LayerTreeSettings(), + std::make_unique<cc::TestUkmRecorderFactory>()); + + { + // Make one request and stop immediately while invisible. + base::RunLoop run_loop; + layer_tree_view.set_run_loop(&run_loop); + layer_tree_view.SetVisible(false); + layer_tree_view.RequestNewLayerTreeFrameSink(); + run_loop.Run(); + layer_tree_view.set_run_loop(nullptr); + EXPECT_EQ(1, layer_tree_view.num_requests_sent()); + } + + { + // Make sure there are no more requests. + base::RunLoop run_loop; + run_loop.RunUntilIdle(); + EXPECT_EQ(1, layer_tree_view.num_requests_sent()); + } + + { + // Becoming visible retries request. + base::RunLoop run_loop; + layer_tree_view.set_run_loop(&run_loop); + layer_tree_view.SetVisible(true); + run_loop.Run(); + layer_tree_view.set_run_loop(nullptr); + EXPECT_EQ(2, layer_tree_view.num_requests_sent()); + } +} + +} // namespace +} // namespace content diff --git a/chromium/content/renderer/gpu/queue_message_swap_promise.cc b/chromium/content/renderer/gpu/queue_message_swap_promise.cc index 199ddfa4402..b9a07865124 100644 --- a/chromium/content/renderer/gpu/queue_message_swap_promise.cc +++ b/chromium/content/renderer/gpu/queue_message_swap_promise.cc @@ -7,7 +7,6 @@ #include <memory> #include "base/command_line.h" -#include "cc/trees/frame_token_allocator.h" #include "content/common/view_messages.h" #include "content/public/common/content_switches.h" #include "content/public/renderer/render_thread.h" @@ -47,9 +46,7 @@ void QueueMessageSwapPromise::DidActivate() { // The OutputSurface will take care of the Drain+Send. } -void QueueMessageSwapPromise::WillSwap( - viz::CompositorFrameMetadata* metadata, - cc::FrameTokenAllocator* frame_token_allocator) { +void QueueMessageSwapPromise::WillSwap(viz::CompositorFrameMetadata* metadata) { #if DCHECK_IS_ON() DCHECK(!completed_); #endif @@ -64,7 +61,7 @@ void QueueMessageSwapPromise::WillSwap( std::vector<IPC::Message> messages_to_send; FrameSwapMessageQueue::TransferMessages(&messages, &messages_to_send); if (!messages_to_send.empty()) { - metadata->frame_token = frame_token_allocator->GetOrAllocateFrameToken(); + metadata->send_frame_token_to_embedder = true; message_sender_->Send(new ViewHostMsg_FrameSwapMessages( message_queue_->routing_id(), metadata->frame_token, messages_to_send)); @@ -76,8 +73,7 @@ void QueueMessageSwapPromise::WillSwap( void QueueMessageSwapPromise::DidSwap() {} -cc::SwapPromise::DidNotSwapAction QueueMessageSwapPromise::DidNotSwap( - DidNotSwapReason reason) { +void QueueMessageSwapPromise::DidNotSwap(DidNotSwapReason reason) { #if DCHECK_IS_ON() DCHECK(!completed_); #endif @@ -89,7 +85,6 @@ cc::SwapPromise::DidNotSwapAction QueueMessageSwapPromise::DidNotSwap( message_sender_->Send(msg.release()); } PromiseCompleted(); - return DidNotSwapAction::BREAK_PROMISE; } void QueueMessageSwapPromise::PromiseCompleted() { diff --git a/chromium/content/renderer/gpu/queue_message_swap_promise.h b/chromium/content/renderer/gpu/queue_message_swap_promise.h index 392ac6da142..e56df3986fe 100644 --- a/chromium/content/renderer/gpu/queue_message_swap_promise.h +++ b/chromium/content/renderer/gpu/queue_message_swap_promise.h @@ -27,10 +27,9 @@ class QueueMessageSwapPromise : public cc::SwapPromise { ~QueueMessageSwapPromise() override; void DidActivate() override; - void WillSwap(viz::CompositorFrameMetadata* metadata, - cc::FrameTokenAllocator* frame_token_allocator) override; + void WillSwap(viz::CompositorFrameMetadata* metadata) override; void DidSwap() override; - DidNotSwapAction DidNotSwap(DidNotSwapReason reason) override; + void DidNotSwap(DidNotSwapReason reason) override; int64_t TraceId() const override; 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 828148017c4..098d92e1e00 100644 --- a/chromium/content/renderer/gpu/queue_message_swap_promise_unittest.cc +++ b/chromium/content/renderer/gpu/queue_message_swap_promise_unittest.cc @@ -12,11 +12,11 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/test/scoped_task_environment.h" -#include "cc/trees/frame_token_allocator.h" #include "cc/trees/swap_promise.h" +#include "content/common/render_frame_metadata.mojom.h" #include "content/common/view_messages.h" #include "content/renderer/gpu/frame_swap_message_queue.h" -#include "content/renderer/gpu/render_widget_compositor.h" +#include "content/renderer/gpu/layer_tree_view.h" #include "content/renderer/render_widget.h" #include "content/test/mock_render_process.h" #include "ipc/ipc_message.h" @@ -146,7 +146,7 @@ class QueueMessageSwapPromiseTest : public testing::Test { for (const auto& promise : promises_) { if (promise.get()) { promise->DidActivate(); - promise->WillSwap(&dummy_metadata_, &dummy_frame_token_allocator_); + promise->WillSwap(&dummy_metadata_); promise->DidSwap(); } } @@ -162,7 +162,6 @@ class QueueMessageSwapPromiseTest : public testing::Test { std::vector<IPC::Message> messages_; std::vector<std::unique_ptr<cc::SwapPromise>> promises_; viz::CompositorFrameMetadata dummy_metadata_; - cc::FrameTokenAllocator dummy_frame_token_allocator_; cc::RenderFrameMetadata dummy_render_frame_metadata_; private: @@ -180,7 +179,7 @@ TEST_F(QueueMessageSwapPromiseTest, NextSwapPolicySchedulesMessageForNextSwap) { ASSERT_TRUE(promises_[0].get()); promises_[0]->DidActivate(); - promises_[0]->WillSwap(&dummy_metadata_, &dummy_frame_token_allocator_); + promises_[0]->WillSwap(&dummy_metadata_); promises_[0]->DidSwap(); EXPECT_TRUE(DirectSendMessages().empty()); @@ -285,7 +284,7 @@ TEST_F(QueueMessageSwapPromiseTest, VisualStateSwapPromiseDidActivate) { QueueMessages(data, arraysize(data)); promises_[0]->DidActivate(); - promises_[0]->WillSwap(&dummy_metadata_, &dummy_frame_token_allocator_); + promises_[0]->WillSwap(&dummy_metadata_); promises_[0]->DidSwap(); ASSERT_FALSE(promises_[1].get()); std::vector<std::unique_ptr<IPC::Message>> messages; diff --git a/chromium/content/renderer/gpu/render_widget_compositor.cc b/chromium/content/renderer/gpu/render_widget_compositor.cc deleted file mode 100644 index e4faef4229e..00000000000 --- a/chromium/content/renderer/gpu/render_widget_compositor.cc +++ /dev/null @@ -1,1304 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/gpu/render_widget_compositor.h" - -#include <stddef.h> - -#include <cmath> -#include <limits> -#include <string> -#include <utility> - -#include "base/auto_reset.h" -#include "base/base_switches.h" -#include "base/callback.h" -#include "base/command_line.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/numerics/safe_conversions.h" -#include "base/single_thread_task_runner.h" -#include "base/strings/string_number_conversions.h" -#include "base/synchronization/lock.h" -#include "base/sys_info.h" -#include "base/task_scheduler/post_task.h" -#include "base/task_scheduler/task_scheduler.h" -#include "base/task_scheduler/task_traits.h" -#include "base/threading/thread_task_runner_handle.h" -#include "base/time/time.h" -#include "base/values.h" -#include "build/build_config.h" -#include "cc/animation/animation_host.h" -#include "cc/animation/animation_timeline.h" -#include "cc/base/region.h" -#include "cc/base/switches.h" -#include "cc/benchmarks/micro_benchmark.h" -#include "cc/debug/layer_tree_debug_state.h" -#include "cc/input/layer_selection_bound.h" -#include "cc/layers/layer.h" -#include "cc/trees/latency_info_swap_promise.h" -#include "cc/trees/latency_info_swap_promise_monitor.h" -#include "cc/trees/layer_tree_host.h" -#include "cc/trees/layer_tree_mutator.h" -#include "cc/trees/render_frame_metadata_observer.h" -#include "cc/trees/swap_promise.h" -#include "cc/trees/ukm_manager.h" -#include "components/viz/common/features.h" -#include "components/viz/common/frame_sinks/begin_frame_args.h" -#include "components/viz/common/frame_sinks/begin_frame_source.h" -#include "components/viz/common/frame_sinks/copy_output_request.h" -#include "components/viz/common/frame_sinks/copy_output_result.h" -#include "components/viz/common/resources/single_release_callback.h" -#include "components/viz/common/switches.h" -#include "content/common/content_switches_internal.h" -#include "content/common/layer_tree_settings_factory.h" -#include "content/common/render_frame_metadata.mojom.h" -#include "content/public/common/content_client.h" -#include "content/public/common/content_switches.h" -#include "content/public/common/screen_info.h" -#include "content/public/common/use_zoom_for_dsf_policy.h" -#include "content/public/renderer/content_renderer_client.h" -#include "content/renderer/gpu/render_widget_compositor_delegate.h" -#include "content/renderer/render_frame_metadata_observer_impl.h" -#include "gpu/command_buffer/client/gles2_interface.h" -#include "gpu/command_buffer/service/gpu_switches.h" -#include "media/base/media_switches.h" -#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h" -#include "third_party/blink/public/platform/scheduler/web_main_thread_scheduler.h" -#include "third_party/blink/public/platform/web_runtime_features.h" -#include "third_party/blink/public/platform/web_size.h" -#include "third_party/blink/public/web/blink.h" -#include "third_party/blink/public/web/web_selection.h" -#include "third_party/skia/include/core/SkImage.h" -#include "ui/base/ui_base_switches.h" -#include "ui/gfx/switches.h" -#include "ui/gl/gl_switches.h" -#include "ui/native_theme/native_theme_features.h" -#include "ui/native_theme/overlay_scrollbar_constants_aura.h" - -namespace base { -class Value; -} - -namespace cc { -class Layer; -} - -namespace content { -namespace { - -const base::Feature kUnpremultiplyAndDitherLowBitDepthTiles = { - "UnpremultiplyAndDitherLowBitDepthTiles", base::FEATURE_ENABLED_BY_DEFAULT}; - -using ReportTimeCallback = blink::WebLayerTreeView::ReportTimeCallback; - -class ReportTimeSwapPromise : public cc::SwapPromise { - public: - ReportTimeSwapPromise( - ReportTimeCallback callback, - scoped_refptr<base::SingleThreadTaskRunner> task_runner); - ~ReportTimeSwapPromise() override; - - void DidActivate() override {} - void WillSwap(viz::CompositorFrameMetadata* metadata, - cc::FrameTokenAllocator* frame_token_allocator) override {} - void DidSwap() override; - DidNotSwapAction DidNotSwap(DidNotSwapReason reason) override; - - int64_t TraceId() const override; - - private: - ReportTimeCallback callback_; - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - - DISALLOW_COPY_AND_ASSIGN(ReportTimeSwapPromise); -}; - -ReportTimeSwapPromise::ReportTimeSwapPromise( - ReportTimeCallback callback, - scoped_refptr<base::SingleThreadTaskRunner> task_runner) - : callback_(std::move(callback)), task_runner_(std::move(task_runner)) {} - -ReportTimeSwapPromise::~ReportTimeSwapPromise() {} - -void ReportTimeSwapPromise::DidSwap() { - task_runner_->PostTask( - FROM_HERE, base::BindOnce(std::move(callback_), - blink::WebLayerTreeView::SwapResult::kDidSwap, - base::TimeTicks::Now())); -} - -cc::SwapPromise::DidNotSwapAction ReportTimeSwapPromise::DidNotSwap( - cc::SwapPromise::DidNotSwapReason reason) { - blink::WebLayerTreeView::SwapResult result; - switch (reason) { - case cc::SwapPromise::DidNotSwapReason::SWAP_FAILS: - result = blink::WebLayerTreeView::SwapResult::kDidNotSwapSwapFails; - break; - case cc::SwapPromise::DidNotSwapReason::COMMIT_FAILS: - result = blink::WebLayerTreeView::SwapResult::kDidNotSwapCommitFails; - break; - case cc::SwapPromise::DidNotSwapReason::COMMIT_NO_UPDATE: - result = blink::WebLayerTreeView::SwapResult::kDidNotSwapCommitNoUpdate; - break; - case cc::SwapPromise::DidNotSwapReason::ACTIVATION_FAILS: - result = blink::WebLayerTreeView::SwapResult::kDidNotSwapActivationFails; - break; - } - task_runner_->PostTask(FROM_HERE, base::BindOnce(std::move(callback_), result, - base::TimeTicks::Now())); - return cc::SwapPromise::DidNotSwapAction::BREAK_PROMISE; -} - -int64_t ReportTimeSwapPromise::TraceId() const { - return 0; -} - -bool GetSwitchValueAsInt(const base::CommandLine& command_line, - const std::string& switch_string, - int min_value, - int max_value, - int* result) { - std::string string_value = command_line.GetSwitchValueASCII(switch_string); - int int_value; - if (base::StringToInt(string_value, &int_value) && int_value >= min_value && - int_value <= max_value) { - *result = int_value; - return true; - } else { - LOG(WARNING) << "Failed to parse switch " << switch_string << ": " - << string_value; - return false; - } -} - -gfx::SelectionBound::Type ConvertFromWebSelectionBoundType( - blink::WebSelectionBound::Type type) { - if (type == blink::WebSelectionBound::Type::kSelectionLeft) - return gfx::SelectionBound::Type::LEFT; - if (type == blink::WebSelectionBound::Type::kSelectionRight) - return gfx::SelectionBound::Type::RIGHT; - // if WebSelection is not a range (caret or none), - // The type of gfx::SelectionBound should be CENTER. - DCHECK_EQ(type, blink::WebSelectionBound::Type::kCaret); - return gfx::SelectionBound::Type::CENTER; -} - -cc::LayerSelectionBound ConvertFromWebSelectionBound( - const blink::WebSelectionBound& bound) { - cc::LayerSelectionBound cc_bound; - DCHECK(bound.layer_id); - - cc_bound.type = ConvertFromWebSelectionBoundType(bound.type); - cc_bound.layer_id = bound.layer_id; - cc_bound.edge_top = gfx::Point(bound.edge_top_in_layer); - cc_bound.edge_bottom = gfx::Point(bound.edge_bottom_in_layer); - cc_bound.hidden = bound.hidden; - return cc_bound; -} - -cc::LayerSelection ConvertFromWebSelection( - const blink::WebSelection& web_selection) { - if (web_selection.IsNone()) - return cc::LayerSelection(); - cc::LayerSelection cc_selection; - cc_selection.start = ConvertFromWebSelectionBound(web_selection.Start()); - cc_selection.end = ConvertFromWebSelectionBound(web_selection.end()); - return cc_selection; -} - -gfx::Size CalculateDefaultTileSize(const ScreenInfo& screen_info) { - int default_tile_size = 256; -#if defined(OS_ANDROID) - const gfx::Size screen_size = gfx::ScaleToFlooredSize( - screen_info.rect.size(), screen_info.device_scale_factor); - int display_width = screen_size.width(); - int display_height = screen_size.height(); - int numTiles = (display_width * display_height) / (256 * 256); - if (numTiles > 16) - default_tile_size = 384; - if (numTiles >= 40) - default_tile_size = 512; - - // Adjust for some resolutions that barely straddle an extra - // tile when in portrait mode. This helps worst case scroll/raster - // by not needing a full extra tile for each row. - constexpr int tolerance = 10; // To avoid rounding errors. - int portrait_width = std::min(display_width, display_height); - if (default_tile_size == 256 && std::abs(portrait_width - 768) < tolerance) - default_tile_size += 32; - if (default_tile_size == 384 && std::abs(portrait_width - 1200) < tolerance) - default_tile_size += 32; -#elif defined(OS_CHROMEOS) || defined(OS_MACOSX) - // Use 512 for high DPI (dsf=2.0f) devices. - if (screen_info.device_scale_factor >= 2.0f) - default_tile_size = 512; -#endif - - return gfx::Size(default_tile_size, default_tile_size); -} - -// Check cc::BrowserControlsState, and blink::WebBrowserControlsState -// are kept in sync. -static_assert(int(blink::kWebBrowserControlsBoth) == int(cc::BOTH), - "mismatching enums: BOTH"); -static_assert(int(blink::kWebBrowserControlsHidden) == int(cc::HIDDEN), - "mismatching enums: HIDDEN"); -static_assert(int(blink::kWebBrowserControlsShown) == int(cc::SHOWN), - "mismatching enums: SHOWN"); - -static cc::BrowserControlsState ConvertBrowserControlsState( - blink::WebBrowserControlsState state) { - return static_cast<cc::BrowserControlsState>(state); -} - -} // namespace - -// static -std::unique_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create( - RenderWidgetCompositorDelegate* delegate, - CompositorDependencies* compositor_deps) { - std::unique_ptr<RenderWidgetCompositor> compositor( - new RenderWidgetCompositor(delegate, compositor_deps)); - return compositor; -} - -RenderWidgetCompositor::RenderWidgetCompositor( - RenderWidgetCompositorDelegate* delegate, - CompositorDependencies* compositor_deps) - : delegate_(delegate), - compositor_deps_(compositor_deps), - threaded_(!!compositor_deps_->GetCompositorImplThreadTaskRunner()), - never_visible_(false), - is_for_oopif_(false), - weak_factory_(this) {} - -void RenderWidgetCompositor::Initialize( - std::unique_ptr<cc::LayerTreeHost> layer_tree_host, - std::unique_ptr<cc::AnimationHost> animation_host) { - DCHECK(layer_tree_host); - DCHECK(animation_host); - animation_host_ = std::move(animation_host); - layer_tree_host_ = std::move(layer_tree_host); -} - -RenderWidgetCompositor::~RenderWidgetCompositor() = default; - -// static -std::unique_ptr<cc::LayerTreeHost> RenderWidgetCompositor::CreateLayerTreeHost( - LayerTreeHostClient* client, - cc::LayerTreeHostSingleThreadClient* single_thread_client, - cc::MutatorHost* mutator_host, - CompositorDependencies* deps, - const ScreenInfo& screen_info) { - base::CommandLine* cmd = base::CommandLine::ForCurrentProcess(); - const bool is_threaded = !!deps->GetCompositorImplThreadTaskRunner(); - cc::LayerTreeSettings settings = GenerateLayerTreeSettings( - *cmd, deps, client->IsForSubframe(), screen_info, is_threaded); - - std::unique_ptr<cc::LayerTreeHost> layer_tree_host; - - cc::LayerTreeHost::InitParams params; - params.client = client; - params.settings = &settings; - params.task_graph_runner = deps->GetTaskGraphRunner(); - params.main_task_runner = deps->GetCompositorMainThreadTaskRunner(); - params.mutator_host = mutator_host; - params.ukm_recorder_factory = deps->CreateUkmRecorderFactory(); - if (base::TaskScheduler::GetInstance()) { - // The image worker thread needs to allow waiting since it makes discardable - // shared memory allocations which need to make synchronous calls to the - // IO thread. - params.image_worker_task_runner = base::CreateSequencedTaskRunnerWithTraits( - {base::WithBaseSyncPrimitives(), base::TaskPriority::USER_VISIBLE, - base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}); - } - if (!is_threaded) { - // Single-threaded layout tests. - layer_tree_host = - cc::LayerTreeHost::CreateSingleThreaded(single_thread_client, ¶ms); - } else { - layer_tree_host = cc::LayerTreeHost::CreateThreaded( - deps->GetCompositorImplThreadTaskRunner(), ¶ms); - } - - return layer_tree_host; -} - -// static -cc::LayerTreeSettings RenderWidgetCompositor::GenerateLayerTreeSettings( - const base::CommandLine& cmd, - CompositorDependencies* compositor_deps, - bool is_for_subframe, - const ScreenInfo& screen_info, - bool is_threaded) { - cc::LayerTreeSettings settings; - - settings.resource_settings.use_r16_texture = - base::FeatureList::IsEnabled(media::kUseR16Texture); - - settings.commit_to_active_tree = !is_threaded; - settings.is_layer_tree_for_subframe = is_for_subframe; - - // For web contents, layer transforms should scale up the contents of layers - // to keep content always crisp when possible. - settings.layer_transforms_should_scale_layer_contents = true; - - settings.main_frame_before_activation_enabled = - cmd.HasSwitch(cc::switches::kEnableMainFrameBeforeActivation); - - // Checkerimaging is not supported for synchronous single-threaded mode, which - // is what the renderer uses if its not threaded. - settings.enable_checker_imaging = - !cmd.HasSwitch(cc::switches::kDisableCheckerImaging) && is_threaded; - -#if defined(OS_ANDROID) - // We can use a more aggressive limit on Android since decodes tend to take - // longer on these devices. - settings.min_image_bytes_to_checker = 512 * 1024; // 512kB - - // Re-rasterization of checker-imaged content with software raster can be too - // costly on Android. - settings.only_checker_images_with_gpu_raster = true; -#endif - - // TODO(danakj): This should not be a setting O_O; it should change when the - // device scale factor on LayerTreeHost changes. - settings.default_tile_size = CalculateDefaultTileSize(screen_info); - if (cmd.HasSwitch(switches::kDefaultTileWidth)) { - int tile_width = 0; - GetSwitchValueAsInt(cmd, switches::kDefaultTileWidth, 1, - std::numeric_limits<int>::max(), &tile_width); - settings.default_tile_size.set_width(tile_width); - } - if (cmd.HasSwitch(switches::kDefaultTileHeight)) { - int tile_height = 0; - GetSwitchValueAsInt(cmd, switches::kDefaultTileHeight, 1, - std::numeric_limits<int>::max(), &tile_height); - settings.default_tile_size.set_height(tile_height); - } - - int max_untiled_layer_width = settings.max_untiled_layer_size.width(); - if (cmd.HasSwitch(switches::kMaxUntiledLayerWidth)) { - GetSwitchValueAsInt(cmd, switches::kMaxUntiledLayerWidth, 1, - std::numeric_limits<int>::max(), - &max_untiled_layer_width); - } - int max_untiled_layer_height = settings.max_untiled_layer_size.height(); - if (cmd.HasSwitch(switches::kMaxUntiledLayerHeight)) { - GetSwitchValueAsInt(cmd, switches::kMaxUntiledLayerHeight, 1, - std::numeric_limits<int>::max(), - &max_untiled_layer_height); - } - - settings.max_untiled_layer_size = - gfx::Size(max_untiled_layer_width, max_untiled_layer_height); - - settings.gpu_rasterization_msaa_sample_count = - compositor_deps->GetGpuRasterizationMSAASampleCount(); - settings.gpu_rasterization_forced = - compositor_deps->IsGpuRasterizationForced(); - - settings.can_use_lcd_text = compositor_deps->IsLcdTextEnabled(); - settings.use_zero_copy = compositor_deps->IsZeroCopyEnabled(); - settings.use_partial_raster = compositor_deps->IsPartialRasterEnabled(); - settings.enable_elastic_overscroll = - compositor_deps->IsElasticOverscrollEnabled(); - settings.resource_settings.use_gpu_memory_buffer_resources = - compositor_deps->IsGpuMemoryBufferCompositorResourcesEnabled(); - settings.enable_oop_rasterization = - cmd.HasSwitch(switches::kEnableOOPRasterization); - - // Build LayerTreeSettings from command line args. - LayerTreeSettingsFactory::SetBrowserControlsSettings(settings, cmd); - - settings.use_layer_lists = cmd.HasSwitch(cc::switches::kEnableLayerLists); - - // The means the renderer compositor has 2 possible modes: - // - Threaded compositing with a scheduler. - // - Single threaded compositing without a scheduler (for layout tests only). - // Using the scheduler in layout tests introduces additional composite steps - // that create flakiness. - settings.single_thread_proxy_scheduler = false; - - // These flags should be mirrored by UI versions in ui/compositor/. - if (cmd.HasSwitch(cc::switches::kShowCompositedLayerBorders)) - settings.initial_debug_state.show_debug_borders.set(); - settings.initial_debug_state.show_layer_animation_bounds_rects = - cmd.HasSwitch(cc::switches::kShowLayerAnimationBounds); - settings.initial_debug_state.show_paint_rects = - cmd.HasSwitch(switches::kShowPaintRects); - settings.initial_debug_state.show_property_changed_rects = - cmd.HasSwitch(cc::switches::kShowPropertyChangedRects); - settings.initial_debug_state.show_surface_damage_rects = - cmd.HasSwitch(cc::switches::kShowSurfaceDamageRects); - settings.initial_debug_state.show_screen_space_rects = - cmd.HasSwitch(cc::switches::kShowScreenSpaceRects); - - settings.initial_debug_state.SetRecordRenderingStats( - cmd.HasSwitch(cc::switches::kEnableGpuBenchmarking)); - settings.enable_surface_synchronization = - features::IsSurfaceSynchronizationEnabled(); - settings.build_hit_test_data = features::IsVizHitTestingSurfaceLayerEnabled(); - - if (cmd.HasSwitch(cc::switches::kSlowDownRasterScaleFactor)) { - const int kMinSlowDownScaleFactor = 0; - const int kMaxSlowDownScaleFactor = INT_MAX; - GetSwitchValueAsInt( - cmd, cc::switches::kSlowDownRasterScaleFactor, kMinSlowDownScaleFactor, - kMaxSlowDownScaleFactor, - &settings.initial_debug_state.slow_down_raster_scale_factor); - } - - // This is default overlay scrollbar settings for Android and DevTools mobile - // emulator. Aura Overlay Scrollbar will override below. - settings.scrollbar_animator = cc::LayerTreeSettings::ANDROID_OVERLAY; - settings.solid_color_scrollbar_color = SkColorSetARGB(128, 128, 128, 128); - settings.scrollbar_fade_delay = base::TimeDelta::FromMilliseconds(300); - settings.scrollbar_fade_duration = base::TimeDelta::FromMilliseconds(300); - - -#if defined(OS_ANDROID) - bool using_synchronous_compositor = - GetContentClient()->UsingSynchronousCompositing(); - bool using_low_memory_policy = base::SysInfo::IsLowEndDevice(); - - settings.use_stream_video_draw_quad = true; - settings.using_synchronous_renderer_compositor = using_synchronous_compositor; - if (using_synchronous_compositor) { - // Android WebView uses system scrollbars, so make ours invisible. - // http://crbug.com/677348: This can't be done using hide_scrollbars - // setting because supporting -webkit custom scrollbars is still desired - // on sublayers. - settings.scrollbar_animator = cc::LayerTreeSettings::NO_ANIMATOR; - settings.solid_color_scrollbar_color = SK_ColorTRANSPARENT; - - settings.enable_early_damage_check = - cmd.HasSwitch(cc::switches::kCheckDamageEarly); - } - // Android WebView handles root layer flings itself. - settings.ignore_root_layer_flings = using_synchronous_compositor; - // Memory policy on Android WebView does not depend on whether device is - // low end, so always use default policy. - if (using_low_memory_policy && !using_synchronous_compositor) { - // On low-end we want to be very carefull about killing other - // apps. So initially we use 50% more memory to avoid flickering - // or raster-on-demand. - settings.max_memory_for_prepaint_percentage = 67; - } else { - // On other devices we have increased memory excessively to avoid - // raster-on-demand already, so now we reserve 50% _only_ to avoid - // raster-on-demand, and use 50% of the memory otherwise. - settings.max_memory_for_prepaint_percentage = 50; - } - - // TODO(danakj): Only do this on low end devices. - settings.create_low_res_tiling = true; - -#else // defined(OS_ANDROID) - bool using_synchronous_compositor = false; // Only for Android WebView. - // On desktop, we never use the low memory policy unless we are simulating - // low-end mode via a switch. - bool using_low_memory_policy = - cmd.HasSwitch(switches::kEnableLowEndDeviceMode); - - if (ui::IsOverlayScrollbarEnabled()) { - settings.scrollbar_animator = cc::LayerTreeSettings::AURA_OVERLAY; - settings.scrollbar_fade_delay = ui::kOverlayScrollbarFadeDelay; - settings.scrollbar_fade_duration = ui::kOverlayScrollbarFadeDuration; - settings.scrollbar_thinning_duration = - ui::kOverlayScrollbarThinningDuration; - settings.scrollbar_flash_after_any_scroll_update = - ui::OverlayScrollbarFlashAfterAnyScrollUpdate(); - settings.scrollbar_flash_when_mouse_enter = - ui::OverlayScrollbarFlashWhenMouseEnter(); - } - - // On desktop, if there's over 4GB of memory on the machine, increase the - // working set size to 256MB for both gpu and software. - const int kImageDecodeMemoryThresholdMB = 4 * 1024; - if (base::SysInfo::AmountOfPhysicalMemoryMB() >= - kImageDecodeMemoryThresholdMB) { - settings.decoded_image_working_set_budget_bytes = 256 * 1024 * 1024; - } else { - // This is the default, but recorded here as well. - settings.decoded_image_working_set_budget_bytes = 128 * 1024 * 1024; - } -#endif // defined(OS_ANDROID) - - if (using_low_memory_policy) { - // RGBA_4444 textures are only enabled: - // - If the user hasn't explicitly disabled them - // - If system ram is <= 512MB (1GB devices are sometimes low-end). - // - If we are not running in a WebView, where 4444 isn't supported. - if (!cmd.HasSwitch(switches::kDisableRGBA4444Textures) && - base::SysInfo::AmountOfPhysicalMemoryMB() <= 512 && - !using_synchronous_compositor) { - settings.use_rgba_4444 = viz::RGBA_4444; - - // If we are going to unpremultiply and dither these tiles, we need to - // allocate an additional RGBA_8888 intermediate for each tile - // rasterization when rastering to RGBA_4444 to allow for dithering. - // Setting a reasonable sized max tile size allows this intermediate to - // be consistently reused. - if (base::FeatureList::IsEnabled( - kUnpremultiplyAndDitherLowBitDepthTiles)) { - settings.max_gpu_raster_tile_size = gfx::Size(512, 256); - settings.unpremultiply_and_dither_low_bit_depth_tiles = true; - } - } - } - - if (cmd.HasSwitch(switches::kEnableLowResTiling)) - settings.create_low_res_tiling = true; - if (cmd.HasSwitch(switches::kDisableLowResTiling)) - settings.create_low_res_tiling = false; - - if (cmd.HasSwitch(switches::kEnableRGBA4444Textures) && - !cmd.HasSwitch(switches::kDisableRGBA4444Textures)) { - settings.use_rgba_4444 = true; - } - - settings.max_staging_buffer_usage_in_bytes = 32 * 1024 * 1024; // 32MB - // Use 1/4th of staging buffers on low-end devices. - if (base::SysInfo::IsLowEndDevice()) - settings.max_staging_buffer_usage_in_bytes /= 4; - - cc::ManagedMemoryPolicy defaults = settings.memory_policy; - settings.memory_policy = GetGpuMemoryPolicy(defaults, screen_info); - - settings.disallow_non_exact_resource_reuse = - cmd.HasSwitch(switches::kDisallowNonExactResourceReuse); -#if defined(OS_ANDROID) - // TODO(crbug.com/746931): This feature appears to be causing visual - // corruption on certain android devices. Will investigate and re-enable. - settings.disallow_non_exact_resource_reuse = true; -#endif - - if (cmd.HasSwitch(switches::kRunAllCompositorStagesBeforeDraw)) { - settings.wait_for_all_pipeline_stages_before_draw = true; - settings.enable_latency_recovery = false; - } - - settings.enable_image_animation_resync = - !cmd.HasSwitch(switches::kDisableImageAnimationResync); - - settings.always_request_presentation_time = - cmd.HasSwitch(cc::switches::kAlwaysRequestPresentationTime); - - settings.use_painted_device_scale_factor = IsUseZoomForDSFEnabled(); - return settings; -} - -// static -cc::ManagedMemoryPolicy RenderWidgetCompositor::GetGpuMemoryPolicy( - const cc::ManagedMemoryPolicy& default_policy, - const ScreenInfo& screen_info) { - cc::ManagedMemoryPolicy actual = default_policy; - actual.bytes_limit_when_visible = 0; - - // If the value was overridden on the command line, use the specified value. - static bool client_hard_limit_bytes_overridden = - base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kForceGpuMemAvailableMb); - if (client_hard_limit_bytes_overridden) { - if (base::StringToSizeT( - base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( - switches::kForceGpuMemAvailableMb), - &actual.bytes_limit_when_visible)) - actual.bytes_limit_when_visible *= 1024 * 1024; - return actual; - } - -#if defined(OS_ANDROID) - // We can't query available GPU memory from the system on Android. - // Physical memory is also mis-reported sometimes (eg. Nexus 10 reports - // 1262MB when it actually has 2GB, while Razr M has 1GB but only reports - // 128MB java heap size). First we estimate physical memory using both. - size_t dalvik_mb = base::SysInfo::DalvikHeapSizeMB(); - size_t physical_mb = base::SysInfo::AmountOfPhysicalMemoryMB(); - size_t physical_memory_mb = 0; - if (base::SysInfo::IsLowEndDevice()) { - // TODO(crbug.com/742534): The code below appears to no longer work. - // |dalvik_mb| no longer follows the expected heuristic pattern, causing us - // to over-estimate memory on low-end devices. This entire section probably - // needs to be re-written, but for now we can address the low-end Android - // issues by ignoring |dalvik_mb|. - physical_memory_mb = physical_mb; - } else if (dalvik_mb >= 256) { - physical_memory_mb = dalvik_mb * 4; - } else { - physical_memory_mb = std::max(dalvik_mb * 4, (physical_mb * 4) / 3); - } - - // Now we take a default of 1/8th of memory on high-memory devices, - // and gradually scale that back for low-memory devices (to be nicer - // to other apps so they don't get killed). Examples: - // Nexus 4/10(2GB) 256MB (normally 128MB) - // Droid Razr M(1GB) 114MB (normally 57MB) - // Galaxy Nexus(1GB) 100MB (normally 50MB) - // Xoom(1GB) 100MB (normally 50MB) - // Nexus S(low-end) 8MB (normally 8MB) - // Note that the compositor now uses only some of this memory for - // pre-painting and uses the rest only for 'emergencies'. - if (actual.bytes_limit_when_visible == 0) { - // NOTE: Non-low-end devices use only 50% of these limits, - // except during 'emergencies' where 100% can be used. - if (physical_memory_mb >= 1536) - actual.bytes_limit_when_visible = physical_memory_mb / 8; // >192MB - else if (physical_memory_mb >= 1152) - actual.bytes_limit_when_visible = physical_memory_mb / 8; // >144MB - else if (physical_memory_mb >= 768) - actual.bytes_limit_when_visible = physical_memory_mb / 10; // >76MB - else if (physical_memory_mb >= 513) - actual.bytes_limit_when_visible = physical_memory_mb / 12; // <64MB - else - // Devices with this little RAM have very little headroom so we hardcode - // the limit rather than relying on the heuristics above. (They also use - // 4444 textures so we can use a lower limit.) - actual.bytes_limit_when_visible = 8; - - actual.bytes_limit_when_visible = - actual.bytes_limit_when_visible * 1024 * 1024; - // Clamp the observed value to a specific range on Android. - actual.bytes_limit_when_visible = std::max( - actual.bytes_limit_when_visible, static_cast<size_t>(8 * 1024 * 1024)); - actual.bytes_limit_when_visible = - std::min(actual.bytes_limit_when_visible, - static_cast<size_t>(256 * 1024 * 1024)); - } - actual.priority_cutoff_when_visible = - gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING; -#else - // Ignore what the system said and give all clients the same maximum - // allocation on desktop platforms. - actual.bytes_limit_when_visible = 512 * 1024 * 1024; - actual.priority_cutoff_when_visible = - gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE; - - // For large monitors (4k), double the tile memory to avoid frequent out of - // memory problems. 4k could mean a screen width of anywhere from 3840 to 4096 - // (see https://en.wikipedia.org/wiki/4K_resolution). We use 3500 as a proxy - // for "large enough". - static const int kLargeDisplayThreshold = 3500; - int display_width = - std::round(screen_info.rect.width() * screen_info.device_scale_factor); - if (display_width >= kLargeDisplayThreshold) - actual.bytes_limit_when_visible *= 2; -#endif - return actual; -} - -void RenderWidgetCompositor::SetNeverVisible() { - DCHECK(!layer_tree_host_->IsVisible()); - never_visible_ = true; -} - -const base::WeakPtr<cc::InputHandler>& -RenderWidgetCompositor::GetInputHandler() { - return layer_tree_host_->GetInputHandler(); -} - -void RenderWidgetCompositor::SetNeedsDisplayOnAllLayers() { - layer_tree_host_->SetNeedsDisplayOnAllLayers(); -} - -void RenderWidgetCompositor::SetRasterizeOnlyVisibleContent() { - cc::LayerTreeDebugState current = layer_tree_host_->GetDebugState(); - current.rasterize_only_visible_content = true; - layer_tree_host_->SetDebugState(current); -} - -void RenderWidgetCompositor::SetNeedsRedrawRect(gfx::Rect damage_rect) { - layer_tree_host_->SetNeedsRedrawRect(damage_rect); -} - -bool RenderWidgetCompositor::IsSurfaceSynchronizationEnabled() const { - return layer_tree_host_->GetSettings().enable_surface_synchronization; -} - -void RenderWidgetCompositor::SetNeedsForcedRedraw() { - layer_tree_host_->SetNeedsCommitWithForcedRedraw(); -} - -std::unique_ptr<cc::SwapPromiseMonitor> -RenderWidgetCompositor::CreateLatencyInfoSwapPromiseMonitor( - ui::LatencyInfo* latency) { - return std::make_unique<cc::LatencyInfoSwapPromiseMonitor>( - latency, layer_tree_host_->GetSwapPromiseManager(), nullptr); -} - -void RenderWidgetCompositor::QueueSwapPromise( - std::unique_ptr<cc::SwapPromise> swap_promise) { - layer_tree_host_->QueueSwapPromise(std::move(swap_promise)); -} - -int RenderWidgetCompositor::GetSourceFrameNumber() const { - return layer_tree_host_->SourceFrameNumber(); -} - -void RenderWidgetCompositor::NotifyInputThrottledUntilCommit() { - layer_tree_host_->NotifyInputThrottledUntilCommit(); -} - -const cc::Layer* RenderWidgetCompositor::GetRootLayer() const { - return layer_tree_host_->root_layer(); -} - -int RenderWidgetCompositor::ScheduleMicroBenchmark( - const std::string& name, - std::unique_ptr<base::Value> value, - const base::Callback<void(std::unique_ptr<base::Value>)>& callback) { - return layer_tree_host_->ScheduleMicroBenchmark(name, std::move(value), - callback); -} - -bool RenderWidgetCompositor::SendMessageToMicroBenchmark( - int id, - std::unique_ptr<base::Value> value) { - return layer_tree_host_->SendMessageToMicroBenchmark(id, std::move(value)); -} - -void RenderWidgetCompositor::SetViewportSizeAndScale( - const gfx::Size& device_viewport_size, - float device_scale_factor, - const viz::LocalSurfaceId& local_surface_id) { - layer_tree_host_->SetViewportSizeAndScale( - device_viewport_size, device_scale_factor, local_surface_id); -} - -void RenderWidgetCompositor::RequestNewLocalSurfaceId() { - layer_tree_host_->RequestNewLocalSurfaceId(); -} - -bool RenderWidgetCompositor::HasNewLocalSurfaceIdRequest() const { - return layer_tree_host_->new_local_surface_id_request_for_testing(); -} - -void RenderWidgetCompositor::SetViewportVisibleRect( - const gfx::Rect& visible_rect) { - layer_tree_host_->SetViewportVisibleRect(visible_rect); -} - -viz::FrameSinkId RenderWidgetCompositor::GetFrameSinkId() { - return frame_sink_id_; -} - -void RenderWidgetCompositor::SetRootLayer(scoped_refptr<cc::Layer> layer) { - layer_tree_host_->SetRootLayer(std::move(layer)); -} - -void RenderWidgetCompositor::ClearRootLayer() { - layer_tree_host_->SetRootLayer(nullptr); -} - -cc::AnimationHost* RenderWidgetCompositor::CompositorAnimationHost() { - return animation_host_.get(); -} - -blink::WebSize RenderWidgetCompositor::GetViewportSize() const { - return layer_tree_host_->device_viewport_size(); -} - -blink::WebFloatPoint RenderWidgetCompositor::adjustEventPointForPinchZoom( - const blink::WebFloatPoint& point) const { - return point; -} - -void RenderWidgetCompositor::SetBackgroundColor(SkColor color) { - layer_tree_host_->set_background_color(color); -} - -void RenderWidgetCompositor::SetVisible(bool visible) { - if (never_visible_) - return; - - layer_tree_host_->SetVisible(visible); - - if (visible && layer_tree_frame_sink_request_failed_while_invisible_) - DidFailToInitializeLayerTreeFrameSink(); -} - -void RenderWidgetCompositor::SetPageScaleFactorAndLimits( - float page_scale_factor, - float minimum, - float maximum) { - layer_tree_host_->SetPageScaleFactorAndLimits(page_scale_factor, minimum, - maximum); -} - -void RenderWidgetCompositor::StartPageScaleAnimation( - const blink::WebPoint& destination, - bool use_anchor, - float new_page_scale, - double duration_sec) { - base::TimeDelta duration = base::TimeDelta::FromMicroseconds( - duration_sec * base::Time::kMicrosecondsPerSecond); - layer_tree_host_->StartPageScaleAnimation( - gfx::Vector2d(destination.x, destination.y), use_anchor, new_page_scale, - duration); -} - -bool RenderWidgetCompositor::HasPendingPageScaleAnimation() const { - return layer_tree_host_->HasPendingPageScaleAnimation(); -} - -void RenderWidgetCompositor::HeuristicsForGpuRasterizationUpdated( - bool matches_heuristics) { - layer_tree_host_->SetHasGpuRasterizationTrigger(matches_heuristics); -} - -void RenderWidgetCompositor::SetNeedsBeginFrame() { - layer_tree_host_->SetNeedsAnimate(); -} - -void RenderWidgetCompositor::DidStopFlinging() { - layer_tree_host_->DidStopFlinging(); -} - -void RenderWidgetCompositor::RegisterViewportLayers( - const blink::WebLayerTreeView::ViewportLayers& layers) { - cc::LayerTreeHost::ViewportLayers viewport_layers; - // TODO(bokan): This check can probably be removed now, but it looks - // like overscroll elasticity may still be nullptr until VisualViewport - // registers its layers. - if (layers.overscroll_elasticity) { - viewport_layers.overscroll_elasticity = layers.overscroll_elasticity; - } - viewport_layers.page_scale = layers.page_scale; - if (layers.inner_viewport_container) { - viewport_layers.inner_viewport_container = layers.inner_viewport_container; - } - if (layers.outer_viewport_container) { - viewport_layers.outer_viewport_container = layers.outer_viewport_container; - } - viewport_layers.inner_viewport_scroll = layers.inner_viewport_scroll; - // TODO(bokan): This check can probably be removed now, but it looks - // like overscroll elasticity may still be nullptr until VisualViewport - // registers its layers. - if (layers.outer_viewport_scroll) { - viewport_layers.outer_viewport_scroll = layers.outer_viewport_scroll; - } - layer_tree_host_->RegisterViewportLayers(viewport_layers); -} - -void RenderWidgetCompositor::ClearViewportLayers() { - layer_tree_host_->RegisterViewportLayers(cc::LayerTreeHost::ViewportLayers()); -} - -void RenderWidgetCompositor::RegisterSelection( - const blink::WebSelection& selection) { - layer_tree_host_->RegisterSelection(ConvertFromWebSelection(selection)); -} - -void RenderWidgetCompositor::ClearSelection() { - cc::LayerSelection empty_selection; - layer_tree_host_->RegisterSelection(empty_selection); -} - -void RenderWidgetCompositor::SetMutatorClient( - std::unique_ptr<cc::LayerTreeMutator> client) { - TRACE_EVENT0("cc", "RenderWidgetCompositor::setMutatorClient"); - layer_tree_host_->SetLayerTreeMutator(std::move(client)); -} - -void RenderWidgetCompositor::ForceRecalculateRasterScales() { - layer_tree_host_->SetNeedsRecalculateRasterScales(); -} - -static_assert(static_cast<cc::EventListenerClass>( - blink::WebEventListenerClass::kTouchStartOrMove) == - cc::EventListenerClass::kTouchStartOrMove, - "EventListenerClass and WebEventListenerClass enums must match"); -static_assert(static_cast<cc::EventListenerClass>( - blink::WebEventListenerClass::kMouseWheel) == - cc::EventListenerClass::kMouseWheel, - "EventListenerClass and WebEventListenerClass enums must match"); - -static_assert(static_cast<cc::EventListenerProperties>( - blink::WebEventListenerProperties::kNothing) == - cc::EventListenerProperties::kNone, - "EventListener and WebEventListener enums must match"); -static_assert(static_cast<cc::EventListenerProperties>( - blink::WebEventListenerProperties::kPassive) == - cc::EventListenerProperties::kPassive, - "EventListener and WebEventListener enums must match"); -static_assert(static_cast<cc::EventListenerProperties>( - blink::WebEventListenerProperties::kBlocking) == - cc::EventListenerProperties::kBlocking, - "EventListener and WebEventListener enums must match"); -static_assert(static_cast<cc::EventListenerProperties>( - blink::WebEventListenerProperties::kBlockingAndPassive) == - cc::EventListenerProperties::kBlockingAndPassive, - "EventListener and WebEventListener enums must match"); - -void RenderWidgetCompositor::SetEventListenerProperties( - blink::WebEventListenerClass eventClass, - blink::WebEventListenerProperties properties) { - layer_tree_host_->SetEventListenerProperties( - static_cast<cc::EventListenerClass>(eventClass), - static_cast<cc::EventListenerProperties>(properties)); -} - -blink::WebEventListenerProperties -RenderWidgetCompositor::EventListenerProperties( - blink::WebEventListenerClass event_class) const { - return static_cast<blink::WebEventListenerProperties>( - layer_tree_host_->event_listener_properties( - static_cast<cc::EventListenerClass>(event_class))); -} - -void RenderWidgetCompositor::SetHaveScrollEventHandlers(bool has_handlers) { - layer_tree_host_->SetHaveScrollEventHandlers(has_handlers); -} - -bool RenderWidgetCompositor::HaveScrollEventHandlers() const { - return layer_tree_host_->have_scroll_event_handlers(); -} - -bool RenderWidgetCompositor::CompositeIsSynchronous() const { - if (!threaded_) { - DCHECK(!layer_tree_host_->GetSettings().single_thread_proxy_scheduler); - return true; - } - return false; -} - -void RenderWidgetCompositor::LayoutAndPaintAsync(base::OnceClosure callback) { - DCHECK(layout_and_paint_async_callback_.is_null()); - layout_and_paint_async_callback_ = std::move(callback); - - if (CompositeIsSynchronous()) { - // The LayoutAndPaintAsyncCallback is invoked in WillCommit, which is - // dispatched after layout and paint for all compositing modes. - const bool raster = false; - layer_tree_host_->GetTaskRunnerProvider()->MainThreadTaskRunner()->PostTask( - FROM_HERE, - base::BindOnce(&RenderWidgetCompositor::SynchronouslyComposite, - weak_factory_.GetWeakPtr(), raster, nullptr)); - } else { - layer_tree_host_->SetNeedsCommit(); - } -} - -void RenderWidgetCompositor::SetLayerTreeFrameSink( - std::unique_ptr<cc::LayerTreeFrameSink> layer_tree_frame_sink) { - if (!layer_tree_frame_sink) { - DidFailToInitializeLayerTreeFrameSink(); - return; - } - layer_tree_host_->SetLayerTreeFrameSink(std::move(layer_tree_frame_sink)); -} - -void RenderWidgetCompositor::InvokeLayoutAndPaintCallback() { - if (!layout_and_paint_async_callback_.is_null()) - std::move(layout_and_paint_async_callback_).Run(); -} - -void RenderWidgetCompositor::CompositeAndReadbackAsync( - base::OnceCallback<void(const SkBitmap&)> callback) { - DCHECK(layout_and_paint_async_callback_.is_null()); - scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner = - layer_tree_host_->GetTaskRunnerProvider()->MainThreadTaskRunner(); - std::unique_ptr<viz::CopyOutputRequest> request = - std::make_unique<viz::CopyOutputRequest>( - viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP, - base::BindOnce( - [](base::OnceCallback<void(const SkBitmap&)> callback, - scoped_refptr<base::SingleThreadTaskRunner> task_runner, - std::unique_ptr<viz::CopyOutputResult> result) { - task_runner->PostTask( - FROM_HERE, - base::BindOnce(std::move(callback), result->AsSkBitmap())); - }, - std::move(callback), std::move(main_thread_task_runner))); - auto swap_promise = - delegate_->RequestCopyOfOutputForLayoutTest(std::move(request)); - - // Force a commit to happen. The temporary copy output request will - // be installed after layout which will happen as a part of the commit, for - // widgets that delay the creation of their output surface. - if (CompositeIsSynchronous()) { - // Since the composite is required for a pixel dump, we need to raster. - // Note that we defer queuing the SwapPromise until the requested Composite - // with rasterization is done. - const bool raster = true; - layer_tree_host_->GetTaskRunnerProvider()->MainThreadTaskRunner()->PostTask( - FROM_HERE, - base::BindOnce(&RenderWidgetCompositor::SynchronouslyComposite, - weak_factory_.GetWeakPtr(), raster, - std::move(swap_promise))); - } else { - // Force a redraw to ensure that the copy swap promise isn't cancelled due - // to no damage. - SetNeedsForcedRedraw(); - layer_tree_host_->QueueSwapPromise(std::move(swap_promise)); - layer_tree_host_->SetNeedsCommit(); - } -} - -void RenderWidgetCompositor::SynchronouslyCompositeNoRasterForTesting() { - SynchronouslyComposite(false /* raster */, nullptr /* swap_promise */); -} - -void RenderWidgetCompositor::CompositeWithRasterForTesting() { - SynchronouslyComposite(true /* raster */, nullptr /* swap_promise */); -} - -void RenderWidgetCompositor::SynchronouslyComposite( - bool raster, - std::unique_ptr<cc::SwapPromise> swap_promise) { - DCHECK(CompositeIsSynchronous()); - if (!layer_tree_host_->IsVisible()) - return; - - if (in_synchronous_compositor_update_) { - // LayoutTests can use a nested message loop to pump frames while inside a - // frame, but the compositor does not support this. In this case, we only - // run blink's lifecycle updates. - delegate_->BeginMainFrame(base::TimeTicks::Now()); - delegate_->UpdateVisualState( - cc::LayerTreeHostClient::VisualStateUpdate::kAll); - return; - } - - if (swap_promise) { - // Force a redraw to ensure that the copy swap promise isn't cancelled due - // to no damage. - SetNeedsForcedRedraw(); - layer_tree_host_->QueueSwapPromise(std::move(swap_promise)); - } - - DCHECK(!in_synchronous_compositor_update_); - base::AutoReset<bool> inside_composite(&in_synchronous_compositor_update_, - true); - layer_tree_host_->Composite(base::TimeTicks::Now(), raster); -} - -void RenderWidgetCompositor::SetDeferCommits(bool defer_commits) { - layer_tree_host_->SetDeferCommits(defer_commits); -} - -int RenderWidgetCompositor::LayerTreeId() const { - return layer_tree_host_->GetId(); -} - -void RenderWidgetCompositor::SetShowFPSCounter(bool show) { - cc::LayerTreeDebugState debug_state = layer_tree_host_->GetDebugState(); - debug_state.show_fps_counter = show; - layer_tree_host_->SetDebugState(debug_state); -} - -void RenderWidgetCompositor::SetShowPaintRects(bool show) { - cc::LayerTreeDebugState debug_state = layer_tree_host_->GetDebugState(); - debug_state.show_paint_rects = show; - layer_tree_host_->SetDebugState(debug_state); -} - -void RenderWidgetCompositor::SetShowDebugBorders(bool show) { - cc::LayerTreeDebugState debug_state = layer_tree_host_->GetDebugState(); - if (show) - debug_state.show_debug_borders.set(); - else - debug_state.show_debug_borders.reset(); - layer_tree_host_->SetDebugState(debug_state); -} - -void RenderWidgetCompositor::SetShowScrollBottleneckRects(bool show) { - cc::LayerTreeDebugState debug_state = layer_tree_host_->GetDebugState(); - debug_state.show_touch_event_handler_rects = show; - debug_state.show_wheel_event_handler_rects = show; - debug_state.show_non_fast_scrollable_rects = show; - layer_tree_host_->SetDebugState(debug_state); -} - -void RenderWidgetCompositor::UpdateBrowserControlsState( - blink::WebBrowserControlsState constraints, - blink::WebBrowserControlsState current, - bool animate) { - layer_tree_host_->UpdateBrowserControlsState( - ConvertBrowserControlsState(constraints), - ConvertBrowserControlsState(current), animate); -} - -void RenderWidgetCompositor::SetBrowserControlsHeight(float top_height, - float bottom_height, - bool shrink) { - layer_tree_host_->SetBrowserControlsHeight(top_height, bottom_height, shrink); -} - -void RenderWidgetCompositor::SetBrowserControlsShownRatio(float ratio) { - layer_tree_host_->SetBrowserControlsShownRatio(ratio); -} - -void RenderWidgetCompositor::RequestDecode( - const cc::PaintImage& image, - base::OnceCallback<void(bool)> callback) { - layer_tree_host_->QueueImageDecode(image, std::move(callback)); - - // If we're compositing synchronously, the SetNeedsCommit call which will be - // issued by |layer_tree_host_| is not going to cause a commit, due to the - // fact that this would make layout tests slow and cause flakiness. However, - // in this case we actually need a commit to transfer the decode requests to - // the impl side. So, force a commit to happen. - if (CompositeIsSynchronous()) { - const bool raster = true; - layer_tree_host_->GetTaskRunnerProvider()->MainThreadTaskRunner()->PostTask( - FROM_HERE, - base::BindOnce(&RenderWidgetCompositor::SynchronouslyComposite, - weak_factory_.GetWeakPtr(), raster, nullptr)); - } -} - -void RenderWidgetCompositor::SetOverscrollBehavior( - const cc::OverscrollBehavior& behavior) { - layer_tree_host_->SetOverscrollBehavior(behavior); -} - -void RenderWidgetCompositor::WillBeginMainFrame() { - delegate_->WillBeginCompositorFrame(); -} - -void RenderWidgetCompositor::DidBeginMainFrame() {} - -void RenderWidgetCompositor::BeginMainFrame(const viz::BeginFrameArgs& args) { - compositor_deps_->GetWebMainThreadScheduler()->WillBeginFrame(args); - delegate_->BeginMainFrame(args.frame_time); -} - -void RenderWidgetCompositor::BeginMainFrameNotExpectedSoon() { - compositor_deps_->GetWebMainThreadScheduler()->BeginFrameNotExpectedSoon(); -} - -void RenderWidgetCompositor::BeginMainFrameNotExpectedUntil( - base::TimeTicks time) { - compositor_deps_->GetWebMainThreadScheduler()->BeginMainFrameNotExpectedUntil( - time); -} - -void RenderWidgetCompositor::UpdateLayerTreeHost( - VisualStateUpdate requested_update) { - delegate_->UpdateVisualState(requested_update); -} - -void RenderWidgetCompositor::ApplyViewportDeltas( - const gfx::Vector2dF& inner_delta, - const gfx::Vector2dF& outer_delta, - const gfx::Vector2dF& elastic_overscroll_delta, - float page_scale, - float top_controls_delta) { - delegate_->ApplyViewportDeltas(inner_delta, outer_delta, - elastic_overscroll_delta, page_scale, - top_controls_delta); -} - -void RenderWidgetCompositor::RecordWheelAndTouchScrollingCount( - bool has_scrolled_by_wheel, - bool has_scrolled_by_touch) { - delegate_->RecordWheelAndTouchScrollingCount(has_scrolled_by_wheel, - has_scrolled_by_touch); -} - -void RenderWidgetCompositor::RequestNewLayerTreeFrameSink() { - // If the host is closing, then no more compositing is possible. This - // prevents shutdown races between handling the close message and - // the CreateLayerTreeFrameSink task. - if (delegate_->IsClosing()) - return; - delegate_->RequestNewLayerTreeFrameSink( - base::Bind(&RenderWidgetCompositor::SetLayerTreeFrameSink, - weak_factory_.GetWeakPtr())); -} - -void RenderWidgetCompositor::DidInitializeLayerTreeFrameSink() { -} - -void RenderWidgetCompositor::DidFailToInitializeLayerTreeFrameSink() { - if (!layer_tree_host_->IsVisible()) { - layer_tree_frame_sink_request_failed_while_invisible_ = true; - return; - } - layer_tree_frame_sink_request_failed_while_invisible_ = false; - layer_tree_host_->GetTaskRunnerProvider()->MainThreadTaskRunner()->PostTask( - FROM_HERE, - base::BindOnce(&RenderWidgetCompositor::RequestNewLayerTreeFrameSink, - weak_factory_.GetWeakPtr())); -} - -void RenderWidgetCompositor::WillCommit() { - InvokeLayoutAndPaintCallback(); -} - -void RenderWidgetCompositor::DidCommit() { - delegate_->DidCommitCompositorFrame(); - compositor_deps_->GetWebMainThreadScheduler()->DidCommitFrameToCompositor(); -} - -void RenderWidgetCompositor::DidCommitAndDrawFrame() { - delegate_->DidCommitAndDrawCompositorFrame(); -} - -void RenderWidgetCompositor::DidReceiveCompositorFrameAck() { - delegate_->DidReceiveCompositorFrameAck(); -} - -void RenderWidgetCompositor::DidCompletePageScaleAnimation() { - delegate_->DidCompletePageScaleAnimation(); -} - -bool RenderWidgetCompositor::IsForSubframe() { - return is_for_oopif_; -} - -void RenderWidgetCompositor::RequestScheduleAnimation() { - delegate_->RequestScheduleAnimation(); -} - -void RenderWidgetCompositor::DidSubmitCompositorFrame() {} - -void RenderWidgetCompositor::DidLoseLayerTreeFrameSink() {} - -void RenderWidgetCompositor::SetFrameSinkId( - const viz::FrameSinkId& frame_sink_id) { - frame_sink_id_ = frame_sink_id; -} - -void RenderWidgetCompositor::SetRasterColorSpace( - const gfx::ColorSpace& color_space) { - layer_tree_host_->SetRasterColorSpace(color_space); -} - -void RenderWidgetCompositor::SetIsForOopif(bool is_for_oopif) { - is_for_oopif_ = is_for_oopif; -} - -void RenderWidgetCompositor::SetContentSourceId(uint32_t id) { - layer_tree_host_->SetContentSourceId(id); -} - -void RenderWidgetCompositor::NotifySwapTime(ReportTimeCallback callback) { - QueueSwapPromise(std::make_unique<ReportTimeSwapPromise>( - std::move(callback), - layer_tree_host_->GetTaskRunnerProvider()->MainThreadTaskRunner())); -} - -void RenderWidgetCompositor::RequestBeginMainFrameNotExpected(bool new_state) { - layer_tree_host_->RequestBeginMainFrameNotExpected(new_state); -} - -void RenderWidgetCompositor::CreateRenderFrameObserver( - mojom::RenderFrameMetadataObserverRequest request, - mojom::RenderFrameMetadataObserverClientPtrInfo client_info) { - auto render_frame_metadata_observer = - std::make_unique<RenderFrameMetadataObserverImpl>(std::move(request), - std::move(client_info)); - layer_tree_host_->SetRenderFrameObserver( - std::move(render_frame_metadata_observer)); -} - -void RenderWidgetCompositor::SetURLForUkm(const GURL& url) { - layer_tree_host_->SetURLForUkm(url); -} - -} // namespace content diff --git a/chromium/content/renderer/gpu/render_widget_compositor_unittest.cc b/chromium/content/renderer/gpu/render_widget_compositor_unittest.cc deleted file mode 100644 index b0cd76d9bb5..00000000000 --- a/chromium/content/renderer/gpu/render_widget_compositor_unittest.cc +++ /dev/null @@ -1,425 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/gpu/render_widget_compositor.h" - -#include <utility> - -#include "base/location.h" -#include "base/macros.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "build/build_config.h" -#include "cc/animation/animation_host.h" -#include "cc/test/fake_layer_tree_frame_sink.h" -#include "cc/trees/layer_tree_host.h" -#include "components/viz/common/frame_sinks/copy_output_request.h" -#include "components/viz/test/test_context_provider.h" -#include "content/public/common/screen_info.h" -#include "content/public/test/mock_render_thread.h" -#include "content/renderer/render_widget.h" -#include "content/test/fake_compositor_dependencies.h" -#include "gpu/GLES2/gl2extchromium.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" - -using testing::AllOf; -using testing::Field; - -namespace content { -namespace { - -enum FailureMode { - NO_FAILURE, - BIND_CONTEXT_FAILURE, - GPU_CHANNEL_FAILURE, -}; - -class StubRenderWidgetCompositorDelegate - : public RenderWidgetCompositorDelegate { - public: - // RenderWidgetCompositorDelegate implementation. - void ApplyViewportDeltas(const gfx::Vector2dF& inner_delta, - const gfx::Vector2dF& outer_delta, - const gfx::Vector2dF& elastic_overscroll_delta, - float page_scale, - float top_controls_delta) override {} - void RecordWheelAndTouchScrollingCount(bool has_scrolled_by_wheel, - bool has_scrolled_by_touch) override {} - void BeginMainFrame(base::TimeTicks frame_time) override {} - void RequestNewLayerTreeFrameSink( - const LayerTreeFrameSinkCallback& callback) override { - callback.Run(nullptr); - } - void DidCommitAndDrawCompositorFrame() override {} - void DidCommitCompositorFrame() override {} - void DidCompletePageScaleAnimation() override {} - void DidReceiveCompositorFrameAck() override {} - bool IsClosing() const override { return false; } - void RequestScheduleAnimation() override {} - void UpdateVisualState(VisualStateUpdate requested_update) override {} - void WillBeginCompositorFrame() override {} - std::unique_ptr<cc::SwapPromise> RequestCopyOfOutputForLayoutTest( - std::unique_ptr<viz::CopyOutputRequest> request) override { - return nullptr; - } -}; - -class FakeRenderWidgetCompositorDelegate - : public StubRenderWidgetCompositorDelegate { - public: - FakeRenderWidgetCompositorDelegate() = default; - - void RequestNewLayerTreeFrameSink( - const LayerTreeFrameSinkCallback& callback) override { - // Subtract one cuz the current request has already been counted but should - // not be included for this. - if (num_requests_since_last_success_ - 1 < num_requests_before_success_) { - callback.Run(std::unique_ptr<cc::LayerTreeFrameSink>()); - return; - } - - auto context_provider = viz::TestContextProvider::Create(); - if (num_failures_since_last_success_ < num_failures_before_success_) { - context_provider->UnboundTestContext3d()->loseContextCHROMIUM( - GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB); - } - callback.Run( - cc::FakeLayerTreeFrameSink::Create3d(std::move(context_provider))); - } - - void Reset() { - num_requests_ = 0; - num_requests_before_success_ = 0; - num_requests_since_last_success_ = 0; - num_failures_ = 0; - num_failures_before_success_ = 0; - num_failures_since_last_success_ = 0; - num_successes_ = 0; - } - - void add_success() { - ++num_successes_; - num_requests_since_last_success_ = 0; - num_failures_since_last_success_ = 0; - } - int num_successes() const { return num_successes_; } - - void add_request() { - ++num_requests_since_last_success_; - ++num_requests_; - } - int num_requests() const { return num_requests_; } - - void add_failure() { - ++num_failures_since_last_success_; - ++num_failures_; - } - int num_failures() const { return num_failures_; } - - void set_num_requests_before_success(int n) { - num_requests_before_success_ = n; - } - void set_num_failures_before_success(int n) { - num_failures_before_success_ = n; - } - int num_failures_before_success() const { - return num_failures_before_success_; - } - - private: - int num_requests_ = 0; - int num_requests_before_success_ = 0; - int num_requests_since_last_success_ = 0; - int num_failures_ = 0; - int num_failures_before_success_ = 0; - int num_failures_since_last_success_ = 0; - int num_successes_ = 0; - - DISALLOW_COPY_AND_ASSIGN(FakeRenderWidgetCompositorDelegate); -}; - -// Verify that failing to create an output surface will cause the compositor -// to attempt to repeatedly create another output surface. -// The use null output surface parameter allows testing whether failures -// from RenderWidget (couldn't create an output surface) vs failures from -// the compositor (couldn't bind the output surface) are handled identically. -class RenderWidgetLayerTreeFrameSink : public RenderWidgetCompositor { - public: - RenderWidgetLayerTreeFrameSink(FakeRenderWidgetCompositorDelegate* delegate, - CompositorDependencies* compositor_deps) - : RenderWidgetCompositor(delegate, compositor_deps), - delegate_(delegate) {} - - using RenderWidgetCompositor::Initialize; - - // Force a new output surface to be created. - void SynchronousComposite() { - layer_tree_host()->SetVisible(false); - layer_tree_host()->ReleaseLayerTreeFrameSink(); - layer_tree_host()->SetVisible(true); - - base::TimeTicks some_time; - layer_tree_host()->Composite(some_time, true /* raster */); - } - - void RequestNewLayerTreeFrameSink() override { - delegate_->add_request(); - RenderWidgetCompositor::RequestNewLayerTreeFrameSink(); - } - - void DidInitializeLayerTreeFrameSink() override { - RenderWidgetCompositor::DidInitializeLayerTreeFrameSink(); - delegate_->add_success(); - if (delegate_->num_successes() == expected_successes_) { - EXPECT_EQ(delegate_->num_requests(), expected_requests_); - EndTest(); - } else { - // Post the synchronous composite task so that it is not called - // reentrantly as a part of RequestNewLayerTreeFrameSink. - blink::scheduler::GetSingleThreadTaskRunnerForTesting()->PostTask( - FROM_HERE, - base::BindOnce(&RenderWidgetLayerTreeFrameSink::SynchronousComposite, - base::Unretained(this))); - } - } - - void DidFailToInitializeLayerTreeFrameSink() override { - RenderWidgetCompositor::DidFailToInitializeLayerTreeFrameSink(); - delegate_->add_failure(); - if (delegate_->num_requests() == expected_requests_) { - EXPECT_EQ(delegate_->num_successes(), expected_successes_); - EndTest(); - return; - } - } - - void SetUp(int expected_successes, - int num_tries, - FailureMode failure_mode, - base::RunLoop* run_loop) { - run_loop_ = run_loop; - failure_mode_ = failure_mode; - expected_successes_ = expected_successes; - switch (failure_mode_) { - case NO_FAILURE: - expected_requests_ = expected_successes; - break; - case BIND_CONTEXT_FAILURE: - case GPU_CHANNEL_FAILURE: - expected_requests_ = num_tries * std::max(1, expected_successes); - break; - } - } - - void EndTest() { run_loop_->Quit(); } - - private: - FakeRenderWidgetCompositorDelegate* delegate_; - base::RunLoop* run_loop_ = nullptr; - int expected_successes_ = 0; - int expected_requests_ = 0; - FailureMode failure_mode_ = NO_FAILURE; - - DISALLOW_COPY_AND_ASSIGN(RenderWidgetLayerTreeFrameSink); -}; - -class RenderWidgetLayerTreeFrameSinkTest : public testing::Test { - public: - RenderWidgetLayerTreeFrameSinkTest() - : render_widget_compositor_(&compositor_delegate_, &compositor_deps_) { - auto animation_host = cc::AnimationHost::CreateMainInstance(); - - ScreenInfo dummy_screen_info; - auto layer_tree_host = RenderWidgetCompositor::CreateLayerTreeHost( - &render_widget_compositor_, &render_widget_compositor_, - animation_host.get(), &compositor_deps_, dummy_screen_info); - render_widget_compositor_.Initialize(std::move(layer_tree_host), - std::move(animation_host)); - } - - void RunTest(int expected_successes, FailureMode failure_mode) { - compositor_delegate_.Reset(); - // 6 is just an artibrary "large" number to show it keeps trying. - const int kTries = 6; - // If it should fail, then it will fail every attempt, otherwise it fails - // until the last attempt. - int tries_before_success = kTries - (expected_successes ? 1 : 0); - switch (failure_mode) { - case NO_FAILURE: - compositor_delegate_.set_num_failures_before_success(0); - compositor_delegate_.set_num_requests_before_success(0); - break; - case BIND_CONTEXT_FAILURE: - compositor_delegate_.set_num_failures_before_success( - tries_before_success); - compositor_delegate_.set_num_requests_before_success(0); - break; - case GPU_CHANNEL_FAILURE: - compositor_delegate_.set_num_failures_before_success(0); - compositor_delegate_.set_num_requests_before_success( - tries_before_success); - break; - } - base::RunLoop run_loop; - render_widget_compositor_.SetUp(expected_successes, kTries, failure_mode, - &run_loop); - render_widget_compositor_.SetVisible(true); - blink::scheduler::GetSingleThreadTaskRunnerForTesting()->PostTask( - FROM_HERE, - base::BindOnce(&RenderWidgetLayerTreeFrameSink::SynchronousComposite, - base::Unretained(&render_widget_compositor_))); - run_loop.Run(); - } - - protected: - base::MessageLoop ye_olde_message_loope_; - MockRenderThread render_thread_; - FakeCompositorDependencies compositor_deps_; - FakeRenderWidgetCompositorDelegate compositor_delegate_; - RenderWidgetLayerTreeFrameSink render_widget_compositor_; - - private: - DISALLOW_COPY_AND_ASSIGN(RenderWidgetLayerTreeFrameSinkTest); -}; - -TEST_F(RenderWidgetLayerTreeFrameSinkTest, SucceedOnce) { - RunTest(1, NO_FAILURE); -} - -TEST_F(RenderWidgetLayerTreeFrameSinkTest, SucceedOnce_AfterNullChannel) { - RunTest(1, GPU_CHANNEL_FAILURE); -} - -TEST_F(RenderWidgetLayerTreeFrameSinkTest, SucceedOnce_AfterLostContext) { - RunTest(1, BIND_CONTEXT_FAILURE); -} - -TEST_F(RenderWidgetLayerTreeFrameSinkTest, SucceedTwice) { - RunTest(2, NO_FAILURE); -} - -TEST_F(RenderWidgetLayerTreeFrameSinkTest, SucceedTwice_AfterNullChannel) { - RunTest(2, GPU_CHANNEL_FAILURE); -} - -TEST_F(RenderWidgetLayerTreeFrameSinkTest, SucceedTwice_AfterLostContext) { - RunTest(2, BIND_CONTEXT_FAILURE); -} - -TEST_F(RenderWidgetLayerTreeFrameSinkTest, FailWithNullChannel) { - RunTest(0, GPU_CHANNEL_FAILURE); -} - -TEST_F(RenderWidgetLayerTreeFrameSinkTest, FailWithLostContext) { - RunTest(0, BIND_CONTEXT_FAILURE); -} - -class VisibilityTestRenderWidgetCompositor : public RenderWidgetCompositor { - public: - VisibilityTestRenderWidgetCompositor( - StubRenderWidgetCompositorDelegate* delegate, - CompositorDependencies* compositor_deps) - : RenderWidgetCompositor(delegate, compositor_deps) {} - - void RequestNewLayerTreeFrameSink() override { - RenderWidgetCompositor::RequestNewLayerTreeFrameSink(); - num_requests_sent_++; - if (run_loop_) - run_loop_->Quit(); - } - - void set_run_loop(base::RunLoop* run_loop) { run_loop_ = run_loop; } - int num_requests_sent() { return num_requests_sent_; } - - private: - int num_requests_sent_ = 0; - base::RunLoop* run_loop_; -}; - -TEST(RenderWidgetCompositorTest, VisibilityTest) { - // Test that RenderWidgetCompositor does not retry FrameSink request while - // invisible. - - base::MessageLoop message_loop; - - FakeCompositorDependencies compositor_deps; - // Synchronously callback with null FrameSink. - StubRenderWidgetCompositorDelegate compositor_delegate; - VisibilityTestRenderWidgetCompositor render_widget_compositor( - &compositor_delegate, &compositor_deps); - - auto animation_host = cc::AnimationHost::CreateMainInstance(); - ScreenInfo dummy_screen_info; - auto layer_tree_host = RenderWidgetCompositor::CreateLayerTreeHost( - &render_widget_compositor, &render_widget_compositor, - animation_host.get(), &compositor_deps, dummy_screen_info); - render_widget_compositor.Initialize(std::move(layer_tree_host), - std::move(animation_host)); - - { - // Make one request and stop immediately while invisible. - base::RunLoop run_loop; - render_widget_compositor.set_run_loop(&run_loop); - render_widget_compositor.SetVisible(false); - render_widget_compositor.RequestNewLayerTreeFrameSink(); - run_loop.Run(); - render_widget_compositor.set_run_loop(nullptr); - EXPECT_EQ(1, render_widget_compositor.num_requests_sent()); - } - - { - // Make sure there are no more requests. - base::RunLoop run_loop; - run_loop.RunUntilIdle(); - EXPECT_EQ(1, render_widget_compositor.num_requests_sent()); - } - - { - // Becoming visible retries request. - base::RunLoop run_loop; - render_widget_compositor.set_run_loop(&run_loop); - render_widget_compositor.SetVisible(true); - run_loop.Run(); - render_widget_compositor.set_run_loop(nullptr); - EXPECT_EQ(2, render_widget_compositor.num_requests_sent()); - } -} - -// Verify desktop memory limit calculations. -#if !defined(OS_ANDROID) -TEST(RenderWidgetCompositorTest, IgnoreGivenMemoryPolicy) { - auto policy = RenderWidgetCompositor::GetGpuMemoryPolicy( - cc::ManagedMemoryPolicy(256), ScreenInfo()); - EXPECT_EQ(512u * 1024u * 1024u, policy.bytes_limit_when_visible); - EXPECT_EQ(gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE, - policy.priority_cutoff_when_visible); -} - -TEST(RenderWidgetCompositorTest, LargeScreensUseMoreMemory) { - ScreenInfo screen_info; - - screen_info.rect = gfx::Rect(4096, 2160); - screen_info.device_scale_factor = 1.f; - auto policy = RenderWidgetCompositor::GetGpuMemoryPolicy( - cc::ManagedMemoryPolicy(256), screen_info); - EXPECT_EQ(2u * 512u * 1024u * 1024u, policy.bytes_limit_when_visible); - EXPECT_EQ(gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE, - policy.priority_cutoff_when_visible); - - screen_info.rect = gfx::Rect(2048, 1080); - screen_info.device_scale_factor = 2.f; - policy = RenderWidgetCompositor::GetGpuMemoryPolicy( - cc::ManagedMemoryPolicy(256), screen_info); - EXPECT_EQ(2u * 512u * 1024u * 1024u, policy.bytes_limit_when_visible); - EXPECT_EQ(gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE, - policy.priority_cutoff_when_visible); -} -#endif // !defined(OS_ANDROID) - -} // namespace -} // namespace content diff --git a/chromium/content/renderer/image_capture/image_capture_frame_grabber.cc b/chromium/content/renderer/image_capture/image_capture_frame_grabber.cc index c5e6515bb19..58c58f005e2 100644 --- a/chromium/content/renderer/image_capture/image_capture_frame_grabber.cc +++ b/chromium/content/renderer/image_capture/image_capture_frame_grabber.cc @@ -79,7 +79,7 @@ void ImageCaptureFrameGrabber::SingleShotFrameHandler::OnVideoFrameOnIOThread( return; } - const uint32 destination_pixel_format = + const uint32_t destination_pixel_format = (kN32_SkColorType == kRGBA_8888_SkColorType) ? libyuv::FOURCC_ABGR : libyuv::FOURCC_ARGB; @@ -89,7 +89,7 @@ void ImageCaptureFrameGrabber::SingleShotFrameHandler::OnVideoFrameOnIOThread( frame->stride(media::VideoFrame::kUPlane), frame->visible_data(media::VideoFrame::kVPlane), frame->stride(media::VideoFrame::kVPlane), - static_cast<uint8*>(pixmap.writable_addr()), + static_cast<uint8_t*>(pixmap.writable_addr()), pixmap.width() * 4, pixmap.width(), pixmap.height(), destination_pixel_format); @@ -98,7 +98,7 @@ void ImageCaptureFrameGrabber::SingleShotFrameHandler::OnVideoFrameOnIOThread( // This function copies any plane into the alpha channel of an ARGB image. libyuv::ARGBCopyYToAlpha(frame->visible_data(media::VideoFrame::kAPlane), frame->stride(media::VideoFrame::kAPlane), - static_cast<uint8*>(pixmap.writable_addr()), + static_cast<uint8_t*>(pixmap.writable_addr()), pixmap.width() * 4, pixmap.width(), pixmap.height()); } @@ -115,7 +115,7 @@ ImageCaptureFrameGrabber::~ImageCaptureFrameGrabber() { void ImageCaptureFrameGrabber::GrabFrame( blink::WebMediaStreamTrack* track, - WebImageCaptureGrabFrameCallbacks* callbacks) { + std::unique_ptr<blink::WebImageCaptureGrabFrameCallbacks> callbacks) { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(!!callbacks); @@ -128,8 +128,8 @@ void ImageCaptureFrameGrabber::GrabFrame( return; } - ScopedWebCallbacks<WebImageCaptureGrabFrameCallbacks> scoped_callbacks = - make_scoped_web_callbacks(callbacks, base::Bind(&OnError)); + auto scoped_callbacks = blink::MakeScopedWebCallbacks( + std::move(callbacks), base::BindOnce(&OnError)); // A SingleShotFrameHandler is bound and given to the Track to guarantee that // only one VideoFrame is converted and delivered to OnSkImage(), otherwise @@ -149,7 +149,8 @@ void ImageCaptureFrameGrabber::GrabFrame( } void ImageCaptureFrameGrabber::OnSkImage( - ScopedWebCallbacks<blink::WebImageCaptureGrabFrameCallbacks> callbacks, + blink::ScopedWebCallbacks<blink::WebImageCaptureGrabFrameCallbacks> + callbacks, sk_sp<SkImage> image) { DCHECK(thread_checker_.CalledOnValidThread()); diff --git a/chromium/content/renderer/image_capture/image_capture_frame_grabber.h b/chromium/content/renderer/image_capture/image_capture_frame_grabber.h index 99356ce9a24..547cc74f507 100644 --- a/chromium/content/renderer/image_capture/image_capture_frame_grabber.h +++ b/chromium/content/renderer/image_capture/image_capture_frame_grabber.h @@ -5,13 +5,15 @@ #ifndef CONTENT_RENDERER_IMAGE_CAPTURE_IMAGE_CAPTURE_FRAME_GRABBER_H_ #define CONTENT_RENDERER_IMAGE_CAPTURE_IMAGE_CAPTURE_FRAME_GRABBER_H_ +#include <memory> + #include "base/compiler_specific.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/threading/thread_checker.h" -#include "content/child/scoped_web_callbacks.h" #include "content/common/content_export.h" #include "content/public/renderer/media_stream_video_sink.h" +#include "third_party/blink/public/platform/scoped_web_callbacks.h" #include "third_party/blink/public/platform/web_image_capture_frame_grabber.h" namespace blink { @@ -36,15 +38,16 @@ class CONTENT_EXPORT ImageCaptureFrameGrabber final // blink::WebImageCaptureFrameGrabber implementation. void GrabFrame(blink::WebMediaStreamTrack* track, - blink::WebImageCaptureGrabFrameCallbacks* callbacks) override; + std::unique_ptr<blink::WebImageCaptureGrabFrameCallbacks> + callbacks) override; private: // Internal class to receive, convert and forward one frame. class SingleShotFrameHandler; - void OnSkImage( - ScopedWebCallbacks<blink::WebImageCaptureGrabFrameCallbacks> callbacks, - sk_sp<SkImage> image); + void OnSkImage(blink::ScopedWebCallbacks< + blink::WebImageCaptureGrabFrameCallbacks> callbacks, + sk_sp<SkImage> image); // Flag to indicate that there is a frame grabbing in progress. bool frame_grab_in_progress_; diff --git a/chromium/content/renderer/indexed_db/OWNERS b/chromium/content/renderer/indexed_db/OWNERS index bbe466e537d..a740487227f 100644 --- a/chromium/content/renderer/indexed_db/OWNERS +++ b/chromium/content/renderer/indexed_db/OWNERS @@ -1 +1,4 @@ file://content/browser/indexed_db/OWNERS + +# TEAM: storage-dev@chromium.org +# COMPONENT: Blink>Storage>IndexedDB diff --git a/chromium/content/renderer/input/frame_input_handler_impl.cc b/chromium/content/renderer/input/frame_input_handler_impl.cc index d4293d0a857..206f5181794 100644 --- a/chromium/content/renderer/input/frame_input_handler_impl.cc +++ b/chromium/content/renderer/input/frame_input_handler_impl.cc @@ -10,7 +10,7 @@ #include "base/debug/stack_trace.h" #include "base/logging.h" #include "content/common/input/ime_text_span_conversions.h" -#include "content/renderer/gpu/render_widget_compositor.h" +#include "content/renderer/gpu/layer_tree_view.h" #include "content/renderer/ime_event_guard.h" #include "content/renderer/input/widget_input_handler_manager.h" #include "content/renderer/render_thread_impl.h" @@ -280,11 +280,11 @@ void FrameInputHandlerImpl::SelectRange(const gfx::Point& base, if (!render_frame_) return; - RenderViewImpl* render_view = render_frame_->render_view(); + RenderWidget* window_widget = render_frame_->render_view()->GetWidget(); HandlingState handling_state(render_frame_, UpdateState::kIsSelectingRange); render_frame_->GetWebFrame()->SelectRange( - render_view->ConvertWindowPointToViewport(base), - render_view->ConvertWindowPointToViewport(extent)); + window_widget->ConvertWindowPointToViewport(base), + window_widget->ConvertWindowPointToViewport(extent)); } void FrameInputHandlerImpl::AdjustSelectionByCharacterOffset( @@ -334,7 +334,8 @@ void FrameInputHandlerImpl::MoveRangeSelectionExtent(const gfx::Point& extent) { return; HandlingState handling_state(render_frame_, UpdateState::kIsSelectingRange); render_frame_->GetWebFrame()->MoveRangeSelectionExtent( - render_frame_->render_view()->ConvertWindowPointToViewport(extent)); + render_frame_->render_view()->GetWidget()->ConvertWindowPointToViewport( + extent)); } void FrameInputHandlerImpl::ScrollFocusedEditableNodeIntoRect( @@ -362,9 +363,9 @@ void FrameInputHandlerImpl::MoveCaret(const gfx::Point& point) { if (!render_frame_) return; - RenderViewImpl* render_view = render_frame_->render_view(); render_frame_->GetWebFrame()->MoveCaretSelection( - render_view->ConvertWindowPointToViewport(point)); + render_frame_->render_view()->GetWidget()->ConvertWindowPointToViewport( + point)); } void FrameInputHandlerImpl::GetWidgetInputHandler( diff --git a/chromium/content/renderer/input/input_event_prediction.cc b/chromium/content/renderer/input/input_event_prediction.cc index 89636c9736d..5b0579d3606 100644 --- a/chromium/content/renderer/input/input_event_prediction.cc +++ b/chromium/content/renderer/input/input_event_prediction.cc @@ -5,8 +5,12 @@ #include "content/renderer/input/input_event_prediction.h" #include "base/feature_list.h" +#include "base/metrics/field_trial.h" +#include "base/metrics/field_trial_params.h" #include "content/public/common/content_features.h" #include "ui/events/blink/prediction/empty_predictor.h" +#include "ui/events/blink/prediction/kalman_predictor.h" +#include "ui/events/blink/prediction/least_squares_predictor.h" using blink::WebInputEvent; using blink::WebMouseEvent; @@ -18,14 +22,23 @@ namespace content { namespace { -std::unique_ptr<ui::InputPredictor> SetUpPredictor() { - return std::make_unique<ui::EmptyPredictor>(); -} +constexpr char kPredictor[] = "predictor"; +constexpr char kInputEventPredictorTypeLsq[] = "lsq"; +constexpr char kInputEventPredictorTypeKalman[] = "kalman"; } // namespace InputEventPrediction::InputEventPrediction() { - mouse_predictor_ = SetUpPredictor(); + std::string predictor_type = GetFieldTrialParamValueByFeature( + features::kResamplingInputEvents, kPredictor); + if (predictor_type == kInputEventPredictorTypeLsq) + selected_predictor_type_ = PredictorType::kLsq; + else if (predictor_type == kInputEventPredictorTypeKalman) + selected_predictor_type_ = PredictorType::kKalman; + else + selected_predictor_type_ = PredictorType::kEmpty; + + mouse_predictor_ = CreatePredictor(); } InputEventPrediction::~InputEventPrediction() {} @@ -54,6 +67,18 @@ void InputEventPrediction::HandleEvents( } } +std::unique_ptr<ui::InputPredictor> InputEventPrediction::CreatePredictor() + const { + switch (selected_predictor_type_) { + case PredictorType::kEmpty: + return std::make_unique<ui::EmptyPredictor>(); + case PredictorType::kLsq: + return std::make_unique<ui::LeastSquaresPredictor>(); + case PredictorType::kKalman: + return std::make_unique<ui::KalmanPredictor>(); + } +} + void InputEventPrediction::UpdatePrediction(const WebInputEvent& event) { if (WebInputEvent::IsTouchEventType(event.GetType())) { DCHECK(event.GetType() == WebInputEvent::kTouchMove); @@ -110,8 +135,7 @@ void InputEventPrediction::ResetPredictor(const WebInputEvent& event) { void InputEventPrediction::UpdateSinglePointer( const WebPointerProperties& event, base::TimeTicks event_time) { - ui::InputPredictor::InputData data = {event.PositionInWidget().x, - event.PositionInWidget().y, event_time}; + ui::InputPredictor::InputData data = {event.PositionInWidget(), event_time}; if (event.pointer_type == WebPointerProperties::PointerType::kMouse) mouse_predictor_->Update(data); else { @@ -119,7 +143,10 @@ void InputEventPrediction::UpdateSinglePointer( if (predictor != pointer_id_predictor_map_.end()) { predictor->second->Update(data); } else { - pointer_id_predictor_map_.insert({event.id, SetUpPredictor()}); + // Workaround for GLIBC C++ < 7.3 that fails to insert with braces + // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82522 + auto pair = std::make_pair(event.id, CreatePredictor()); + pointer_id_predictor_map_.insert(std::move(pair)); pointer_id_predictor_map_[event.id]->Update(data); } } @@ -131,7 +158,7 @@ bool InputEventPrediction::ResampleSinglePointer(base::TimeTicks frame_time, if (event->pointer_type == WebPointerProperties::PointerType::kMouse) { if (mouse_predictor_->HasPrediction() && mouse_predictor_->GeneratePrediction(frame_time, &predict_result)) { - event->SetPositionInWidget(predict_result.pos_x, predict_result.pos_y); + event->SetPositionInWidget(predict_result.pos); return true; } } else { @@ -142,7 +169,7 @@ bool InputEventPrediction::ResampleSinglePointer(base::TimeTicks frame_time, if (predictor != pointer_id_predictor_map_.end() && predictor->second->HasPrediction() && predictor->second->GeneratePrediction(frame_time, &predict_result)) { - event->SetPositionInWidget(predict_result.pos_x, predict_result.pos_y); + event->SetPositionInWidget(predict_result.pos); return true; } } diff --git a/chromium/content/renderer/input/input_event_prediction.h b/chromium/content/renderer/input/input_event_prediction.h index 59a473e977d..3bcc9ae3a58 100644 --- a/chromium/content/renderer/input/input_event_prediction.h +++ b/chromium/content/renderer/input/input_event_prediction.h @@ -28,7 +28,14 @@ class CONTENT_EXPORT InputEventPrediction { base::TimeTicks frame_time, blink::WebInputEvent* event); + // Initialize predictor for different pointer. + std::unique_ptr<ui::InputPredictor> CreatePredictor() const; + private: + friend class InputEventPredictionTest; + + enum class PredictorType { kEmpty, kLsq, kKalman }; + // The following three function is for handling multiple TouchPoints in a // WebTouchEvent. They should be more neat when WebTouchEvent is elimated. // Cast events from WebInputEvent to WebPointerProperties. Call @@ -52,12 +59,14 @@ class CONTENT_EXPORT InputEventPrediction { // predictor, for other pointer type, remove it from mapping. void ResetSinglePredictor(const WebPointerProperties& event); - friend class InputEventPredictionTest; - std::unordered_map<ui::PointerId, std::unique_ptr<ui::InputPredictor>> pointer_id_predictor_map_; std::unique_ptr<ui::InputPredictor> mouse_predictor_; + // Store the field trial parameter used for choosing different types of + // predictor. + PredictorType selected_predictor_type_; + DISALLOW_COPY_AND_ASSIGN(InputEventPrediction); }; diff --git a/chromium/content/renderer/input/input_event_prediction_unittest.cc b/chromium/content/renderer/input/input_event_prediction_unittest.cc index a0d5a498031..04ef06741ce 100644 --- a/chromium/content/renderer/input/input_event_prediction_unittest.cc +++ b/chromium/content/renderer/input/input_event_prediction_unittest.cc @@ -69,8 +69,8 @@ TEST_F(InputEventPredictionTest, MouseEvent) { HandleEvents(mouse_move); EXPECT_EQ(GetPredictorMapSize(), 0); EXPECT_TRUE(GetPrediction(mouse_move, &last_point)); - EXPECT_EQ(last_point.pos_x, 10); - EXPECT_EQ(last_point.pos_y, 10); + EXPECT_EQ(last_point.pos.x(), 10); + EXPECT_EQ(last_point.pos.y(), 10); WebMouseEvent mouse_down = SyntheticWebMouseEventBuilder::Build( WebInputEvent::kMouseDown, 10, 10, 0); @@ -93,8 +93,8 @@ TEST_F(InputEventPredictionTest, SingleTouchPoint) { HandleEvents(touch_event); EXPECT_EQ(GetPredictorMapSize(), 1); EXPECT_TRUE(GetPrediction(touch_event.touches[0], &last_point)); - EXPECT_EQ(last_point.pos_x, 11); - EXPECT_EQ(last_point.pos_y, 12); + EXPECT_EQ(last_point.pos.x(), 11); + EXPECT_EQ(last_point.pos.y(), 12); touch_event.ReleasePoint(0); HandleEvents(touch_event); @@ -111,8 +111,8 @@ TEST_F(InputEventPredictionTest, MouseEventTypePen) { HandleEvents(pen_move); EXPECT_EQ(GetPredictorMapSize(), 1); EXPECT_TRUE(GetPrediction(pen_move, &last_point)); - EXPECT_EQ(last_point.pos_x, 10); - EXPECT_EQ(last_point.pos_y, 10); + EXPECT_EQ(last_point.pos.x(), 10); + EXPECT_EQ(last_point.pos.y(), 10); WebMouseEvent pen_leave = SyntheticWebMouseEventBuilder::Build( WebInputEvent::kMouseLeave, 10, 10, 0, @@ -145,12 +145,12 @@ TEST_F(InputEventPredictionTest, MultipleTouchPoint) { ui::InputPredictor::InputData last_point; EXPECT_TRUE(GetPrediction(touch_event.touches[0], &last_point)); - EXPECT_EQ(last_point.pos_x, 11); - EXPECT_EQ(last_point.pos_y, 12); + EXPECT_EQ(last_point.pos.x(), 11); + EXPECT_EQ(last_point.pos.y(), 12); EXPECT_TRUE(GetPrediction(touch_event.touches[1], &last_point)); - EXPECT_EQ(last_point.pos_x, 25); - EXPECT_EQ(last_point.pos_y, 25); + EXPECT_EQ(last_point.pos.x(), 25); + EXPECT_EQ(last_point.pos.y(), 25); touch_event.ReleasePoint(0); HandleEvents(touch_event); @@ -210,4 +210,4 @@ TEST_F(InputEventPredictionTest, TouchScrollStartedRemoveAllTouchPoints) { EXPECT_EQ(GetPredictorMapSize(), 0); } -} // namespace content
\ No newline at end of file +} // 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 7db4e91d2e5..3503cbbd5d2 100644 --- a/chromium/content/renderer/input/main_thread_event_queue.cc +++ b/chromium/content/renderer/input/main_thread_event_queue.cc @@ -209,7 +209,7 @@ MainThreadEventQueue::SharedState::~SharedState() {} MainThreadEventQueue::MainThreadEventQueue( MainThreadEventQueueClient* client, const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner, - blink::scheduler::WebMainThreadScheduler* main_thread_scheduler, + blink::scheduler::WebThreadScheduler* main_thread_scheduler, bool allow_raf_aligned_input) : client_(client), last_touch_start_forced_nonblocking_due_to_fling_(false), @@ -526,6 +526,8 @@ void MainThreadEventQueue::SetNeedsMainFrame() { } if (client_) client_->SetNeedsMainFrame(); + if (main_thread_scheduler_) + main_thread_scheduler_->OnMainFrameRequestedForInput(); return; } diff --git a/chromium/content/renderer/input/main_thread_event_queue.h b/chromium/content/renderer/input/main_thread_event_queue.h index cf767c67a3d..f1a690f58d5 100644 --- a/chromium/content/renderer/input/main_thread_event_queue.h +++ b/chromium/content/renderer/input/main_thread_event_queue.h @@ -16,7 +16,7 @@ #include "content/renderer/input/input_event_prediction.h" #include "content/renderer/input/main_thread_event_queue_task_list.h" #include "content/renderer/input/scoped_web_input_event_with_latency_info.h" -#include "third_party/blink/public/platform/scheduler/web_main_thread_scheduler.h" +#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h" #include "third_party/blink/public/platform/web_input_event.h" #include "ui/events/blink/did_overscroll_params.h" #include "ui/events/blink/web_input_event_traits.h" @@ -85,7 +85,7 @@ class CONTENT_EXPORT MainThreadEventQueue MainThreadEventQueue( MainThreadEventQueueClient* client, const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner, - blink::scheduler::WebMainThreadScheduler* main_thread_scheduler, + blink::scheduler::WebThreadScheduler* main_thread_scheduler, bool allow_raf_aligned_input); // Called once the compositor has handled |event| and indicated that it is @@ -162,7 +162,7 @@ class CONTENT_EXPORT MainThreadEventQueue SharedState shared_state_; scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; - blink::scheduler::WebMainThreadScheduler* main_thread_scheduler_; + blink::scheduler::WebThreadScheduler* main_thread_scheduler_; base::OneShotTimer raf_fallback_timer_; bool use_raf_fallback_timer_; diff --git a/chromium/content/renderer/input/main_thread_event_queue_task.h b/chromium/content/renderer/input/main_thread_event_queue_task.h index 7702e79d9a7..ce7c9a17b21 100644 --- a/chromium/content/renderer/input/main_thread_event_queue_task.h +++ b/chromium/content/renderer/input/main_thread_event_queue_task.h @@ -6,7 +6,7 @@ #define CONTENT_RENDERER_INPUT_MAIN_THREAD_EVENT_QUEUE_TASK_H_ #include "content/public/common/input_event_ack_state.h" -#include "third_party/blink/public/platform/scheduler/web_main_thread_scheduler.h" +#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h" #include "third_party/blink/public/platform/web_input_event.h" namespace content { diff --git a/chromium/content/renderer/input/render_widget_input_handler.cc b/chromium/content/renderer/input/render_widget_input_handler.cc index ca425a44022..e4636407871 100644 --- a/chromium/content/renderer/input/render_widget_input_handler.cc +++ b/chromium/content/renderer/input/render_widget_input_handler.cc @@ -17,15 +17,14 @@ #include "content/common/input/input_event_ack.h" #include "content/public/common/content_switches.h" #include "content/public/common/input_event_ack_state.h" -#include "content/public/common/use_zoom_for_dsf_policy.h" #include "content/public/renderer/render_frame.h" -#include "content/renderer/gpu/render_widget_compositor.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" #include "content/renderer/render_frame_proxy.h" #include "content/renderer/render_thread_impl.h" #include "content/renderer/render_widget.h" -#include "third_party/blink/public/platform/scheduler/web_main_thread_scheduler.h" +#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h" #include "third_party/blink/public/platform/web_float_point.h" #include "third_party/blink/public/platform/web_float_size.h" #include "third_party/blink/public/platform/web_gesture_event.h" @@ -194,7 +193,7 @@ RenderWidgetInputHandler::~RenderWidgetInputHandler() {} viz::FrameSinkId RenderWidgetInputHandler::GetFrameSinkIdAtPoint( const gfx::Point& point) { gfx::PointF point_in_pixel(point); - if (IsUseZoomForDSFEnabled()) { + if (widget_->compositor_deps()->IsUseZoomForDSFEnabled()) { point_in_pixel = gfx::ConvertPointToPixel( widget_->GetOriginalScreenInfo().device_scale_factor, point_in_pixel); } @@ -305,10 +304,10 @@ void RenderWidgetInputHandler::HandleInputEvent( ui::LatencyInfo swap_latency_info(latency_info); swap_latency_info.AddLatencyNumber( - ui::LatencyComponentType::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT, 0); - if (widget_->compositor()) { + ui::LatencyComponentType::INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT); + if (widget_->layer_tree_view()) { latency_info_swap_promise_monitor = - widget_->compositor()->CreateLatencyInfoSwapPromiseMonitor( + widget_->layer_tree_view()->CreateLatencyInfoSwapPromiseMonitor( &swap_latency_info); } diff --git a/chromium/content/renderer/input/widget_input_handler_impl.cc b/chromium/content/renderer/input/widget_input_handler_impl.cc index dd01e03a9f1..09384eed9c0 100644 --- a/chromium/content/renderer/input/widget_input_handler_impl.cc +++ b/chromium/content/renderer/input/widget_input_handler_impl.cc @@ -10,13 +10,13 @@ #include "base/logging.h" #include "content/common/input/ime_text_span_conversions.h" #include "content/common/input_messages.h" -#include "content/renderer/gpu/render_widget_compositor.h" +#include "content/renderer/gpu/layer_tree_view.h" #include "content/renderer/ime_event_guard.h" #include "content/renderer/input/widget_input_handler_manager.h" #include "content/renderer/render_thread_impl.h" #include "content/renderer/render_widget.h" #include "third_party/blink/public/platform/platform.h" -#include "third_party/blink/public/platform/scheduler/web_main_thread_scheduler.h" +#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_local_frame.h" diff --git a/chromium/content/renderer/input/widget_input_handler_manager.cc b/chromium/content/renderer/input/widget_input_handler_manager.cc index fa74edacbc2..d76df765d91 100644 --- a/chromium/content/renderer/input/widget_input_handler_manager.cc +++ b/chromium/content/renderer/input/widget_input_handler_manager.cc @@ -9,13 +9,13 @@ #include "base/bind.h" #include "base/logging.h" #include "content/common/input_messages.h" -#include "content/renderer/gpu/render_widget_compositor.h" +#include "content/renderer/gpu/layer_tree_view.h" #include "content/renderer/ime_event_guard.h" #include "content/renderer/input/widget_input_handler_impl.h" #include "content/renderer/render_thread_impl.h" #include "content/renderer/render_widget.h" #include "third_party/blink/public/platform/platform.h" -#include "third_party/blink/public/platform/scheduler/web_main_thread_scheduler.h" +#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_local_frame.h" @@ -23,7 +23,7 @@ #if defined(OS_ANDROID) #include "content/public/common/content_client.h" -#include "content/renderer/android/synchronous_compositor_proxy_mojo.h" +#include "content/renderer/android/synchronous_compositor_proxy.h" #include "content/renderer/android/synchronous_compositor_registry.h" #endif @@ -80,14 +80,14 @@ class SynchronousCompositorProxyRegistry void CreateProxy(ui::SynchronousInputHandlerProxy* handler) { DCHECK(compositor_task_runner_->BelongsToCurrentThread()); - proxy_ = std::make_unique<SynchronousCompositorProxyMojo>(handler); + proxy_ = std::make_unique<SynchronousCompositorProxy>(handler); proxy_->Init(); if (sink_) proxy_->SetLayerTreeFrameSink(sink_); } - SynchronousCompositorProxyMojo* proxy() { return proxy_.get(); } + SynchronousCompositorProxy* proxy() { return proxy_.get(); } void RegisterLayerTreeFrameSink( int routing_id, @@ -114,7 +114,7 @@ class SynchronousCompositorProxyRegistry private: scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_; - std::unique_ptr<SynchronousCompositorProxyMojo> proxy_; + std::unique_ptr<SynchronousCompositorProxy> proxy_; SynchronousLayerTreeFrameSink* sink_ = nullptr; }; @@ -123,7 +123,7 @@ class SynchronousCompositorProxyRegistry scoped_refptr<WidgetInputHandlerManager> WidgetInputHandlerManager::Create( base::WeakPtr<RenderWidget> render_widget, scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner, - blink::scheduler::WebMainThreadScheduler* main_thread_scheduler) { + blink::scheduler::WebThreadScheduler* main_thread_scheduler) { scoped_refptr<WidgetInputHandlerManager> manager = new WidgetInputHandlerManager(std::move(render_widget), std::move(compositor_task_runner), @@ -135,7 +135,7 @@ scoped_refptr<WidgetInputHandlerManager> WidgetInputHandlerManager::Create( WidgetInputHandlerManager::WidgetInputHandlerManager( base::WeakPtr<RenderWidget> render_widget, scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner, - blink::scheduler::WebMainThreadScheduler* main_thread_scheduler) + blink::scheduler::WebThreadScheduler* main_thread_scheduler) : render_widget_(render_widget), main_thread_scheduler_(main_thread_scheduler), input_event_queue_(render_widget->GetInputEventQueue()), @@ -161,7 +161,7 @@ void WidgetInputHandlerManager::Init() { FROM_HERE, base::BindOnce( &WidgetInputHandlerManager::InitOnCompositorThread, this, - render_widget_->compositor()->GetInputHandler(), + render_widget_->layer_tree_view()->GetInputHandler(), render_widget_->compositor_deps()->IsScrollAnimatorEnabled(), sync_compositing)); } @@ -225,15 +225,6 @@ void WidgetInputHandlerManager::DispatchNonBlockingEventToMainThread( INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING, HandledEventCallback()); } -std::unique_ptr<blink::WebGestureCurve> -WidgetInputHandlerManager::CreateFlingAnimationCurve( - blink::WebGestureDevice device_source, - const blink::WebFloatPoint& velocity, - const blink::WebSize& cumulative_scroll) { - return blink::Platform::Current()->CreateFlingAnimationCurve( - device_source, velocity, cumulative_scroll); -} - void WidgetInputHandlerManager::DidOverscroll( const gfx::Vector2dF& accumulated_overscroll, const gfx::Vector2dF& latest_overscroll_delta, @@ -252,13 +243,6 @@ void WidgetInputHandlerManager::DidOverscroll( host->DidOverscroll(params); } -void WidgetInputHandlerManager::DidStopFlinging() { - mojom::WidgetInputHandlerHost* host = GetWidgetInputHandlerHost(); - if (!host) - return; - host->DidStopFlinging(); -} - void WidgetInputHandlerManager::DidAnimateForInput() { main_thread_scheduler_->DidAnimateForInputOnCompositorThread(); } @@ -389,10 +373,8 @@ void WidgetInputHandlerManager::InitOnCompositorThread( const base::WeakPtr<cc::InputHandler>& input_handler, bool smooth_scroll_enabled, bool sync_compositing) { - input_handler_proxy_ = std::make_unique<ui::InputHandlerProxy>( - input_handler.get(), this, - base::FeatureList::IsEnabled(features::kTouchpadAndWheelScrollLatching), - base::FeatureList::IsEnabled(features::kAsyncWheelEvents)); + input_handler_proxy_ = + std::make_unique<ui::InputHandlerProxy>(input_handler.get(), this); input_handler_proxy_->set_smooth_scroll_enabled(smooth_scroll_enabled); #if defined(OS_ANDROID) @@ -457,12 +439,12 @@ void WidgetInputHandlerManager::DidHandleInputEventAndOverscroll( InputEventAckState ack_state = InputEventDispositionToAck(event_disposition); if (ack_state == INPUT_EVENT_ACK_STATE_CONSUMED) { main_thread_scheduler_->DidHandleInputEventOnCompositorThread( - *input_event, blink::scheduler::WebMainThreadScheduler:: - InputEventState::EVENT_CONSUMED_BY_COMPOSITOR); + *input_event, blink::scheduler::WebThreadScheduler::InputEventState:: + EVENT_CONSUMED_BY_COMPOSITOR); } else if (MainThreadEventQueue::IsForwardedAndSchedulerKnown(ack_state)) { main_thread_scheduler_->DidHandleInputEventOnCompositorThread( - *input_event, blink::scheduler::WebMainThreadScheduler:: - InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD); + *input_event, blink::scheduler::WebThreadScheduler::InputEventState:: + EVENT_FORWARDED_TO_MAIN_THREAD); } if (ack_state == INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING || diff --git a/chromium/content/renderer/input/widget_input_handler_manager.h b/chromium/content/renderer/input/widget_input_handler_manager.h index abda6108d65..06821186013 100644 --- a/chromium/content/renderer/input/widget_input_handler_manager.h +++ b/chromium/content/renderer/input/widget_input_handler_manager.h @@ -17,7 +17,7 @@ namespace blink { namespace scheduler { -class WebMainThreadScheduler; +class WebThreadScheduler; }; // namespace scheduler }; // namespace blink @@ -36,7 +36,7 @@ class CONTENT_EXPORT WidgetInputHandlerManager static scoped_refptr<WidgetInputHandlerManager> Create( base::WeakPtr<RenderWidget> render_widget, scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner, - blink::scheduler::WebMainThreadScheduler* main_thread_scheduler); + blink::scheduler::WebThreadScheduler* main_thread_scheduler); void AddAssociatedInterface( mojom::WidgetInputHandlerAssociatedRequest interface_request, mojom::WidgetInputHandlerHostPtr host); @@ -49,10 +49,6 @@ class CONTENT_EXPORT WidgetInputHandlerManager void DispatchNonBlockingEventToMainThread( ui::WebScopedInputEvent event, const ui::LatencyInfo& latency_info) override; - std::unique_ptr<blink::WebGestureCurve> CreateFlingAnimationCurve( - blink::WebGestureDevice device_source, - const blink::WebFloatPoint& velocity, - const blink::WebSize& cumulative_scroll) override; void DidOverscroll( const gfx::Vector2dF& accumulated_overscroll, @@ -60,7 +56,6 @@ class CONTENT_EXPORT WidgetInputHandlerManager const gfx::Vector2dF& current_fling_velocity, const gfx::PointF& causal_event_viewport_point, const cc::OverscrollBehavior& overscroll_behavior) override; - void DidStopFlinging() override; void DidAnimateForInput() override; void DidStartScrollingViewport() override; void GenerateScrollBeginAndSendToMainThread( @@ -98,7 +93,7 @@ class CONTENT_EXPORT WidgetInputHandlerManager WidgetInputHandlerManager( base::WeakPtr<RenderWidget> render_widget, scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner, - blink::scheduler::WebMainThreadScheduler* main_thread_scheduler); + blink::scheduler::WebThreadScheduler* main_thread_scheduler); void Init(); void InitOnCompositorThread( const base::WeakPtr<cc::InputHandler>& input_handler, @@ -129,7 +124,7 @@ class CONTENT_EXPORT WidgetInputHandlerManager // Only valid to be called on the main thread. base::WeakPtr<RenderWidget> render_widget_; - blink::scheduler::WebMainThreadScheduler* main_thread_scheduler_; + blink::scheduler::WebThreadScheduler* main_thread_scheduler_; // InputHandlerProxy is only interacted with on the compositor // thread. 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 32ddb9deabd..9dd95c396a7 100644 --- a/chromium/content/renderer/loader/child_url_loader_factory_bundle.cc +++ b/chromium/content/renderer/loader/child_url_loader_factory_bundle.cc @@ -24,12 +24,14 @@ class URLLoaderRelay : public network::mojom::URLLoaderClient, client_sink_(std::move(client_sink)) {} // network::mojom::URLLoader implementation: - void FollowRedirect(const base::Optional<net::HttpRequestHeaders>& + void FollowRedirect(const base::Optional<std::vector<std::string>>& + to_be_removed_request_headers, + const base::Optional<net::HttpRequestHeaders>& modified_request_headers) override { DCHECK(!modified_request_headers.has_value()) << "Redirect with modified headers was not supported yet. " "crbug.com/845683"; - loader_sink_->FollowRedirect(base::nullopt); + loader_sink_->FollowRedirect(base::nullopt, base::nullopt); } void ProceedWithResponse() override { loader_sink_->ProceedWithResponse(); } @@ -48,10 +50,8 @@ class URLLoaderRelay : public network::mojom::URLLoaderClient, } // network::mojom::URLLoaderClient implementation: - void OnReceiveResponse( - const network::ResourceResponseHead& head, - network::mojom::DownloadedTempFilePtr downloaded_file) override { - client_sink_->OnReceiveResponse(head, std::move(downloaded_file)); + void OnReceiveResponse(const network::ResourceResponseHead& head) override { + client_sink_->OnReceiveResponse(head); } void OnReceiveRedirect(const net::RedirectInfo& redirect_info, @@ -59,10 +59,6 @@ class URLLoaderRelay : public network::mojom::URLLoaderClient, client_sink_->OnReceiveRedirect(redirect_info, head); } - void OnDataDownloaded(int64_t data_length, int64_t encoded_length) override { - client_sink_->OnDataDownloaded(data_length, encoded_length); - } - void OnUploadProgress(int64_t current_position, int64_t total_size, OnUploadProgressCallback callback) override { @@ -133,18 +129,14 @@ ChildURLLoaderFactoryBundle::ChildURLLoaderFactoryBundle( } ChildURLLoaderFactoryBundle::ChildURLLoaderFactoryBundle( - PossiblyAssociatedFactoryGetterCallback direct_network_factory_getter, - FactoryGetterCallback default_blob_factory_getter) - : direct_network_factory_getter_(std::move(direct_network_factory_getter)), - default_blob_factory_getter_(std::move(default_blob_factory_getter)) {} + PossiblyAssociatedFactoryGetterCallback direct_network_factory_getter) + : direct_network_factory_getter_(std::move(direct_network_factory_getter)) { +} ChildURLLoaderFactoryBundle::~ChildURLLoaderFactoryBundle() = default; network::mojom::URLLoaderFactory* ChildURLLoaderFactoryBundle::GetFactoryForURL( const GURL& url) { - if (url.SchemeIsBlob()) - InitDefaultBlobFactoryIfNecessary(); - auto it = factories_.find(url.scheme()); if (it != factories_.end()) return it->second.get(); @@ -171,7 +163,7 @@ void ChildURLLoaderFactoryBundle::CreateLoaderAndStart( std::move(override_iter->second); subresource_overrides_.erase(override_iter); - client->OnReceiveResponse(transferrable_loader->head, nullptr); + client->OnReceiveResponse(transferrable_loader->head); mojo::MakeStrongBinding( std::make_unique<URLLoaderRelay>( network::mojom::URLLoaderPtr( @@ -221,20 +213,6 @@ bool ChildURLLoaderFactoryBundle::IsHostChildURLLoaderFactoryBundle() const { return false; } -void ChildURLLoaderFactoryBundle::InitDefaultBlobFactoryIfNecessary() { - if (default_blob_factory_getter_.is_null()) - return; - - if (factories_.find(url::kBlobScheme) == factories_.end()) { - network::mojom::URLLoaderFactoryPtr blob_factory = - std::move(default_blob_factory_getter_).Run(); - if (blob_factory) - factories_.emplace(url::kBlobScheme, std::move(blob_factory)); - } else { - default_blob_factory_getter_.Reset(); - } -} - void ChildURLLoaderFactoryBundle::InitDirectNetworkFactoryIfNecessary() { if (direct_network_factory_getter_.is_null()) return; @@ -248,7 +226,6 @@ void ChildURLLoaderFactoryBundle::InitDirectNetworkFactoryIfNecessary() { std::unique_ptr<network::SharedURLLoaderFactoryInfo> ChildURLLoaderFactoryBundle::CloneInternal(bool include_default) { - InitDefaultBlobFactoryIfNecessary(); InitDirectNetworkFactoryIfNecessary(); network::mojom::URLLoaderFactoryPtrInfo default_factory_info; @@ -278,7 +255,6 @@ ChildURLLoaderFactoryBundle::CloneInternal(bool include_default) { std::unique_ptr<ChildURLLoaderFactoryBundleInfo> ChildURLLoaderFactoryBundle::PassInterface() { - InitDefaultBlobFactoryIfNecessary(); InitDirectNetworkFactoryIfNecessary(); network::mojom::URLLoaderFactoryPtrInfo default_factory_info; 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 cb613cbc247..bcf816a026c 100644 --- a/chromium/content/renderer/loader/child_url_loader_factory_bundle.h +++ b/chromium/content/renderer/loader/child_url_loader_factory_bundle.h @@ -47,8 +47,8 @@ class CONTENT_EXPORT ChildURLLoaderFactoryBundleInfo // This class extends URLLoaderFactoryBundle to support a direct network loader // factory, which bypasses custom overrides such as appcache or service worker. -// Besides, it also supports using callbacks to lazily initialize the blob and -// the direct network loader factories. +// Besides, it also supports using callbacks to lazily initialize the direct +// network loader factory. class CONTENT_EXPORT ChildURLLoaderFactoryBundle : public URLLoaderFactoryBundle { public: @@ -66,8 +66,7 @@ class CONTENT_EXPORT ChildURLLoaderFactoryBundle std::unique_ptr<ChildURLLoaderFactoryBundleInfo> info); ChildURLLoaderFactoryBundle( - PossiblyAssociatedFactoryGetterCallback direct_network_factory_getter, - FactoryGetterCallback default_blob_factory_getter); + PossiblyAssociatedFactoryGetterCallback direct_network_factory_getter); // URLLoaderFactoryBundle overrides. network::mojom::URLLoaderFactory* GetFactoryForURL(const GURL& url) override; @@ -100,7 +99,6 @@ class CONTENT_EXPORT ChildURLLoaderFactoryBundle ~ChildURLLoaderFactoryBundle() override; private: - void InitDefaultBlobFactoryIfNecessary(); void InitDirectNetworkFactoryIfNecessary(); std::unique_ptr<network::SharedURLLoaderFactoryInfo> CloneInternal( bool include_default); @@ -109,8 +107,6 @@ class CONTENT_EXPORT ChildURLLoaderFactoryBundle PossiblyAssociatedURLLoaderFactoryPtr direct_network_factory_; std::map<GURL, mojom::TransferrableURLLoaderPtr> subresource_overrides_; - - FactoryGetterCallback default_blob_factory_getter_; }; } // namespace content diff --git a/chromium/content/renderer/loader/resource_dispatcher.cc b/chromium/content/renderer/loader/resource_dispatcher.cc index f3f906a3c5a..3d5bd290d7b 100644 --- a/chromium/content/renderer/loader/resource_dispatcher.cc +++ b/chromium/content/renderer/loader/resource_dispatcher.cc @@ -19,9 +19,11 @@ #include "base/strings/string_util.h" #include "base/synchronization/waitable_event.h" #include "base/task_scheduler/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/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" @@ -38,7 +40,6 @@ #include "net/base/load_flags.h" #include "net/base/net_errors.h" #include "net/base/request_priority.h" -#include "net/cert/cert_status_flags.h" #include "net/http/http_response_headers.h" #include "services/network/public/cpp/features.h" #include "services/network/public/cpp/resource_request.h" @@ -95,10 +96,36 @@ void NotifySubresourceStarted( render_frame->GetFrameHost()->SubresourceResponseStarted(url, cert_status); } +void NotifyResourceLoadStarted( + scoped_refptr<base::SingleThreadTaskRunner> thread_task_runner, + int render_frame_id, + int request_id, + const network::ResourceResponseHead& response_head, + content::ResourceType resource_type) { + if (!thread_task_runner) + return; + + if (!thread_task_runner->BelongsToCurrentThread()) { + thread_task_runner->PostTask( + FROM_HERE, base::BindOnce(NotifyResourceLoadStarted, thread_task_runner, + render_frame_id, request_id, response_head, + resource_type)); + return; + } + + RenderFrameImpl* render_frame = + RenderFrameImpl::FromRoutingID(render_frame_id); + if (!render_frame) + return; + + render_frame->DidStartResponse(request_id, response_head, resource_type); +} + void NotifyResourceLoadComplete( scoped_refptr<base::SingleThreadTaskRunner> thread_task_runner, int render_frame_id, - mojom::ResourceLoadInfoPtr resource_load_info) { + mojom::ResourceLoadInfoPtr resource_load_info, + const network::URLLoaderCompletionStatus& status) { if (!thread_task_runner) return; @@ -106,7 +133,7 @@ void NotifyResourceLoadComplete( thread_task_runner->PostTask( FROM_HERE, base::BindOnce(NotifyResourceLoadComplete, thread_task_runner, - render_frame_id, std::move(resource_load_info))); + render_frame_id, std::move(resource_load_info), status)); return; } @@ -115,10 +142,57 @@ void NotifyResourceLoadComplete( if (!render_frame) return; + render_frame->DidCompleteResponse(resource_load_info->request_id, status); render_frame->GetFrameHost()->ResourceLoadComplete( std::move(resource_load_info)); } +void NotifyResourceLoadCancel( + scoped_refptr<base::SingleThreadTaskRunner> thread_task_runner, + int render_frame_id, + int request_id) { + if (!thread_task_runner) + return; + + if (!thread_task_runner->BelongsToCurrentThread()) { + thread_task_runner->PostTask( + FROM_HERE, base::BindOnce(NotifyResourceLoadCancel, thread_task_runner, + render_frame_id, request_id)); + return; + } + + RenderFrameImpl* render_frame = + RenderFrameImpl::FromRoutingID(render_frame_id); + if (!render_frame) + return; + + render_frame->DidCancelResponse(request_id); +} + +void NotifyResourceTransferSizeUpdate( + scoped_refptr<base::SingleThreadTaskRunner> thread_task_runner, + int render_frame_id, + int request_id, + int transfer_size_diff) { + if (!thread_task_runner) + return; + + if (!thread_task_runner->BelongsToCurrentThread()) { + thread_task_runner->PostTask( + FROM_HERE, + base::BindOnce(NotifyResourceTransferSizeUpdate, thread_task_runner, + render_frame_id, request_id, transfer_size_diff)); + return; + } + + RenderFrameImpl* render_frame = + RenderFrameImpl::FromRoutingID(render_frame_id); + if (!render_frame) + return; + + render_frame->DidReceiveTransferSizeUpdate(request_id, transfer_size_diff); +} + // Returns true if the headers indicate that this resource should always be // revalidated or not cached. bool AlwaysAccessNetwork( @@ -231,6 +305,15 @@ void ResourceDispatcher::OnReceivedResponse( } request_info->peer->OnReceivedResponse(renderer_response_info); + + // Make a deep copy of ResourceResponseHead before passing it cross-thread. + auto resource_response = base::MakeRefCounted<network::ResourceResponse>(); + resource_response->head = response_head; + auto deep_copied_response = resource_response->DeepCopy(); + NotifyResourceLoadStarted(RenderThreadImpl::DeprecatedGetMainTaskRunner(), + request_info->render_frame_id, request_id, + deep_copied_response->head, + request_info->resource_type); } void ResourceDispatcher::OnReceivedCachedMetadata( @@ -256,16 +339,6 @@ void ResourceDispatcher::OnStartLoadingResponseBody( request_info->peer->OnStartLoadingResponseBody(std::move(body)); } -void ResourceDispatcher::OnDownloadedData(int request_id, - int data_len, - int encoded_data_length) { - PendingRequestInfo* request_info = GetPendingRequestInfo(request_id); - if (!request_info) - return; - - request_info->peer->OnDownloadedData(data_len, encoded_data_length); -} - void ResourceDispatcher::OnReceivedRedirect( int request_id, const net::RedirectInfo& redirect_info, @@ -317,7 +390,7 @@ 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(); + request_info->url_loader->FollowRedirect(base::nullopt); } } @@ -331,6 +404,7 @@ void ResourceDispatcher::OnRequestComplete( return; request_info->buffer.reset(); request_info->buffer_size = 0; + request_info->net_error = status.error_code; auto resource_load_info = mojom::ResourceLoadInfo::New(); resource_load_info->url = request_info->response_url; @@ -356,7 +430,7 @@ void ResourceDispatcher::OnRequestComplete( NotifyResourceLoadComplete(RenderThreadImpl::DeprecatedGetMainTaskRunner(), request_info->render_frame_id, - std::move(resource_load_info)); + std::move(resource_load_info), status); RequestPeer* peer = request_info->peer.get(); @@ -399,17 +473,6 @@ void ResourceDispatcher::OnRequestComplete( peer->OnCompletedRequest(renderer_status); } -network::mojom::DownloadedTempFilePtr -ResourceDispatcher::TakeDownloadedTempFile(int request_id) { - PendingRequestMap::iterator it = pending_requests_.find(request_id); - if (it == pending_requests_.end()) - return nullptr; - PendingRequestInfo* request_info = it->second.get(); - if (!request_info->url_loader_client) - return nullptr; - return request_info->url_loader_client->TakeDownloadedTempFile(); -} - bool ResourceDispatcher::RemovePendingRequest( int request_id, scoped_refptr<base::SingleThreadTaskRunner> task_runner) { @@ -417,6 +480,15 @@ bool ResourceDispatcher::RemovePendingRequest( if (it == pending_requests_.end()) return false; + if (it->second->net_error == net::ERR_IO_PENDING) { + it->second->net_error = net::ERR_ABORTED; + NotifyResourceLoadCancel(RenderThreadImpl::DeprecatedGetMainTaskRunner(), + it->second->render_frame_id, request_id); + } + + RecordLoadHistograms(it->second->response_url, it->second->resource_type, + it->second->net_error); + // Cancel loading. it->second->url_loader = nullptr; // Clear URLLoaderClient to stop receiving further Mojo IPC from the browser @@ -485,6 +557,10 @@ void ResourceDispatcher::OnTransferSizeUpdated(int request_id, // TODO(yhirano): Consider using int64_t in // RequestPeer::OnTransferSizeUpdated. request_info->peer->OnTransferSizeUpdated(transfer_size_diff); + + NotifyResourceTransferSizeUpdate( + RenderThreadImpl::DeprecatedGetMainTaskRunner(), + request_info->render_frame_id, request_id, transfer_size_diff); } ResourceDispatcher::PendingRequestInfo::PendingRequestInfo( @@ -494,7 +570,6 @@ ResourceDispatcher::PendingRequestInfo::PendingRequestInfo( const GURL& request_url, const std::string& method, const GURL& referrer, - bool download_to_file, std::unique_ptr<NavigationResponseOverrideParameters> navigation_response_override_params) : peer(std::move(peer)), @@ -504,7 +579,6 @@ ResourceDispatcher::PendingRequestInfo::PendingRequestInfo( response_url(request_url), response_method(method), response_referrer(referrer), - download_to_file(download_to_file), local_request_start(base::TimeTicks::Now()), buffer_size(0), navigation_response_override( @@ -520,7 +594,7 @@ void ResourceDispatcher::StartSync( SyncLoadResponse* response, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, std::vector<std::unique_ptr<URLLoaderThrottle>> throttles, - double timeout, + base::TimeDelta timeout, blink::mojom::BlobRegistryPtrInfo download_to_blob_registry, std::unique_ptr<RequestPeer> peer) { CheckSchemeForReferrerPolicy(*request); @@ -599,8 +673,7 @@ int ResourceDispatcher::StartAsync( pending_requests_[request_id] = std::make_unique<PendingRequestInfo>( std::move(peer), static_cast<ResourceType>(request->resource_type), request->render_frame_id, request->url, request->method, - request->referrer, request->download_to_file, - std::move(response_override_params)); + request->referrer, std::move(response_override_params)); if (override_url_loader) { pending_requests_[request_id]->url_loader_client = @@ -709,8 +782,7 @@ void ResourceDispatcher::ContinueForNavigation(int request_id) { return; } - client_ptr->OnReceiveResponse(response_override->response, - network::mojom::DownloadedTempFilePtr()); + client_ptr->OnReceiveResponse(response_override->response); // Abort if the request is cancelled. if (!GetPendingRequestInfo(request_id)) diff --git a/chromium/content/renderer/loader/resource_dispatcher.h b/chromium/content/renderer/loader/resource_dispatcher.h index 609aaef3f2a..3040fbd1189 100644 --- a/chromium/content/renderer/loader/resource_dispatcher.h +++ b/chromium/content/renderer/loader/resource_dispatcher.h @@ -28,6 +28,7 @@ #include "content/public/common/url_loader_throttle.h" #include "mojo/public/cpp/system/data_pipe.h" #include "net/base/host_port_pair.h" +#include "net/base/net_errors.h" #include "net/base/request_priority.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "services/network/public/cpp/shared_url_loader_factory.h" @@ -89,7 +90,8 @@ class CONTENT_EXPORT ResourceDispatcher { // // |routing_id| is used to associated the bridge with a frame's network // context. - // |timeout| (in seconds) is used to abort the sync request on timeouts. + // |timeout| is used to abort the sync request on timeouts. TimeDelta::Max() + // is interpreted as no-timeout. // If |download_to_blob_registry| is not null, it is used to redirect the // download to a blob, using StartAsync's |pass_response_pipe_to_peer| flag. virtual void StartSync( @@ -99,7 +101,7 @@ class CONTENT_EXPORT ResourceDispatcher { SyncLoadResponse* response, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, std::vector<std::unique_ptr<URLLoaderThrottle>> throttles, - double timeout, + base::TimeDelta timeout, blink::mojom::BlobRegistryPtrInfo download_to_blob_registry, std::unique_ptr<RequestPeer> peer); @@ -131,8 +133,6 @@ class CONTENT_EXPORT ResourceDispatcher { response_override_params, base::OnceClosure* continue_navigation_function); - network::mojom::DownloadedTempFilePtr TakeDownloadedTempFile(int request_id); - // Removes a request from the |pending_requests_| list, returning true if the // request was found and removed. bool RemovePendingRequest( @@ -185,7 +185,6 @@ class CONTENT_EXPORT ResourceDispatcher { const GURL& request_url, const std::string& method, const GURL& referrer, - bool download_to_file, std::unique_ptr<NavigationResponseOverrideParameters> response_override_params); @@ -202,7 +201,6 @@ class CONTENT_EXPORT ResourceDispatcher { GURL response_url; std::string response_method; GURL response_referrer; - bool download_to_file; bool has_pending_redirect = false; base::TimeTicks local_request_start; base::TimeTicks local_response_start; @@ -217,6 +215,10 @@ class CONTENT_EXPORT ResourceDispatcher { navigation_response_override; bool should_follow_redirect = true; bool always_access_network = 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. + int net_error = net::ERR_IO_PENDING; std::vector<content::mojom::RedirectInfoPtr> redirect_info_chain; @@ -245,7 +247,6 @@ class CONTENT_EXPORT ResourceDispatcher { scoped_refptr<base::SingleThreadTaskRunner> task_runner); void OnStartLoadingResponseBody(int request_id, mojo::ScopedDataPipeConsumerHandle body); - void OnDownloadedData(int request_id, int data_len, int encoded_data_length); void OnRequestComplete(int request_id, const network::URLLoaderCompletionStatus& status); diff --git a/chromium/content/renderer/loader/resource_dispatcher_unittest.cc b/chromium/content/renderer/loader/resource_dispatcher_unittest.cc index 9d89c8b0198..186292fb0ba 100644 --- a/chromium/content/renderer/loader/resource_dispatcher_unittest.cc +++ b/chromium/content/renderer/loader/resource_dispatcher_unittest.cc @@ -85,7 +85,7 @@ class ResourceDispatcherTest : public testing::Test, head.headers = new net::HttpResponseHeaders(raw_headers); head.mime_type = kTestPageMimeType; head.charset = kTestPageCharset; - client->OnReceiveResponse(head, {}); + client->OnReceiveResponse(head); } std::unique_ptr<network::ResourceRequest> CreateResourceRequest() { @@ -184,8 +184,6 @@ class TestResourceDispatcherDelegate : public ResourceDispatcherDelegate { void OnStartLoadingResponseBody( mojo::ScopedDataPipeConsumerHandle body) override {} - void OnDownloadedData(int len, int encoded_data_length) override {} - void OnReceivedData(std::unique_ptr<ReceivedData> data) override { data_.append(data->payload(), data->length()); } @@ -325,7 +323,7 @@ class TimeConversionTest : public ResourceDispatcherTest { ASSERT_EQ(1u, loader_and_clients_.size()); auto client = std::move(loader_and_clients_[0].second); loader_and_clients_.clear(); - client->OnReceiveResponse(response_head, {}); + client->OnReceiveResponse(response_head); } const network::ResourceResponseInfo& response_info() const { @@ -396,7 +394,7 @@ class CompletionTimeConversionTest : public ResourceDispatcherTest { // copied. response_head.load_timing.request_start_time = base::Time() + base::TimeDelta::FromSeconds(99); - client->OnReceiveResponse(response_head, {}); + client->OnReceiveResponse(response_head); network::URLLoaderCompletionStatus status; status.completion_time = completion_time; diff --git a/chromium/content/renderer/loader/sync_load_context.cc b/chromium/content/renderer/loader/sync_load_context.cc index 17da79d30b5..b9362684d8e 100644 --- a/chromium/content/renderer/loader/sync_load_context.cc +++ b/chromium/content/renderer/loader/sync_load_context.cc @@ -7,7 +7,9 @@ #include <string> #include "base/logging.h" +#include "base/optional.h" #include "base/synchronization/waitable_event.h" +#include "base/time/time.h" #include "content/public/common/url_loader_throttle.h" #include "content/renderer/loader/navigation_response_override_parameters.h" #include "content/renderer/loader/sync_load_response.h" @@ -24,32 +26,42 @@ class SyncLoadContext::SignalHelper final { SignalHelper(SyncLoadContext* context, base::WaitableEvent* redirect_or_response_event, base::WaitableEvent* abort_event, - double timeout) + base::TimeDelta timeout) : context_(context), redirect_or_response_event_(redirect_or_response_event), abort_event_(abort_event) { - Start(base::TimeDelta::FromSecondsD(timeout)); + // base::TimeDelta::Max() means no timeout. + if (timeout != base::TimeDelta::Max()) { + // Instantiate a base::OneShotTimer instance. + timeout_timer_.emplace(); + } + Start(timeout); } void SignalRedirectOrResponseComplete() { abort_watcher_.StopWatching(); - timeout_timer_.AbandonAndStop(); + if (timeout_timer_) + timeout_timer_->AbandonAndStop(); redirect_or_response_event_->Signal(); } bool RestartAfterRedirect() { if (abort_event_ && abort_event_->IsSignaled()) return false; - base::TimeDelta timeout_remainder = - timeout_timer_.desired_run_time() - base::TimeTicks::Now(); - if (timeout_remainder <= base::TimeDelta()) - return false; + + base::TimeDelta timeout_remainder = base::TimeDelta::Max(); + if (timeout_timer_) { + timeout_remainder = + timeout_timer_->desired_run_time() - base::TimeTicks::Now(); + if (timeout_remainder <= base::TimeDelta()) + return false; + } Start(timeout_remainder); return true; } private: - void Start(const base::TimeDelta& timeout) { + void Start(base::TimeDelta timeout) { DCHECK(!redirect_or_response_event_->IsSignaled()); if (abort_event_) { abort_watcher_.StartWatching( @@ -57,9 +69,10 @@ class SyncLoadContext::SignalHelper final { base::BindOnce(&SyncLoadContext::OnAbort, base::Unretained(context_)), context_->task_runner_); } - if (timeout > base::TimeDelta()) { - timeout_timer_.Start(FROM_HERE, timeout, context_, - &SyncLoadContext::OnTimeout); + if (timeout_timer_) { + DCHECK_NE(base::TimeDelta::Max(), timeout); + timeout_timer_->Start(FROM_HERE, timeout, context_, + &SyncLoadContext::OnTimeout); } } @@ -67,7 +80,7 @@ class SyncLoadContext::SignalHelper final { base::WaitableEvent* redirect_or_response_event_; base::WaitableEvent* abort_event_; base::WaitableEventWatcher abort_watcher_; - base::OneShotTimer timeout_timer_; + base::Optional<base::OneShotTimer> timeout_timer_; }; // static @@ -82,7 +95,7 @@ void SyncLoadContext::StartAsyncWithWaitableEvent( SyncLoadResponse* response, base::WaitableEvent* redirect_or_response_event, base::WaitableEvent* abort_event, - double timeout, + base::TimeDelta timeout, blink::mojom::BlobRegistryPtrInfo download_to_blob_registry) { bool download_to_blob = download_to_blob_registry.is_valid(); auto* context = new SyncLoadContext( @@ -104,7 +117,7 @@ SyncLoadContext::SyncLoadContext( SyncLoadResponse* response, base::WaitableEvent* redirect_or_response_event, base::WaitableEvent* abort_event, - double timeout, + base::TimeDelta timeout, blink::mojom::BlobRegistryPtrInfo download_to_blob_registry, scoped_refptr<base::SingleThreadTaskRunner> task_runner) : response_(response), @@ -113,8 +126,7 @@ SyncLoadContext::SyncLoadContext( signals_(std::make_unique<SignalHelper>(this, redirect_or_response_event, abort_event, - timeout)), - fetch_request_mode_(request->fetch_request_mode) { + timeout)) { url_loader_factory_ = network::SharedURLLoaderFactory::Create(std::move(url_loader_factory)); @@ -134,23 +146,6 @@ bool SyncLoadContext::OnReceivedRedirect( const net::RedirectInfo& redirect_info, const network::ResourceResponseInfo& info) { DCHECK(!Completed()); - // Synchronous loads in blink aren't associated with a ResourceClient, and - // CORS checks are performed by ResourceClient subclasses, so there's - // currently no way to perform CORS checks for redirects. - // Err on the side of extreme caution and block any cross origin redirect - // that might have CORS implications. - if (fetch_request_mode_ != network::mojom::FetchRequestMode::kNoCORS && - redirect_info.new_url.GetOrigin() != response_->url.GetOrigin()) { - LOG(ERROR) << "Cross origin redirect denied"; - response_->error_code = net::ERR_ABORTED; - - CompleteRequest(false /* remove_pending_request */); - - // Returning false here will cause the request to be cancelled and this - // object deleted. - return false; - } - response_->url = redirect_info.new_url; response_->info = info; response_->redirect_info = redirect_info; @@ -200,11 +195,6 @@ void SyncLoadContext::OnStartLoadingResponseBody( base::Unretained(this))); } -void SyncLoadContext::OnDownloadedData(int len, int encoded_data_length) { - downloaded_file_length_ = - (downloaded_file_length_ ? *downloaded_file_length_ : 0) + len; -} - void SyncLoadContext::OnReceivedData(std::unique_ptr<ReceivedData> data) { DCHECK(!Completed()); response_->data.append(data->payload(), data->length()); @@ -217,17 +207,9 @@ void SyncLoadContext::OnCompletedRequest( DCHECK(!Completed()); response_->error_code = status.error_code; response_->extended_error_code = status.extended_error_code; - if (status.cors_error_status) - response_->cors_error = status.cors_error_status->cors_error; + response_->cors_error = status.cors_error_status; response_->info.encoded_data_length = status.encoded_data_length; response_->info.encoded_body_length = status.encoded_body_length; - response_->downloaded_file_length = downloaded_file_length_; - // Need to pass |downloaded_tmp_file| to the caller thread. Otherwise the blob - // creation in ResourceResponse::SetDownloadedFilePath() fails. - response_->downloaded_tmp_file = - resource_dispatcher_->TakeDownloadedTempFile(request_id_); - DCHECK_EQ(!response_->downloaded_file_length, - !response_->downloaded_tmp_file); if (blob_response_started_ && !blob_finished_) { request_completed_ = true; return; diff --git a/chromium/content/renderer/loader/sync_load_context.h b/chromium/content/renderer/loader/sync_load_context.h index 23a7e7e8094..576233f5054 100644 --- a/chromium/content/renderer/loader/sync_load_context.h +++ b/chromium/content/renderer/loader/sync_load_context.h @@ -50,7 +50,7 @@ class SyncLoadContext : public RequestPeer { SyncLoadResponse* response, base::WaitableEvent* completed_event, base::WaitableEvent* abort_event, - double timeout, + base::TimeDelta timeout, blink::mojom::BlobRegistryPtrInfo download_to_blob_registry); ~SyncLoadContext() override; @@ -65,7 +65,7 @@ class SyncLoadContext : public RequestPeer { SyncLoadResponse* response, base::WaitableEvent* completed_event, base::WaitableEvent* abort_event, - double timeout, + base::TimeDelta timeout, blink::mojom::BlobRegistryPtrInfo download_to_blob_registry, scoped_refptr<base::SingleThreadTaskRunner> task_runner); // RequestPeer implementation: @@ -75,7 +75,6 @@ class SyncLoadContext : public RequestPeer { void OnReceivedResponse(const network::ResourceResponseInfo& info) override; void OnStartLoadingResponseBody( mojo::ScopedDataPipeConsumerHandle body) override; - void OnDownloadedData(int len, int encoded_data_length) override; void OnReceivedData(std::unique_ptr<ReceivedData> data) override; void OnTransferSizeUpdated(int transfer_size_diff) override; void OnCompletedRequest( @@ -108,13 +107,9 @@ class SyncLoadContext : public RequestPeer { scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - base::Optional<int64_t> downloaded_file_length_; - class SignalHelper; std::unique_ptr<SignalHelper> signals_; - const network::mojom::FetchRequestMode fetch_request_mode_; - DISALLOW_COPY_AND_ASSIGN(SyncLoadContext); }; diff --git a/chromium/content/renderer/loader/sync_load_response.h b/chromium/content/renderer/loader/sync_load_response.h index ea252ca5f31..df5a86cf879 100644 --- a/chromium/content/renderer/loader/sync_load_response.h +++ b/chromium/content/renderer/loader/sync_load_response.h @@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_RENDERER_CHILD_SYNC_LOAD_RESPONSE_H_ -#define CONTENT_RENDERER_CHILD_SYNC_LOAD_RESPONSE_H_ +#ifndef CONTENT_RENDERER_LOADER_SYNC_LOAD_RESPONSE_H_ +#define CONTENT_RENDERER_LOADER_SYNC_LOAD_RESPONSE_H_ #include <string> #include "base/optional.h" #include "content/common/content_export.h" +#include "services/network/public/cpp/cors/cors_error_status.h" #include "services/network/public/cpp/resource_response_info.h" -#include "services/network/public/mojom/cors.mojom.h" #include "services/network/public/mojom/url_loader.mojom.h" #include "third_party/blink/public/mojom/blob/serialized_blob.mojom.h" #include "url/gurl.h" @@ -40,7 +40,7 @@ struct CONTENT_EXPORT SyncLoadResponse { int extended_error_code = 0; // Optional CORS error details. - base::Optional<network::mojom::CORSError> cors_error; + base::Optional<network::CORSErrorStatus> cors_error; // The final URL of the response. This may differ from the request URL in // the case of a server redirect. @@ -50,11 +50,9 @@ struct CONTENT_EXPORT SyncLoadResponse { std::string data; // Used for blob response type XMLHttpRequest. - base::Optional<int64_t> downloaded_file_length; - network::mojom::DownloadedTempFilePtr downloaded_tmp_file; blink::mojom::SerializedBlobPtr downloaded_blob; }; } // namespace content -#endif // CONTENT_RENDERER_CHILD_SYNC_LOAD_RESPONSE_H_ +#endif // CONTENT_RENDERER_LOADER_SYNC_LOAD_RESPONSE_H_ diff --git a/chromium/content/renderer/loader/test_request_peer.cc b/chromium/content/renderer/loader/test_request_peer.cc index 1d92c02c630..95f90b53f9b 100644 --- a/chromium/content/renderer/loader/test_request_peer.cc +++ b/chromium/content/renderer/loader/test_request_peer.cc @@ -55,14 +55,6 @@ void TestRequestPeer::OnStartLoadingResponseBody( EXPECT_FALSE(context_->complete); } -void TestRequestPeer::OnDownloadedData(int len, int encoded_data_length) { - EXPECT_TRUE(context_->received_response); - EXPECT_FALSE(context_->cancelled); - EXPECT_FALSE(context_->complete); - context_->total_downloaded_data_length += len; - context_->total_encoded_data_length += encoded_data_length; -} - void TestRequestPeer::OnReceivedData(std::unique_ptr<ReceivedData> data) { if (context_->cancelled) return; diff --git a/chromium/content/renderer/loader/test_request_peer.h b/chromium/content/renderer/loader/test_request_peer.h index 3c40627b410..f77658b574c 100644 --- a/chromium/content/renderer/loader/test_request_peer.h +++ b/chromium/content/renderer/loader/test_request_peer.h @@ -41,7 +41,6 @@ class TestRequestPeer : public RequestPeer { void OnReceivedResponse(const network::ResourceResponseInfo& info) override; void OnStartLoadingResponseBody( mojo::ScopedDataPipeConsumerHandle body) override; - void OnDownloadedData(int len, int encoded_data_length) override; void OnReceivedData(std::unique_ptr<ReceivedData> data) override; void OnTransferSizeUpdated(int transfer_size_diff) override; void OnReceivedCachedMetadata(const char* data, int len) override; @@ -73,9 +72,6 @@ class TestRequestPeer : public RequestPeer { int total_encoded_data_length = 0; bool defer_on_transfer_size_updated = false; - // Total length when downloading to a file. - int total_downloaded_data_length = 0; - bool complete = false; bool cancelled = false; int request_id = -1; diff --git a/chromium/content/renderer/loader/url_loader_client_impl.cc b/chromium/content/renderer/loader/url_loader_client_impl.cc index 9b237d2ae52..0deb4423338 100644 --- a/chromium/content/renderer/loader/url_loader_client_impl.cc +++ b/chromium/content/renderer/loader/url_loader_client_impl.cc @@ -65,23 +65,6 @@ class URLLoaderClientImpl::DeferredOnReceiveRedirect final scoped_refptr<base::SingleThreadTaskRunner> task_runner_; }; -class URLLoaderClientImpl::DeferredOnDataDownloaded final - : public DeferredMessage { - public: - DeferredOnDataDownloaded(int64_t data_length, int64_t encoded_data_length) - : data_length_(data_length), encoded_data_length_(encoded_data_length) {} - - void HandleMessage(ResourceDispatcher* dispatcher, int request_id) override { - dispatcher->OnDownloadedData(request_id, data_length_, - encoded_data_length_); - } - bool IsCompletionMessage() const override { return false; } - - private: - const int64_t data_length_; - const int64_t encoded_data_length_; -}; - class URLLoaderClientImpl::DeferredOnUploadProgress final : public DeferredMessage { public: @@ -233,10 +216,8 @@ void URLLoaderClientImpl::Bind( } void URLLoaderClientImpl::OnReceiveResponse( - const network::ResourceResponseHead& response_head, - network::mojom::DownloadedTempFilePtr downloaded_file) { + const network::ResourceResponseHead& response_head) { has_received_response_ = true; - downloaded_file_ = std::move(downloaded_file); if (NeedsStoringMessage()) { StoreAndDispatch( std::make_unique<DeferredOnReceiveResponse>(response_head)); @@ -259,17 +240,6 @@ void URLLoaderClientImpl::OnReceiveRedirect( } } -void URLLoaderClientImpl::OnDataDownloaded(int64_t data_len, - int64_t encoded_data_len) { - if (NeedsStoringMessage()) { - StoreAndDispatch( - std::make_unique<DeferredOnDataDownloaded>(data_len, encoded_data_len)); - } else { - resource_dispatcher_->OnDownloadedData(request_id_, data_len, - encoded_data_len); - } -} - void URLLoaderClientImpl::OnUploadProgress( int64_t current_position, int64_t total_size, @@ -338,11 +308,6 @@ void URLLoaderClientImpl::OnComplete( body_consumer_->OnComplete(status); } -network::mojom::DownloadedTempFilePtr -URLLoaderClientImpl::TakeDownloadedTempFile() { - return std::move(downloaded_file_); -} - bool URLLoaderClientImpl::NeedsStoringMessage() const { return is_deferred_ || deferred_messages_.size() > 0; } diff --git a/chromium/content/renderer/loader/url_loader_client_impl.h b/chromium/content/renderer/loader/url_loader_client_impl.h index 66c1a455214..6ede15c50e6 100644 --- a/chromium/content/renderer/loader/url_loader_client_impl.h +++ b/chromium/content/renderer/loader/url_loader_client_impl.h @@ -68,12 +68,10 @@ class CONTENT_EXPORT URLLoaderClientImpl final // network::mojom::URLLoaderClient implementation void OnReceiveResponse( - const network::ResourceResponseHead& response_head, - network::mojom::DownloadedTempFilePtr downloaded_file) override; + const network::ResourceResponseHead& response_head) override; void OnReceiveRedirect( const net::RedirectInfo& redirect_info, const network::ResourceResponseHead& response_head) override; - void OnDataDownloaded(int64_t data_len, int64_t encoded_data_len) override; void OnUploadProgress(int64_t current_position, int64_t total_size, OnUploadProgressCallback ack_callback) override; @@ -83,14 +81,10 @@ class CONTENT_EXPORT URLLoaderClientImpl final mojo::ScopedDataPipeConsumerHandle body) override; void OnComplete(const network::URLLoaderCompletionStatus& status) override; - // Takes |downloaded_file_|. - network::mojom::DownloadedTempFilePtr TakeDownloadedTempFile(); - private: class DeferredMessage; class DeferredOnReceiveResponse; class DeferredOnReceiveRedirect; - class DeferredOnDataDownloaded; class DeferredOnUploadProgress; class DeferredOnReceiveCachedMetadata; class DeferredOnComplete; @@ -100,7 +94,6 @@ class CONTENT_EXPORT URLLoaderClientImpl final void OnConnectionClosed(); scoped_refptr<URLResponseBodyConsumer> body_consumer_; - network::mojom::DownloadedTempFilePtr downloaded_file_; std::vector<std::unique_ptr<DeferredMessage>> deferred_messages_; const int request_id_; bool has_received_response_ = false; 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 4278bd904a9..71bdf233be9 100644 --- a/chromium/content/renderer/loader/url_loader_client_impl_unittest.cc +++ b/chromium/content/renderer/loader/url_loader_client_impl_unittest.cc @@ -79,7 +79,7 @@ class URLLoaderClientImplTest : public ::testing::Test, TEST_F(URLLoaderClientImplTest, OnReceiveResponse) { network::ResourceResponseHead response_head; - url_loader_client_->OnReceiveResponse(response_head, nullptr); + url_loader_client_->OnReceiveResponse(response_head); EXPECT_FALSE(request_peer_context_.received_response); base::RunLoop().RunUntilIdle(); @@ -89,7 +89,7 @@ TEST_F(URLLoaderClientImplTest, OnReceiveResponse) { TEST_F(URLLoaderClientImplTest, ResponseBody) { network::ResourceResponseHead response_head; - url_loader_client_->OnReceiveResponse(response_head, nullptr); + url_loader_client_->OnReceiveResponse(response_head); EXPECT_FALSE(request_peer_context_.received_response); base::RunLoop().RunUntilIdle(); @@ -119,28 +119,12 @@ TEST_F(URLLoaderClientImplTest, OnReceiveRedirect) { EXPECT_EQ(1, request_peer_context_.seen_redirects); } -TEST_F(URLLoaderClientImplTest, OnDataDownloaded) { - network::ResourceResponseHead response_head; - - url_loader_client_->OnReceiveResponse(response_head, nullptr); - url_loader_client_->OnDataDownloaded(8, 13); - url_loader_client_->OnDataDownloaded(2, 1); - - EXPECT_FALSE(request_peer_context_.received_response); - EXPECT_EQ(0, request_peer_context_.total_downloaded_data_length); - EXPECT_EQ(0, request_peer_context_.total_encoded_data_length); - base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(request_peer_context_.received_response); - EXPECT_EQ(10, request_peer_context_.total_downloaded_data_length); - EXPECT_EQ(14, request_peer_context_.total_encoded_data_length); -} - TEST_F(URLLoaderClientImplTest, OnReceiveCachedMetadata) { network::ResourceResponseHead response_head; std::vector<uint8_t> metadata; metadata.push_back('a'); - url_loader_client_->OnReceiveResponse(response_head, nullptr); + url_loader_client_->OnReceiveResponse(response_head); url_loader_client_->OnReceiveCachedMetadata(metadata); EXPECT_FALSE(request_peer_context_.received_response); @@ -154,7 +138,7 @@ TEST_F(URLLoaderClientImplTest, OnReceiveCachedMetadata) { TEST_F(URLLoaderClientImplTest, OnTransferSizeUpdated) { network::ResourceResponseHead response_head; - url_loader_client_->OnReceiveResponse(response_head, nullptr); + url_loader_client_->OnReceiveResponse(response_head); url_loader_client_->OnTransferSizeUpdated(4); url_loader_client_->OnTransferSizeUpdated(4); @@ -169,7 +153,7 @@ TEST_F(URLLoaderClientImplTest, OnCompleteWithoutResponseBody) { network::ResourceResponseHead response_head; network::URLLoaderCompletionStatus status; - url_loader_client_->OnReceiveResponse(response_head, nullptr); + url_loader_client_->OnReceiveResponse(response_head); url_loader_client_->OnComplete(status); EXPECT_FALSE(request_peer_context_.received_response); @@ -183,7 +167,7 @@ TEST_F(URLLoaderClientImplTest, OnCompleteWithResponseBody) { network::ResourceResponseHead response_head; network::URLLoaderCompletionStatus status; - url_loader_client_->OnReceiveResponse(response_head, nullptr); + url_loader_client_->OnReceiveResponse(response_head); mojo::DataPipe data_pipe(DataPipeOptions()); url_loader_client_->OnStartLoadingResponseBody( std::move(data_pipe.consumer_handle)); @@ -217,7 +201,7 @@ TEST_F(URLLoaderClientImplTest, OnCompleteShouldBeTheLastMessage) { network::ResourceResponseHead response_head; network::URLLoaderCompletionStatus status; - url_loader_client_->OnReceiveResponse(response_head, nullptr); + url_loader_client_->OnReceiveResponse(response_head); mojo::DataPipe data_pipe(DataPipeOptions()); url_loader_client_->OnStartLoadingResponseBody( std::move(data_pipe.consumer_handle)); @@ -249,7 +233,7 @@ TEST_F(URLLoaderClientImplTest, CancelOnReceiveResponse) { network::ResourceResponseHead response_head; network::URLLoaderCompletionStatus status; - url_loader_client_->OnReceiveResponse(response_head, nullptr); + url_loader_client_->OnReceiveResponse(response_head); mojo::DataPipe data_pipe(DataPipeOptions()); url_loader_client_->OnStartLoadingResponseBody( std::move(data_pipe.consumer_handle)); @@ -278,7 +262,7 @@ TEST_F(URLLoaderClientImplTest, CancelOnReceiveData) { ASSERT_EQ(MOJO_RESULT_OK, result); EXPECT_EQ(5u, size); - url_loader_client_->OnReceiveResponse(response_head, nullptr); + url_loader_client_->OnReceiveResponse(response_head); url_loader_client_->OnStartLoadingResponseBody( std::move(data_pipe.consumer_handle)); url_loader_client_->OnComplete(status); @@ -299,7 +283,7 @@ TEST_F(URLLoaderClientImplTest, Defer) { network::ResourceResponseHead response_head; network::URLLoaderCompletionStatus status; - url_loader_client_->OnReceiveResponse(response_head, nullptr); + url_loader_client_->OnReceiveResponse(response_head); url_loader_client_->OnComplete(status); EXPECT_FALSE(request_peer_context_.received_response); @@ -324,7 +308,7 @@ TEST_F(URLLoaderClientImplTest, DeferWithResponseBody) { network::ResourceResponseHead response_head; network::URLLoaderCompletionStatus status; - url_loader_client_->OnReceiveResponse(response_head, nullptr); + url_loader_client_->OnReceiveResponse(response_head); mojo::DataPipe data_pipe(DataPipeOptions()); uint32_t size = 5; MojoResult result = data_pipe.producer_handle->WriteData( @@ -365,7 +349,7 @@ TEST_F(URLLoaderClientImplTest, DeferWithTransferSizeUpdated) { network::ResourceResponseHead response_head; network::URLLoaderCompletionStatus status; - url_loader_client_->OnReceiveResponse(response_head, nullptr); + url_loader_client_->OnReceiveResponse(response_head); mojo::DataPipe data_pipe(DataPipeOptions()); uint32_t size = 5; MojoResult result = data_pipe.producer_handle->WriteData( @@ -413,7 +397,7 @@ TEST_F(URLLoaderClientImplTest, SetDeferredDuringFlushingDeferredMessage) { network::URLLoaderCompletionStatus status; url_loader_client_->OnReceiveRedirect(redirect_info, response_head); - url_loader_client_->OnReceiveResponse(response_head, nullptr); + url_loader_client_->OnReceiveResponse(response_head); mojo::DataPipe data_pipe(DataPipeOptions()); uint32_t size = 5; MojoResult result = data_pipe.producer_handle->WriteData( @@ -474,7 +458,7 @@ TEST_F(URLLoaderClientImplTest, network::ResourceResponseHead response_head; network::URLLoaderCompletionStatus status; - url_loader_client_->OnReceiveResponse(response_head, nullptr); + url_loader_client_->OnReceiveResponse(response_head); url_loader_client_->OnTransferSizeUpdated(4); url_loader_client_->OnComplete(status); @@ -523,7 +507,7 @@ TEST_F(URLLoaderClientImplTest, CancelOnReceiveDataWhileFlushing) { ASSERT_EQ(MOJO_RESULT_OK, result); EXPECT_EQ(5u, size); - url_loader_client_->OnReceiveResponse(response_head, nullptr); + url_loader_client_->OnReceiveResponse(response_head); url_loader_client_->OnStartLoadingResponseBody( std::move(data_pipe.consumer_handle)); url_loader_client_->OnComplete(status); diff --git a/chromium/content/renderer/loader/url_response_body_consumer_unittest.cc b/chromium/content/renderer/loader/url_response_body_consumer_unittest.cc index 3038533caa2..fb32f809835 100644 --- a/chromium/content/renderer/loader/url_response_body_consumer_unittest.cc +++ b/chromium/content/renderer/loader/url_response_body_consumer_unittest.cc @@ -55,10 +55,6 @@ class TestRequestPeer : public RequestPeer { ADD_FAILURE() << "OnStartLoadingResponseBody should not be called."; } - void OnDownloadedData(int len, int encoded_data_length) override { - ADD_FAILURE() << "OnDownloadedData should not be called."; - } - void OnReceivedData(std::unique_ptr<ReceivedData> data) override { EXPECT_FALSE(context_->complete); context_->data.append(data->payload(), data->length()); diff --git a/chromium/content/renderer/loader/web_url_loader_impl.cc b/chromium/content/renderer/loader/web_url_loader_impl.cc index c1ece37554f..b031f857bb1 100644 --- a/chromium/content/renderer/loader/web_url_loader_impl.cc +++ b/chromium/content/renderer/loader/web_url_loader_impl.cc @@ -89,6 +89,7 @@ using blink::WebURLLoader; using blink::WebURLLoaderClient; using blink::WebURLRequest; using blink::WebURLResponse; +using blink::scheduler::WebResourceLoadingTaskRunnerHandle; namespace content { @@ -367,21 +368,28 @@ WebURLLoaderFactoryImpl::CreateTestOnlyFactory() { std::unique_ptr<blink::WebURLLoader> WebURLLoaderFactoryImpl::CreateURLLoader( const blink::WebURLRequest& request, - scoped_refptr<base::SingleThreadTaskRunner> task_runner) { + std::unique_ptr<WebResourceLoadingTaskRunnerHandle> task_runner_handle) { if (!loader_factory_) { // In some tests like RenderViewTests loader_factory_ is not available. // These tests can still use data URLs to bypass the ResourceDispatcher. - if (!task_runner) - task_runner = base::ThreadTaskRunnerHandle::Get(); + if (!task_runner_handle) { + // TODO(altimin): base::ThreadTaskRunnerHandle::Get is deprecated in + // the renderer. Fix this for frame and non-frame clients. + task_runner_handle = + WebResourceLoadingTaskRunnerHandle::CreateUnprioritized( + base::ThreadTaskRunnerHandle::Get()); + } + return std::make_unique<WebURLLoaderImpl>(resource_dispatcher_.get(), - std::move(task_runner), + std::move(task_runner_handle), nullptr /* factory */); } - DCHECK(task_runner); + DCHECK(task_runner_handle); DCHECK(resource_dispatcher_); - return std::make_unique<WebURLLoaderImpl>( - resource_dispatcher_.get(), std::move(task_runner), loader_factory_); + return std::make_unique<WebURLLoaderImpl>(resource_dispatcher_.get(), + std::move(task_runner_handle), + loader_factory_); } // This inner class exists since the WebURLLoader may be deleted while inside a @@ -391,11 +399,12 @@ class WebURLLoaderImpl::Context : public base::RefCounted<Context> { public: using ReceivedData = RequestPeer::ReceivedData; - Context(WebURLLoaderImpl* loader, - ResourceDispatcher* resource_dispatcher, - scoped_refptr<base::SingleThreadTaskRunner> task_runner, - scoped_refptr<network::SharedURLLoaderFactory> factory, - mojom::KeepAliveHandlePtr keep_alive_handle); + Context( + WebURLLoaderImpl* loader, + ResourceDispatcher* resource_dispatcher, + std::unique_ptr<WebResourceLoadingTaskRunnerHandle> task_runner_handle, + scoped_refptr<network::SharedURLLoaderFactory> factory, + mojom::KeepAliveHandlePtr keep_alive_handle); ResourceDispatcher* resource_dispatcher() { return resource_dispatcher_; } int request_id() const { return request_id_; } @@ -417,7 +426,6 @@ class WebURLLoaderImpl::Context : public base::RefCounted<Context> { const network::ResourceResponseInfo& info); void OnReceivedResponse(const network::ResourceResponseInfo& info); void OnStartLoadingResponseBody(mojo::ScopedDataPipeConsumerHandle body); - void OnDownloadedData(int len, int encoded_data_length); void OnReceivedData(std::unique_ptr<ReceivedData> data); void OnTransferSizeUpdated(int transfer_size_diff); void OnReceivedCachedMetadata(const char* data, int len); @@ -450,6 +458,7 @@ class WebURLLoaderImpl::Context : public base::RefCounted<Context> { WebURLLoaderClient* client_; ResourceDispatcher* resource_dispatcher_; + std::unique_ptr<WebResourceLoadingTaskRunnerHandle> task_runner_handle_; scoped_refptr<base::SingleThreadTaskRunner> task_runner_; std::unique_ptr<FtpDirectoryListingResponseDelegate> ftp_listing_delegate_; std::unique_ptr<SharedMemoryDataConsumerHandle::Writer> body_stream_writer_; @@ -477,7 +486,6 @@ class WebURLLoaderImpl::RequestPeerImpl : public RequestPeer { void OnReceivedResponse(const network::ResourceResponseInfo& info) override; void OnStartLoadingResponseBody( mojo::ScopedDataPipeConsumerHandle body) override; - void OnDownloadedData(int len, int encoded_data_length) override; void OnReceivedData(std::unique_ptr<ReceivedData> data) override; void OnTransferSizeUpdated(int transfer_size_diff) override; void OnReceivedCachedMetadata(const char* data, int len) override; @@ -504,7 +512,6 @@ class WebURLLoaderImpl::SinkPeer : public RequestPeer { void OnReceivedResponse(const network::ResourceResponseInfo& info) override {} void OnStartLoadingResponseBody( mojo::ScopedDataPipeConsumerHandle body) override {} - void OnDownloadedData(int len, int encoded_data_length) override {} void OnReceivedData(std::unique_ptr<ReceivedData> data) override {} void OnTransferSizeUpdated(int transfer_size_diff) override {} void OnReceivedCachedMetadata(const char* data, int len) override {} @@ -524,7 +531,7 @@ class WebURLLoaderImpl::SinkPeer : public RequestPeer { WebURLLoaderImpl::Context::Context( WebURLLoaderImpl* loader, ResourceDispatcher* resource_dispatcher, - scoped_refptr<base::SingleThreadTaskRunner> task_runner, + std::unique_ptr<WebResourceLoadingTaskRunnerHandle> task_runner_handle, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, mojom::KeepAliveHandlePtr keep_alive_handle_ptr) : loader_(loader), @@ -532,7 +539,8 @@ WebURLLoaderImpl::Context::Context( report_raw_headers_(false), client_(nullptr), resource_dispatcher_(resource_dispatcher), - task_runner_(std::move(task_runner)), + task_runner_handle_(std::move(task_runner_handle)), + task_runner_(task_runner_handle_->GetTaskRunner()), keep_alive_handle_( keep_alive_handle_ptr ? std::make_unique<KeepAliveHandleWithChildProcessReference>( @@ -583,10 +591,11 @@ void WebURLLoaderImpl::Context::SetDefersLoading(bool value) { void WebURLLoaderImpl::Context::DidChangePriority( WebURLRequest::Priority new_priority, int intra_priority_value) { if (request_id_ != -1) { - resource_dispatcher_->DidChangePriority( - request_id_, - ConvertWebKitPriorityToNetPriority(new_priority), - intra_priority_value); + net::RequestPriority net_priority = + ConvertWebKitPriorityToNetPriority(new_priority); + resource_dispatcher_->DidChangePriority(request_id_, net_priority, + intra_priority_value); + task_runner_handle_->DidChangeRequestPriority(net_priority); } } @@ -644,6 +653,7 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request, resource_request->method = method; resource_request->url = url_; resource_request->site_for_cookies = request.SiteForCookies(); + resource_request->upgrade_if_insecure = request.UpgradeIfInsecure(); resource_request->request_initiator = request.RequestorOrigin().IsNull() ? base::Optional<url::Origin>() @@ -698,7 +708,6 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request, resource_request->fetch_frame_type = request.GetFrameType(); resource_request->request_body = GetRequestBodyForWebURLRequest(request).get(); - resource_request->download_to_file = request.DownloadToFile(); resource_request->keepalive = request.GetKeepalive(); resource_request->has_user_gesture = request.HasUserGesture(); resource_request->enable_load_timing = true; @@ -712,6 +721,7 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request, resource_request->report_raw_headers = request.ReportRawHeaders(); resource_request->previews_state = static_cast<int>(request.GetPreviewsState()); + resource_request->throttling_profile_id = request.GetDevToolsToken(); // The network request has already been made by the browser. The renderer // should bind the URLLoaderClientEndpoints stored in |response_override| to @@ -882,12 +892,6 @@ void WebURLLoaderImpl::Context::OnStartLoadingResponseBody( client_->DidStartLoadingResponseBody(std::move(body)); } -void WebURLLoaderImpl::Context::OnDownloadedData(int len, - int encoded_data_length) { - if (client_) - client_->DidDownloadData(len, encoded_data_length); -} - void WebURLLoaderImpl::Context::OnReceivedData( std::unique_ptr<ReceivedData> data) { const char* payload = data->payload(); @@ -964,7 +968,7 @@ void WebURLLoaderImpl::Context::OnCompletedRequest( } else { client_->DidFinishLoading(status.completion_time, total_transfer_size, encoded_body_size, status.decoded_body_length, - status.blocked_cross_site_document); + status.should_report_corb_blocking); } } } @@ -1003,8 +1007,8 @@ bool WebURLLoaderImpl::Context::CanHandleDataURLRequestLocally( return false; // The fast paths for data URL, Start() and HandleDataURL(), don't support - // the downloadToFile option. - if (request.DownloadToFile() || request.PassResponsePipeToClient()) + // the PassResponsePipeToClient option. + if (request.PassResponsePipeToClient()) return false; // Data url requests from object tags may need to be intercepted as streams @@ -1099,12 +1103,6 @@ void WebURLLoaderImpl::RequestPeerImpl::OnStartLoadingResponseBody( context_->OnStartLoadingResponseBody(std::move(body)); } -void WebURLLoaderImpl::RequestPeerImpl::OnDownloadedData( - int len, - int encoded_data_length) { - context_->OnDownloadedData(len, encoded_data_length); -} - void WebURLLoaderImpl::RequestPeerImpl::OnReceivedData( std::unique_ptr<ReceivedData> data) { if (discard_body_) @@ -1134,21 +1132,21 @@ void WebURLLoaderImpl::RequestPeerImpl::OnCompletedRequest( WebURLLoaderImpl::WebURLLoaderImpl( ResourceDispatcher* resource_dispatcher, - scoped_refptr<base::SingleThreadTaskRunner> task_runner, + std::unique_ptr<WebResourceLoadingTaskRunnerHandle> task_runner_handle, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) : WebURLLoaderImpl(resource_dispatcher, - std::move(task_runner), + std::move(task_runner_handle), std::move(url_loader_factory), nullptr) {} WebURLLoaderImpl::WebURLLoaderImpl( ResourceDispatcher* resource_dispatcher, - scoped_refptr<base::SingleThreadTaskRunner> task_runner, + std::unique_ptr<WebResourceLoadingTaskRunnerHandle> task_runner_handle, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, mojom::KeepAliveHandlePtr keep_alive_handle) : context_(new Context(this, resource_dispatcher, - std::move(task_runner), + std::move(task_runner_handle), std::move(url_loader_factory), std::move(keep_alive_handle))) {} @@ -1181,8 +1179,6 @@ void WebURLLoaderImpl::PopulateURLResponse( response->SetRemotePort(info.socket_address.port()); response->SetConnectionID(info.load_timing.socket_log_id); response->SetConnectionReused(info.load_timing.socket_reused); - response->SetDownloadFilePath( - blink::FilePathToWebString(info.download_file_path)); response->SetWasFetchedViaSPDY(info.was_fetched_via_spdy); response->SetWasFetchedViaServiceWorker(info.was_fetched_via_service_worker); response->SetWasFallbackRequiredByServiceWorker( @@ -1207,6 +1203,7 @@ void WebURLLoaderImpl::PopulateURLResponse( response->SetAlpnNegotiatedProtocol( WebString::FromUTF8(info.alpn_negotiated_protocol)); response->SetConnectionInfo(info.connection_info); + response->SetAsyncRevalidationRequested(info.async_revalidation_requested); SetSecurityStyleAndDetails(url, info, response, report_security_info); @@ -1297,7 +1294,6 @@ void WebURLLoaderImpl::LoadSynchronously( WebData& data, int64_t& encoded_data_length, int64_t& encoded_body_length, - base::Optional<int64_t>& downloaded_file_length, blink::WebBlobInfo& downloaded_blob) { TRACE_EVENT0("loading", "WebURLLoaderImpl::loadSynchronously"); SyncLoadResponse sync_load_response; @@ -1313,10 +1309,8 @@ void WebURLLoaderImpl::LoadSynchronously( const int error_code = sync_load_response.error_code; if (error_code != net::OK) { if (sync_load_response.cors_error) { - // TODO(toyoshim): Pass CORS error related headers here. - error = - WebURLError(network::CORSErrorStatus(*sync_load_response.cors_error), - WebURLError::HasCopyInCache::kFalse, final_url); + error = WebURLError(*sync_load_response.cors_error, + WebURLError::HasCopyInCache::kFalse, final_url); } else { // SyncResourceHandler returns ERR_ABORTED for CORS redirect errors, // so we treat the error as a web security violation. @@ -1335,7 +1329,6 @@ void WebURLLoaderImpl::LoadSynchronously( request.ReportRawHeaders()); encoded_data_length = sync_load_response.info.encoded_data_length; encoded_body_length = sync_load_response.info.encoded_body_length; - downloaded_file_length = sync_load_response.downloaded_file_length; if (sync_load_response.downloaded_blob) { downloaded_blob = blink::WebBlobInfo( WebString::FromLatin1(sync_load_response.downloaded_blob->uuid), diff --git a/chromium/content/renderer/loader/web_url_loader_impl.h b/chromium/content/renderer/loader/web_url_loader_impl.h index ced62e5a71b..890893884c1 100644 --- a/chromium/content/renderer/loader/web_url_loader_impl.h +++ b/chromium/content/renderer/loader/web_url_loader_impl.h @@ -5,6 +5,8 @@ #ifndef CONTENT_RENDERER_LOADER_WEB_URL_LOADER_IMPL_H_ #define CONTENT_RENDERER_LOADER_WEB_URL_LOADER_IMPL_H_ +#include <memory> + #include "base/macros.h" #include "base/memory/ref_counted.h" #include "content/common/content_export.h" @@ -12,13 +14,10 @@ #include "mojo/public/cpp/system/data_pipe.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/scheduler/web_resource_loading_task_runner_handle.h" #include "third_party/blink/public/platform/web_url_loader.h" #include "third_party/blink/public/platform/web_url_loader_factory.h" -namespace base { -class SingleThreadTaskRunner; -} - namespace network { struct ResourceResponseInfo; } @@ -41,7 +40,8 @@ class CONTENT_EXPORT WebURLLoaderFactoryImpl std::unique_ptr<blink::WebURLLoader> CreateURLLoader( const blink::WebURLRequest& request, - scoped_refptr<base::SingleThreadTaskRunner> task_runner) override; + std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle> + task_runner_handle) override; private: base::WeakPtr<ResourceDispatcher> resource_dispatcher_; @@ -53,13 +53,15 @@ class CONTENT_EXPORT WebURLLoaderImpl : public blink::WebURLLoader { public: WebURLLoaderImpl( ResourceDispatcher* resource_dispatcher, - scoped_refptr<base::SingleThreadTaskRunner> task_runner, + std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle> + task_runner_handle, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory); // When non-null |keep_alive_handle| is specified, this loader prolongs // this render process's lifetime. WebURLLoaderImpl( ResourceDispatcher* resource_dispatcher, - scoped_refptr<base::SingleThreadTaskRunner> task_runner, + std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle> + task_runner_handle, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, mojom::KeepAliveHandlePtr keep_alive_handle); ~WebURLLoaderImpl() override; @@ -76,7 +78,6 @@ class CONTENT_EXPORT WebURLLoaderImpl : public blink::WebURLLoader { blink::WebData& data, int64_t& encoded_data_length, int64_t& encoded_body_length, - base::Optional<int64_t>& downloaded_file_length, blink::WebBlobInfo& downloaded_blob) override; void LoadAsynchronously(const blink::WebURLRequest& request, blink::WebURLLoaderClient* client) override; 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 e3fd5112703..9a92c2bcb8f 100644 --- a/chromium/content/renderer/loader/web_url_loader_impl_unittest.cc +++ b/chromium/content/renderer/loader/web_url_loader_impl_unittest.cc @@ -39,6 +39,7 @@ #include "services/network/public/mojom/request_context_frame_type.mojom.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" +#include "third_party/blink/public/platform/web_data.h" #include "third_party/blink/public/platform/web_string.h" #include "third_party/blink/public/platform/web_url_error.h" #include "third_party/blink/public/platform/web_url_loader_client.h" @@ -77,7 +78,7 @@ class TestResourceDispatcher : public ResourceDispatcher { SyncLoadResponse* response, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, std::vector<std::unique_ptr<URLLoaderThrottle>> throttles, - double timeout, + base::TimeDelta timeout, blink::mojom::BlobRegistryPtrInfo download_to_blob_registry, std::unique_ptr<RequestPeer> peer) override { *response = std::move(sync_load_response_); @@ -175,7 +176,9 @@ class TestWebURLLoaderClient : public blink::WebURLLoaderClient { TestWebURLLoaderClient(ResourceDispatcher* dispatcher) : loader_(new WebURLLoaderImpl( dispatcher, - blink::scheduler::GetSingleThreadTaskRunnerForTesting(), + blink::scheduler::WebResourceLoadingTaskRunnerHandle:: + CreateUnprioritized( + blink::scheduler::GetSingleThreadTaskRunnerForTesting()), base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( &fake_url_loader_factory_))), delete_on_receive_redirect_(false), @@ -224,10 +227,6 @@ class TestWebURLLoaderClient : public blink::WebURLLoaderClient { loader_.reset(); } - void DidDownloadData(int dataLength, int encodedDataLength) override { - EXPECT_TRUE(loader_); - } - void DidReceiveData(const char* data, int dataLength) override { EXPECT_TRUE(loader_); // The response should have started, but must not have finished, or failed. @@ -245,7 +244,7 @@ class TestWebURLLoaderClient : public blink::WebURLLoaderClient { int64_t totalEncodedDataLength, int64_t totalEncodedBodyLength, int64_t totalDecodedBodyLength, - bool blocked_cross_site_document) override { + bool should_report_corb_blocking) override { EXPECT_TRUE(loader_); EXPECT_TRUE(did_receive_response_); EXPECT_FALSE(did_finish_); @@ -796,15 +795,13 @@ TEST_F(WebURLLoaderImplTest, SyncLengths) { blink::WebData data; int64_t encoded_data_length = 0; int64_t encoded_body_length = 0; - base::Optional<int64_t> downloaded_file_length; blink::WebBlobInfo downloaded_blob; - client()->loader()->LoadSynchronously( - request, nullptr, response, error, data, encoded_data_length, - encoded_body_length, downloaded_file_length, downloaded_blob); + client()->loader()->LoadSynchronously(request, nullptr, response, error, data, + encoded_data_length, + encoded_body_length, downloaded_blob); EXPECT_EQ(kEncodedBodyLength, encoded_body_length); EXPECT_EQ(kEncodedDataLength, encoded_data_length); - EXPECT_FALSE(downloaded_file_length); EXPECT_TRUE(downloaded_blob.Uuid().IsNull()); } diff --git a/chromium/content/renderer/loader/web_url_request_util.cc b/chromium/content/renderer/loader/web_url_request_util.cc index 9dacb1aad64..bceb21b9362 100644 --- a/chromium/content/renderer/loader/web_url_request_util.cc +++ b/chromium/content/renderer/loader/web_url_request_util.cc @@ -30,6 +30,7 @@ #include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom-shared.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/web_data.h" +#include "third_party/blink/public/platform/web_http_body.h" #include "third_party/blink/public/platform/web_http_header_visitor.h" #include "third_party/blink/public/platform/web_mixed_content.h" #include "third_party/blink/public/platform/web_string.h" @@ -291,6 +292,8 @@ int GetLoadFlagsForWebURLRequest(const WebURLRequest& request) { if (extra_data->is_for_no_state_prefetch()) load_flags |= net::LOAD_PREFETCH; } + if (request.SupportsAsyncRevalidation()) + load_flags |= net::LOAD_SUPPORT_ASYNC_REVALIDATION; return load_flags; } @@ -389,12 +392,7 @@ scoped_refptr<network::ResourceRequestBody> GetRequestBodyForWebHTTPBody( while (httpBody.ElementAt(i++, element)) { switch (element.type) { case WebHTTPBody::Element::kTypeData: - element.data.ForEachSegment([&request_body](const char* segment, - size_t segment_size, - size_t segment_offset) { - request_body->AppendBytes(segment, static_cast<int>(segment_size)); - return true; - }); + request_body->AppendBytes(element.data.Copy().ReleaseVector()); break; case WebHTTPBody::Element::kTypeFile: if (element.file_length == -1) { diff --git a/chromium/content/renderer/service_worker/worker_fetch_context_impl.cc b/chromium/content/renderer/loader/web_worker_fetch_context_impl.cc index bc16217cbdc..d548ae54b5d 100644 --- a/chromium/content/renderer/service_worker/worker_fetch_context_impl.cc +++ b/chromium/content/renderer/loader/web_worker_fetch_context_impl.cc @@ -2,16 +2,20 @@ // 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/worker_fetch_context_impl.h" +#include "content/renderer/loader/web_worker_fetch_context_impl.h" + +#include <utility> #include "base/feature_list.h" #include "base/single_thread_task_runner.h" +#include "base/task_scheduler/post_task.h" #include "content/child/child_thread_impl.h" #include "content/child/thread_safe_sender.h" +#include "content/common/content_constants_internal.h" #include "content/common/frame_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/content_features.h" +#include "content/public/common/origin_util.h" #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" @@ -25,31 +29,35 @@ #include "mojo/public/cpp/bindings/strong_binding.h" #include "services/network/public/cpp/wrapper_shared_url_loader_factory.h" #include "services/service_manager/public/cpp/connector.h" +#include "third_party/blink/public/common/service_worker/service_worker_utils.h" #include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h" +#include "third_party/blink/public/platform/web_security_origin.h" namespace content { -WorkerFetchContextImpl::RewriteURLFunction g_rewrite_url = nullptr; +WebWorkerFetchContextImpl::RewriteURLFunction g_rewrite_url = nullptr; namespace { // Runs on IO thread. -void CreateSubresourceLoaderFactory( +void CreateSubresourceLoaderFactoryForWorker( mojom::ServiceWorkerContainerHostPtrInfo container_host_info, const std::string& client_id, std::unique_ptr<network::SharedURLLoaderFactoryInfo> fallback_factory, - network::mojom::URLLoaderFactoryRequest request) { + network::mojom::URLLoaderFactoryRequest request, + scoped_refptr<base::SequencedTaskRunner> task_runner) { ServiceWorkerSubresourceLoaderFactory::Create( base::MakeRefCounted<ControllerServiceWorkerConnector>( - std::move(container_host_info), client_id), + std::move(container_host_info), nullptr /* controller_ptr */, + client_id), network::SharedURLLoaderFactory::Create(std::move(fallback_factory)), - std::move(request)); + std::move(request), std::move(task_runner)); } } // namespace // static -void WorkerFetchContextImpl::InstallRewriteURLFunction( +void WebWorkerFetchContextImpl::InstallRewriteURLFunction( RewriteURLFunction rewrite_url) { CHECK(!g_rewrite_url); g_rewrite_url = rewrite_url; @@ -60,7 +68,7 @@ void WorkerFetchContextImpl::InstallRewriteURLFunction( // worker fetch context is controlled by a service worker, it creates a loader // that uses |service_worker_loader_factory_| for requests that should be // intercepted by the service worker. -class WorkerFetchContextImpl::Factory : public blink::WebURLLoaderFactory { +class WebWorkerFetchContextImpl::Factory : public blink::WebURLLoaderFactory { public: Factory(base::WeakPtr<ResourceDispatcher> resource_dispatcher, scoped_refptr<network::SharedURLLoaderFactory> loader_factory) @@ -71,17 +79,29 @@ class WorkerFetchContextImpl::Factory : public blink::WebURLLoaderFactory { std::unique_ptr<blink::WebURLLoader> CreateURLLoader( const blink::WebURLRequest& request, - scoped_refptr<base::SingleThreadTaskRunner> task_runner) override { - DCHECK(task_runner); + std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle> + task_runner_handle) override { + DCHECK(task_runner_handle); DCHECK(resource_dispatcher_); - if (auto loader = CreateServiceWorkerURLLoader(request, task_runner)) - return loader; - return std::make_unique<WebURLLoaderImpl>( - resource_dispatcher_.get(), std::move(task_runner), loader_factory_); + if (CanCreateServiceWorkerURLLoader(request)) { + // Create our own URLLoader to route the request to the controller service + // worker. + return std::make_unique<WebURLLoaderImpl>(resource_dispatcher_.get(), + std::move(task_runner_handle), + service_worker_loader_factory_); + } + + return std::make_unique<WebURLLoaderImpl>(resource_dispatcher_.get(), + std::move(task_runner_handle), + loader_factory_); } void SetServiceWorkerURLLoaderFactory( network::mojom::URLLoaderFactoryPtr service_worker_loader_factory) { + if (!service_worker_loader_factory) { + service_worker_loader_factory_ = nullptr; + return; + } service_worker_loader_factory_ = base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>( std::move(service_worker_loader_factory)); @@ -90,9 +110,7 @@ class WorkerFetchContextImpl::Factory : public blink::WebURLLoaderFactory { base::WeakPtr<Factory> GetWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); } private: - std::unique_ptr<blink::WebURLLoader> CreateServiceWorkerURLLoader( - const blink::WebURLRequest& request, - scoped_refptr<base::SingleThreadTaskRunner> task_runner) { + bool CanCreateServiceWorkerURLLoader(const blink::WebURLRequest& request) { // TODO(horo): Unify this code path with // ServiceWorkerNetworkProvider::CreateURLLoader that is used for document // cases. @@ -100,21 +118,24 @@ class WorkerFetchContextImpl::Factory : public blink::WebURLLoaderFactory { // We need the service worker loader factory populated in order to create // our own URLLoader for subresource loading via a service worker. if (!service_worker_loader_factory_) - return nullptr; - - // If it's not for HTTP or HTTPS no need to intercept the request. - if (!GURL(request.Url()).SchemeIsHTTPOrHTTPS()) - return nullptr; + return false; + + // If the URL is not http(s) or otherwise whitelisted, do not intercept the + // request. Schemes like 'blob' and 'file' are not eligible to be + // intercepted by service workers. + // TODO(falken): Let ServiceWorkerSubresourceLoaderFactory handle the + // request and move this check there (i.e., for such URLs, it should use + // its fallback factory). + if (!GURL(request.Url()).SchemeIsHTTPOrHTTPS() && + !OriginCanAccessServiceWorkers(request.Url())) { + return false; + } // If GetSkipServiceWorker() returns true, no need to intercept the request. if (request.GetSkipServiceWorker()) - return nullptr; + return false; - // Create our own URLLoader to route the request to the controller service - // worker. - return std::make_unique<WebURLLoaderImpl>(resource_dispatcher_.get(), - std::move(task_runner), - service_worker_loader_factory_); + return true; } base::WeakPtr<ResourceDispatcher> resource_dispatcher_; @@ -124,8 +145,11 @@ class WorkerFetchContextImpl::Factory : public blink::WebURLLoaderFactory { DISALLOW_COPY_AND_ASSIGN(Factory); }; -WorkerFetchContextImpl::WorkerFetchContextImpl( +WebWorkerFetchContextImpl::WebWorkerFetchContextImpl( + RendererPreferences renderer_preferences, mojom::ServiceWorkerWorkerClientRequest service_worker_client_request, + mojom::ServiceWorkerWorkerClientRegistryPtrInfo + service_worker_worker_client_registry_info, mojom::ServiceWorkerContainerHostPtrInfo service_worker_container_host_info, std::unique_ptr<network::SharedURLLoaderFactoryInfo> loader_factory_info, std::unique_ptr<network::SharedURLLoaderFactoryInfo> fallback_factory_info, @@ -133,54 +157,69 @@ WorkerFetchContextImpl::WorkerFetchContextImpl( std::unique_ptr<WebSocketHandshakeThrottleProvider> websocket_handshake_throttle_provider, ThreadSafeSender* thread_safe_sender, - scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) + std::unique_ptr<service_manager::Connector> service_manager_connection) : binding_(this), service_worker_client_request_(std::move(service_worker_client_request)), + service_worker_worker_client_registry_info_( + std::move(service_worker_worker_client_registry_info)), service_worker_container_host_info_( std::move(service_worker_container_host_info)), loader_factory_info_(std::move(loader_factory_info)), fallback_factory_info_(std::move(fallback_factory_info)), thread_safe_sender_(thread_safe_sender), + renderer_preferences_(std::move(renderer_preferences)), throttle_provider_(std::move(throttle_provider)), websocket_handshake_throttle_provider_( std::move(websocket_handshake_throttle_provider)), - io_task_runner_(std::move(io_task_runner)) { - if (ServiceWorkerUtils::IsServicificationEnabled()) { - ChildThreadImpl::current()->GetConnector()->BindInterface( - mojom::kBrowserServiceName, - mojo::MakeRequest(&blob_registry_ptr_info_)); - } -} + service_manager_connection_(std::move(service_manager_connection)) {} -WorkerFetchContextImpl::~WorkerFetchContextImpl() {} +WebWorkerFetchContextImpl::~WebWorkerFetchContextImpl() {} -void WorkerFetchContextImpl::SetTerminateSyncLoadEvent( +void WebWorkerFetchContextImpl::SetTerminateSyncLoadEvent( base::WaitableEvent* terminate_sync_load_event) { DCHECK(!terminate_sync_load_event_); terminate_sync_load_event_ = terminate_sync_load_event; } std::unique_ptr<blink::WebWorkerFetchContext> -WorkerFetchContextImpl::CloneForNestedWorker() { - // TODO(japhet?): This doens't plumb service worker state to nested workers, - // because dedicated workers in service worker-controlled documents are - // currently not spec compliant and we don't want to propagate the wrong - // behavior. See https://crbug.com/731604 - auto new_context = std::make_unique<WorkerFetchContextImpl>( - mojom::ServiceWorkerWorkerClientRequest(), - mojom::ServiceWorkerContainerHostPtrInfo(), loader_factory_->Clone(), +WebWorkerFetchContextImpl::CloneForNestedWorker() { + mojom::ServiceWorkerWorkerClientRequest service_worker_client_request; + mojom::ServiceWorkerWorkerClientPtr service_worker_client_ptr; + service_worker_client_request = mojo::MakeRequest(&service_worker_client_ptr); + service_worker_worker_client_registry_->RegisterWorkerClient( + std::move(service_worker_client_ptr)); + + mojom::ServiceWorkerWorkerClientRegistryPtrInfo + service_worker_worker_client_registry_ptr_info; + service_worker_worker_client_registry_->CloneWorkerClientRegistry( + mojo::MakeRequest(&service_worker_worker_client_registry_ptr_info)); + + mojom::ServiceWorkerContainerHostPtrInfo host_ptr_info; + if (blink::ServiceWorkerUtils::IsServicificationEnabled()) { + service_worker_container_host_->CloneForWorker( + mojo::MakeRequest(&host_ptr_info)); + } + + auto new_context = std::make_unique<WebWorkerFetchContextImpl>( + renderer_preferences_, 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(), throttle_provider_ ? throttle_provider_->Clone() : nullptr, websocket_handshake_throttle_provider_ ? websocket_handshake_throttle_provider_->Clone() : nullptr, - thread_safe_sender_.get(), io_task_runner_); + thread_safe_sender_.get(), service_manager_connection_->Clone()); + new_context->service_worker_provider_id_ = service_worker_provider_id_; + new_context->is_controlled_by_service_worker_ = + 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->appcache_host_id_ = appcache_host_id_; return new_context; } -void WorkerFetchContextImpl::InitializeOnWorkerThread() { +void WebWorkerFetchContextImpl::InitializeOnWorkerThread() { DCHECK(!resource_dispatcher_); DCHECK(!binding_.is_bound()); resource_dispatcher_ = std::make_unique<ResourceDispatcher>(); @@ -194,12 +233,16 @@ void WorkerFetchContextImpl::InitializeOnWorkerThread() { if (service_worker_client_request_.is_pending()) binding_.Bind(std::move(service_worker_client_request_)); - if (ServiceWorkerUtils::IsServicificationEnabled()) { + service_worker_worker_client_registry_.Bind( + std::move(service_worker_worker_client_registry_info_)); + + if (blink::ServiceWorkerUtils::IsServicificationEnabled()) { service_worker_container_host_.Bind( std::move(service_worker_container_host_info_)); blink::mojom::BlobRegistryPtr blob_registry_ptr; - blob_registry_ptr.Bind(std::move(blob_registry_ptr_info_)); + service_manager_connection_->BindInterface( + mojom::kBrowserServiceName, mojo::MakeRequest(&blob_registry_ptr)); blob_registry_ = base::MakeRefCounted< base::RefCountedData<blink::mojom::BlobRegistryPtr>>( std::move(blob_registry_ptr)); @@ -207,21 +250,21 @@ void WorkerFetchContextImpl::InitializeOnWorkerThread() { } std::unique_ptr<blink::WebURLLoaderFactory> -WorkerFetchContextImpl::CreateURLLoaderFactory() { +WebWorkerFetchContextImpl::CreateURLLoaderFactory() { DCHECK(loader_factory_); DCHECK(!web_loader_factory_); auto factory = std::make_unique<Factory>(resource_dispatcher_->GetWeakPtr(), loader_factory_); web_loader_factory_ = factory->GetWeakPtr(); - if (ServiceWorkerUtils::IsServicificationEnabled()) + if (blink::ServiceWorkerUtils::IsServicificationEnabled()) ResetServiceWorkerURLLoaderFactory(); return factory; } std::unique_ptr<blink::WebURLLoaderFactory> -WorkerFetchContextImpl::WrapURLLoaderFactory( +WebWorkerFetchContextImpl::WrapURLLoaderFactory( mojo::ScopedMessagePipeHandle url_loader_factory_handle) { return std::make_unique<WebURLLoaderFactoryImpl>( resource_dispatcher_->GetWeakPtr(), @@ -231,19 +274,25 @@ WorkerFetchContextImpl::WrapURLLoaderFactory( network::mojom::URLLoaderFactory::Version_))); } -void WorkerFetchContextImpl::WillSendRequest(blink::WebURLRequest& request) { +void WebWorkerFetchContextImpl::WillSendRequest(blink::WebURLRequest& request) { + if (renderer_preferences_.enable_do_not_track) { + request.SetHTTPHeaderField(blink::WebString::FromUTF8(kDoNotTrackHeader), + "1"); + } + auto extra_data = std::make_unique<RequestExtraData>(); extra_data->set_service_worker_provider_id(service_worker_provider_id_); - extra_data->set_render_frame_id(parent_frame_id_); + extra_data->set_render_frame_id(ancestor_frame_id_); extra_data->set_initiated_in_secure_context(is_secure_context_); if (throttle_provider_) { extra_data->set_url_loader_throttles(throttle_provider_->CreateThrottles( - parent_frame_id_, request, WebURLRequestToResourceType(request))); + ancestor_frame_id_, request, WebURLRequestToResourceType(request))); } request.SetExtraData(std::move(extra_data)); request.SetAppCacheHostID(appcache_host_id_); - if (!IsControlledByServiceWorker()) { + if (IsControlledByServiceWorker() == + blink::mojom::ControllerServiceWorkerMode::kNoController) { // TODO(falken): Is still this needed? It used to set kForeign for foreign // fetch. request.SetSkipServiceWorker(true); @@ -251,116 +300,123 @@ void WorkerFetchContextImpl::WillSendRequest(blink::WebURLRequest& request) { if (g_rewrite_url) request.SetURL(g_rewrite_url(request.Url().GetString().Utf8(), false)); + + if (!renderer_preferences_.enable_referrers) { + request.SetHTTPReferrer(blink::WebString(), + blink::kWebReferrerPolicyDefault); + } } -bool WorkerFetchContextImpl::IsControlledByServiceWorker() const { - return is_controlled_by_service_worker_ || - (controller_version_id_ != - blink::mojom::kInvalidServiceWorkerVersionId); +blink::mojom::ControllerServiceWorkerMode +WebWorkerFetchContextImpl::IsControlledByServiceWorker() const { + return is_controlled_by_service_worker_; } -void WorkerFetchContextImpl::SetIsOnSubframe(bool is_on_sub_frame) { +void WebWorkerFetchContextImpl::SetIsOnSubframe(bool is_on_sub_frame) { is_on_sub_frame_ = is_on_sub_frame; } -bool WorkerFetchContextImpl::IsOnSubframe() const { +bool WebWorkerFetchContextImpl::IsOnSubframe() const { return is_on_sub_frame_; } -blink::WebURL WorkerFetchContextImpl::SiteForCookies() const { +blink::WebURL WebWorkerFetchContextImpl::SiteForCookies() const { return site_for_cookies_; } -void WorkerFetchContextImpl::DidRunContentWithCertificateErrors() { - Send(new FrameHostMsg_DidRunContentWithCertificateErrors(parent_frame_id_)); +void WebWorkerFetchContextImpl::DidRunContentWithCertificateErrors() { + Send(new FrameHostMsg_DidRunContentWithCertificateErrors(ancestor_frame_id_)); } -void WorkerFetchContextImpl::DidDisplayContentWithCertificateErrors() { +void WebWorkerFetchContextImpl::DidDisplayContentWithCertificateErrors() { Send(new FrameHostMsg_DidDisplayContentWithCertificateErrors( - parent_frame_id_)); + ancestor_frame_id_)); } -void WorkerFetchContextImpl::DidRunInsecureContent( +void WebWorkerFetchContextImpl::DidRunInsecureContent( const blink::WebSecurityOrigin& origin, const blink::WebURL& url) { Send(new FrameHostMsg_DidRunInsecureContent( - parent_frame_id_, GURL(origin.ToString().Utf8()), url)); + ancestor_frame_id_, GURL(origin.ToString().Utf8()), url)); } -void WorkerFetchContextImpl::SetSubresourceFilterBuilder( +void WebWorkerFetchContextImpl::SetSubresourceFilterBuilder( std::unique_ptr<blink::WebDocumentSubresourceFilter::Builder> subresource_filter_builder) { subresource_filter_builder_ = std::move(subresource_filter_builder); } std::unique_ptr<blink::WebDocumentSubresourceFilter> -WorkerFetchContextImpl::TakeSubresourceFilter() { +WebWorkerFetchContextImpl::TakeSubresourceFilter() { if (!subresource_filter_builder_) return nullptr; return std::move(subresource_filter_builder_)->Build(); } std::unique_ptr<blink::WebSocketHandshakeThrottle> -WorkerFetchContextImpl::CreateWebSocketHandshakeThrottle() { +WebWorkerFetchContextImpl::CreateWebSocketHandshakeThrottle() { if (!websocket_handshake_throttle_provider_) return nullptr; return websocket_handshake_throttle_provider_->CreateThrottle( - parent_frame_id_); + ancestor_frame_id_); } -void WorkerFetchContextImpl::set_service_worker_provider_id(int id) { +void WebWorkerFetchContextImpl::set_service_worker_provider_id(int id) { service_worker_provider_id_ = id; } -void WorkerFetchContextImpl::set_is_controlled_by_service_worker(bool flag) { - is_controlled_by_service_worker_ = flag; +void WebWorkerFetchContextImpl::set_is_controlled_by_service_worker( + blink::mojom::ControllerServiceWorkerMode mode) { + is_controlled_by_service_worker_ = mode; } -void WorkerFetchContextImpl::set_parent_frame_id(int id) { - parent_frame_id_ = id; +void WebWorkerFetchContextImpl::set_ancestor_frame_id(int id) { + ancestor_frame_id_ = id; } -void WorkerFetchContextImpl::set_site_for_cookies( +void WebWorkerFetchContextImpl::set_site_for_cookies( const blink::WebURL& site_for_cookies) { site_for_cookies_ = site_for_cookies; } -void WorkerFetchContextImpl::set_is_secure_context(bool flag) { +void WebWorkerFetchContextImpl::set_is_secure_context(bool flag) { is_secure_context_ = flag; } -void WorkerFetchContextImpl::set_origin_url(const GURL& origin_url) { +void WebWorkerFetchContextImpl::set_origin_url(const GURL& origin_url) { origin_url_ = origin_url; } -void WorkerFetchContextImpl::set_client_id(const std::string& client_id) { +void WebWorkerFetchContextImpl::set_client_id(const std::string& client_id) { client_id_ = client_id; } -void WorkerFetchContextImpl::SetApplicationCacheHostID(int id) { +void WebWorkerFetchContextImpl::SetApplicationCacheHostID(int id) { appcache_host_id_ = id; } -int WorkerFetchContextImpl::ApplicationCacheHostID() const { +int WebWorkerFetchContextImpl::ApplicationCacheHostID() const { return appcache_host_id_; } -void WorkerFetchContextImpl::SetControllerServiceWorker( - int64_t controller_version_id) { - controller_version_id_ = controller_version_id; - if (ServiceWorkerUtils::IsServicificationEnabled()) +void WebWorkerFetchContextImpl::OnControllerChanged( + blink::mojom::ControllerServiceWorkerMode mode) { + set_is_controlled_by_service_worker(mode); + + if (blink::ServiceWorkerUtils::IsServicificationEnabled()) ResetServiceWorkerURLLoaderFactory(); } -bool WorkerFetchContextImpl::Send(IPC::Message* message) { +bool WebWorkerFetchContextImpl::Send(IPC::Message* message) { return thread_safe_sender_->Send(message); } -void WorkerFetchContextImpl::ResetServiceWorkerURLLoaderFactory() { - DCHECK(ServiceWorkerUtils::IsServicificationEnabled()); +void WebWorkerFetchContextImpl::ResetServiceWorkerURLLoaderFactory() { + DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled()); if (!web_loader_factory_) return; - if (!IsControlledByServiceWorker()) { + if (IsControlledByServiceWorker() != + blink::mojom::ControllerServiceWorkerMode::kControlled) { web_loader_factory_->SetServiceWorkerURLLoaderFactory(nullptr); return; } @@ -370,12 +426,15 @@ void WorkerFetchContextImpl::ResetServiceWorkerURLLoaderFactory() { service_worker_container_host_->CloneForWorker( mojo::MakeRequest(&host_ptr_info)); // To avoid potential dead-lock while synchronous loading, create the - // SubresourceLoaderFactory on the IO thread. - io_task_runner_->PostTask( + // SubresourceLoaderFactory on a background thread. + auto task_runner = base::CreateSequencedTaskRunnerWithTraits( + {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}); + task_runner->PostTask( FROM_HERE, - base::BindOnce(&CreateSubresourceLoaderFactory, std::move(host_ptr_info), - client_id_, fallback_factory_->Clone(), - mojo::MakeRequest(&service_worker_url_loader_factory))); + base::BindOnce( + &CreateSubresourceLoaderFactoryForWorker, std::move(host_ptr_info), + client_id_, fallback_factory_->Clone(), + mojo::MakeRequest(&service_worker_url_loader_factory), task_runner)); web_loader_factory_->SetServiceWorkerURLLoaderFactory( std::move(service_worker_url_loader_factory)); } diff --git a/chromium/content/renderer/service_worker/worker_fetch_context_impl.h b/chromium/content/renderer/loader/web_worker_fetch_context_impl.h index 82217aa61f7..519e3bc570d 100644 --- a/chromium/content/renderer/service_worker/worker_fetch_context_impl.h +++ b/chromium/content/renderer/loader/web_worker_fetch_context_impl.h @@ -2,16 +2,21 @@ // 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_WORKER_FETCH_CONTEXT_IMPL_H_ -#define CONTENT_RENDERER_SERVICE_WORKER_WORKER_FETCH_CONTEXT_IMPL_H_ +#ifndef CONTENT_RENDERER_LOADER_WEB_WORKER_FETCH_CONTEXT_IMPL_H_ +#define CONTENT_RENDERER_LOADER_WEB_WORKER_FETCH_CONTEXT_IMPL_H_ + +#include <memory> +#include <string> #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_preferences.h" #include "ipc/ipc_message.h" #include "mojo/public/cpp/bindings/binding.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" #include "third_party/blink/public/mojom/blob/blob_registry.mojom.h" #include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h" #include "third_party/blink/public/platform/web_application_cache_host.h" @@ -29,15 +34,19 @@ class ThreadSafeSender; class URLLoaderThrottleProvider; class WebSocketHandshakeThrottleProvider; -// This class is used while fetching resource requests on workers (dedicated +// This class is used for fetching resource requests from workers (dedicated // worker and shared worker). This class is created on the main thread and // passed to the worker thread. This class is not used for service workers. For // service workers, ServiceWorkerFetchContextImpl class is used instead. -class CONTENT_EXPORT WorkerFetchContextImpl +class CONTENT_EXPORT WebWorkerFetchContextImpl : public blink::WebWorkerFetchContext, public mojom::ServiceWorkerWorkerClient { public: - // |loader_factory_info| is used for regular loading by the worker. + // |service_worker_client_request| is bound to |this| to receive + // OnControllerChanged() notifications. + // |service_worker_worker_client_registry_info| is a host pointer to register + // a new ServiceWorkerWorkerClient, which is needed when creating a nested + // worker. |loader_factory_info| is used for regular loading by the worker. // // S13nServiceWorker: // If the worker is controlled by a service worker, this class makes another @@ -51,8 +60,11 @@ class CONTENT_EXPORT WorkerFetchContextImpl // |fallback_factory_info| might not be simply the direct network factory, // because it might additionally support non-NetworkService schemes (e.g., // chrome-extension://). - WorkerFetchContextImpl( + WebWorkerFetchContextImpl( + RendererPreferences renderer_preferences, mojom::ServiceWorkerWorkerClientRequest service_worker_client_request, + mojom::ServiceWorkerWorkerClientRegistryPtrInfo + service_worker_worker_client_registry_info, mojom::ServiceWorkerContainerHostPtrInfo service_worker_container_host_info, std::unique_ptr<network::SharedURLLoaderFactoryInfo> loader_factory_info, @@ -62,8 +74,8 @@ class CONTENT_EXPORT WorkerFetchContextImpl std::unique_ptr<WebSocketHandshakeThrottleProvider> websocket_handshake_throttle_provider, ThreadSafeSender* thread_safe_sender, - scoped_refptr<base::SingleThreadTaskRunner> io_task_runner); - ~WorkerFetchContextImpl() override; + std::unique_ptr<service_manager::Connector> service_manager_connection); + ~WebWorkerFetchContextImpl() override; // blink::WebWorkerFetchContext implementation: std::unique_ptr<blink::WebWorkerFetchContext> CloneForNestedWorker() override; @@ -73,7 +85,8 @@ class CONTENT_EXPORT WorkerFetchContextImpl std::unique_ptr<blink::WebURLLoaderFactory> WrapURLLoaderFactory( mojo::ScopedMessagePipeHandle url_loader_factory_handle) override; void WillSendRequest(blink::WebURLRequest&) override; - bool IsControlledByServiceWorker() const override; + blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker() + const override; void SetIsOnSubframe(bool) override; bool IsOnSubframe() const override; blink::WebURL SiteForCookies() const override; @@ -91,13 +104,16 @@ class CONTENT_EXPORT WorkerFetchContextImpl CreateWebSocketHandshakeThrottle() override; // mojom::ServiceWorkerWorkerClient implementation: - void SetControllerServiceWorker(int64_t controller_version_id) override; + void OnControllerChanged(blink::mojom::ControllerServiceWorkerMode) override; - // Sets the fetch context status copied from the frame; the parent frame for a - // dedicated worker, the main frame of the shadow page for a shared worker. + // Sets the fetch context status copied from a frame. For dedicated workers, + // it's copied from the ancestor frame (directly for non-nested workers, or + // indirectly via its parent worker for nested workers). For shared workers, + // it's copied from the shadow page. void set_service_worker_provider_id(int id); - void set_is_controlled_by_service_worker(bool flag); - void set_parent_frame_id(int id); + void set_is_controlled_by_service_worker( + blink::mojom::ControllerServiceWorkerMode mode); + void set_ancestor_frame_id(int id); 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/ @@ -121,20 +137,26 @@ class CONTENT_EXPORT WorkerFetchContextImpl void ResetServiceWorkerURLLoaderFactory(); mojo::Binding<mojom::ServiceWorkerWorkerClient> binding_; + mojom::ServiceWorkerWorkerClientRegistryPtr + service_worker_worker_client_registry_; // Bound to |this| on the worker thread. mojom::ServiceWorkerWorkerClientRequest service_worker_client_request_; + // Consumed on the worker thread to create + // |service_worker_worker_client_registry_|. + mojom::ServiceWorkerWorkerClientRegistryPtrInfo + service_worker_worker_client_registry_info_; // Consumed on the worker thread to create |service_worker_container_host_|. mojom::ServiceWorkerContainerHostPtrInfo service_worker_container_host_info_; // Consumed on the worker thread to create |loader_factory_|. std::unique_ptr<network::SharedURLLoaderFactoryInfo> loader_factory_info_; // Consumed on the worker thread to create |fallback_factory_|. std::unique_ptr<network::SharedURLLoaderFactoryInfo> fallback_factory_info_; - // Consumed on the worker thread to create |blob_registry_|. - blink::mojom::BlobRegistryPtrInfo blob_registry_ptr_info_; int service_worker_provider_id_ = kInvalidServiceWorkerProviderId; - bool is_controlled_by_service_worker_ = false; + blink::mojom::ControllerServiceWorkerMode is_controlled_by_service_worker_ = + blink::mojom::ControllerServiceWorkerMode::kNoController; + // S13nServiceWorker: // Initialized on the worker thread when InitializeOnWorkerThread() is called. mojom::ServiceWorkerContainerHostPtr service_worker_container_host_; @@ -165,20 +187,23 @@ class CONTENT_EXPORT WorkerFetchContextImpl scoped_refptr<base::RefCountedData<blink::mojom::BlobRegistryPtr>> blob_registry_; - // Updated when mojom::ServiceWorkerWorkerClient::SetControllerServiceWorker() - // is called from the browser process via mojo IPC. - int controller_version_id_ = blink::mojom::kInvalidServiceWorkerVersionId; - scoped_refptr<ThreadSafeSender> thread_safe_sender_; std::unique_ptr<blink::WebDocumentSubresourceFilter::Builder> subresource_filter_builder_; + // For dedicated workers, this is the ancestor frame (the parent frame for + // non-nested workers, the closest ancestor for nested workers). For shared + // workers, this is the shadow page. bool is_on_sub_frame_ = false; - int parent_frame_id_ = MSG_ROUTING_NONE; + int ancestor_frame_id_ = MSG_ROUTING_NONE; 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_; + // This is owned by ThreadedMessagingProxyBase on the main thread. base::WaitableEvent* terminate_sync_load_event_ = nullptr; @@ -190,9 +215,9 @@ class CONTENT_EXPORT WorkerFetchContextImpl std::unique_ptr<WebSocketHandshakeThrottleProvider> websocket_handshake_throttle_provider_; - scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; + std::unique_ptr<service_manager::Connector> service_manager_connection_; }; } // namespace content -#endif // CONTENT_RENDERER_SERVICE_WORKER_WORKER_FETCH_CONTEXT_IMPL_H_ +#endif // CONTENT_RENDERER_LOADER_WEB_WORKER_FETCH_CONTEXT_IMPL_H_ diff --git a/chromium/content/renderer/low_memory_mode_controller.cc b/chromium/content/renderer/low_memory_mode_controller.cc new file mode 100644 index 00000000000..a3e6fc43fb5 --- /dev/null +++ b/chromium/content/renderer/low_memory_mode_controller.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/renderer/low_memory_mode_controller.h" + +#include "base/metrics/histogram_macros.h" +#include "third_party/blink/public/web/blink.h" +#include "v8/include/v8.h" + +namespace content { + +LowMemoryModeController::LowMemoryModeController() = default; + +LowMemoryModeController::~LowMemoryModeController() = default; + +void LowMemoryModeController::OnFrameCreated(bool is_main_frame) { + if (is_main_frame) { + // If the process is gaining its first main frame, disable memory + // savings mode. + if (++main_frame_count_ == 1) { + Disable(); + } + } else if (main_frame_count_ == 0) { + // The process is getting a new frame and none is main, enable + // memory savings mode (if not already on). + Enable(); + } +} + +void LowMemoryModeController::OnFrameDestroyed(bool is_main_frame) { + // If the process is losing its last main frame, enable memory + // savings mode. + if (is_main_frame && --main_frame_count_ == 0) { + Enable(); + } +} + +void LowMemoryModeController::Enable() { + if (is_enabled_) + return; + + blink::MainThreadIsolate()->EnableMemorySavingsMode(); + RecordHistogram(true); + is_enabled_ = true; +} + +void LowMemoryModeController::Disable() { + if (!is_enabled_) + return; + + blink::MainThreadIsolate()->DisableMemorySavingsMode(); + RecordHistogram(false); + is_enabled_ = false; +} + +void LowMemoryModeController::RecordHistogram(bool enabled) { + UMA_HISTOGRAM_BOOLEAN("SiteIsolation.LowMemoryMode.Transition", enabled); +} + +} // namespace content diff --git a/chromium/content/renderer/low_memory_mode_controller.h b/chromium/content/renderer/low_memory_mode_controller.h new file mode 100644 index 00000000000..2038a68600c --- /dev/null +++ b/chromium/content/renderer/low_memory_mode_controller.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_RENDERER_LOW_MEMORY_MODE_CONTROLLER_H_ +#define CONTENT_RENDERER_LOW_MEMORY_MODE_CONTROLLER_H_ + +#include <memory> + +#include "base/macros.h" +#include "content/common/content_export.h" + +namespace content { + +// The LowMemoryModeController manages for a renderer process the blink +// main thread isolate's memory savings mode state. This is only enabled +// if the V8LowMemoryModeForNonMainFrames feature and --site-per-process +// are enabled. +// +// When a process only contains subframes, the memory saving mode is +// enabled. If a main frame is later created, then the mode is disabled +// for the duration of the main frame's existence. +// +// The default state after initialization is to not enable low memory mode. +class CONTENT_EXPORT LowMemoryModeController { + public: + LowMemoryModeController(); + ~LowMemoryModeController(); + + // Notifies the controller that a frame has either been created or + // destroyed. A transition to the memory saving mode may occur as a result. + void OnFrameCreated(bool is_main_frame); + void OnFrameDestroyed(bool is_main_frame); + + bool is_enabled() const { return is_enabled_; } + + private: + // Puts the main thread isolate into memory savings mode if it is not + // currently enabled. + void Enable(); + + // Takes the main thread isolate out of memory savings mode if it is + // currently enabled. + void Disable(); + + // Records an UMA histogram marking an Enabled->Disabled state transition, + // or vice versa. + void RecordHistogram(bool enabled); + + int main_frame_count_ = 0; + bool is_enabled_ = false; + + DISALLOW_COPY_AND_ASSIGN(LowMemoryModeController); +}; + +} // namespace content + +#endif // CONTENT_RENDERER_LOW_MEMORY_MODE_CONTROLLER_H_ diff --git a/chromium/content/renderer/low_memory_mode_controller_unittest.cc b/chromium/content/renderer/low_memory_mode_controller_unittest.cc new file mode 100644 index 00000000000..00f0fa81f45 --- /dev/null +++ b/chromium/content/renderer/low_memory_mode_controller_unittest.cc @@ -0,0 +1,86 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/renderer/low_memory_mode_controller.h" + +#include "base/test/metrics/histogram_tester.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace content { +namespace { + +class LowMemoryModeControllerTest : public testing::Test { + public: + LowMemoryModeController* controller() { return &controller_; } + + void ExpectTransitionCount(int enabled_count, int disabled_count) { + static constexpr char kHistogram[] = + "SiteIsolation.LowMemoryMode.Transition"; + histogram_tester_.ExpectBucketCount(kHistogram, true, enabled_count); + histogram_tester_.ExpectBucketCount(kHistogram, false, disabled_count); + histogram_tester_.ExpectTotalCount(kHistogram, + enabled_count + disabled_count); + } + + private: + base::HistogramTester histogram_tester_; + LowMemoryModeController controller_; +}; + +TEST_F(LowMemoryModeControllerTest, CreateMainFrames) { + EXPECT_FALSE(controller()->is_enabled()); + + controller()->OnFrameCreated(true); + EXPECT_FALSE(controller()->is_enabled()); + + controller()->OnFrameCreated(true); + EXPECT_FALSE(controller()->is_enabled()); + + controller()->OnFrameDestroyed(true); + EXPECT_FALSE(controller()->is_enabled()); + + controller()->OnFrameDestroyed(true); + EXPECT_TRUE(controller()->is_enabled()); + + ExpectTransitionCount(1, 0); +} + +TEST_F(LowMemoryModeControllerTest, MainFrameAddSubframe) { + EXPECT_FALSE(controller()->is_enabled()); + + controller()->OnFrameCreated(true); + EXPECT_FALSE(controller()->is_enabled()); + + controller()->OnFrameCreated(false); + EXPECT_FALSE(controller()->is_enabled()); + + controller()->OnFrameDestroyed(true); + EXPECT_TRUE(controller()->is_enabled()); + + controller()->OnFrameDestroyed(false); + EXPECT_TRUE(controller()->is_enabled()); + + ExpectTransitionCount(1, 0); +} + +TEST_F(LowMemoryModeControllerTest, SubFrameAddMainFrame) { + EXPECT_FALSE(controller()->is_enabled()); + + controller()->OnFrameCreated(false); + EXPECT_TRUE(controller()->is_enabled()); + + controller()->OnFrameCreated(true); + EXPECT_FALSE(controller()->is_enabled()); + + controller()->OnFrameDestroyed(true); + EXPECT_TRUE(controller()->is_enabled()); + + controller()->OnFrameDestroyed(false); + EXPECT_TRUE(controller()->is_enabled()); + + ExpectTransitionCount(2, 1); +} + +} // namespace +} // namespace content diff --git a/chromium/content/renderer/manifest/manifest_parser.cc b/chromium/content/renderer/manifest/manifest_parser.cc index 21f715cbf0d..22fba6ba3bd 100644 --- a/chromium/content/renderer/manifest/manifest_parser.cc +++ b/chromium/content/renderer/manifest/manifest_parser.cc @@ -277,13 +277,13 @@ std::vector<gfx::Size> ManifestParser::ParseIconSizes( return sizes; } -std::vector<blink::Manifest::Icon::IconPurpose> +std::vector<blink::Manifest::ImageResource::Purpose> ManifestParser::ParseIconPurpose(const base::DictionaryValue& icon) { base::NullableString16 purpose_str = ParseString(icon, "purpose", NoTrim); - std::vector<blink::Manifest::Icon::IconPurpose> purposes; + std::vector<blink::Manifest::ImageResource::Purpose> purposes; if (purpose_str.is_null()) { - purposes.push_back(blink::Manifest::Icon::IconPurpose::ANY); + purposes.push_back(blink::Manifest::ImageResource::Purpose::ANY); return purposes; } @@ -292,9 +292,9 @@ ManifestParser::ParseIconPurpose(const base::DictionaryValue& icon) { base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); for (const base::string16& keyword : keywords) { if (base::LowerCaseEqualsASCII(keyword, "any")) { - purposes.push_back(blink::Manifest::Icon::IconPurpose::ANY); + purposes.push_back(blink::Manifest::ImageResource::Purpose::ANY); } else if (base::LowerCaseEqualsASCII(keyword, "badge")) { - purposes.push_back(blink::Manifest::Icon::IconPurpose::BADGE); + purposes.push_back(blink::Manifest::ImageResource::Purpose::BADGE); } else { AddErrorInfo( "found icon with invalid purpose. " @@ -303,15 +303,15 @@ ManifestParser::ParseIconPurpose(const base::DictionaryValue& icon) { } if (purposes.empty()) { - purposes.push_back(blink::Manifest::Icon::IconPurpose::ANY); + purposes.push_back(blink::Manifest::ImageResource::Purpose::ANY); } return purposes; } -std::vector<blink::Manifest::Icon> ManifestParser::ParseIcons( +std::vector<blink::Manifest::ImageResource> ManifestParser::ParseIcons( const base::DictionaryValue& dictionary) { - std::vector<blink::Manifest::Icon> icons; + std::vector<blink::Manifest::ImageResource> icons; if (!dictionary.HasKey("icons")) return icons; @@ -326,7 +326,7 @@ std::vector<blink::Manifest::Icon> ManifestParser::ParseIcons( if (!icons_list->GetDictionary(i, &icon_dictionary)) continue; - blink::Manifest::Icon icon; + blink::Manifest::ImageResource icon; icon.src = ParseIconSrc(*icon_dictionary); // An icon MUST have a valid src. If it does not, it MUST be ignored. if (!icon.src.is_valid()) diff --git a/chromium/content/renderer/manifest/manifest_parser.h b/chromium/content/renderer/manifest/manifest_parser.h index a456754390f..69551b8c3f3 100644 --- a/chromium/content/renderer/manifest/manifest_parser.h +++ b/chromium/content/renderer/manifest/manifest_parser.h @@ -146,14 +146,14 @@ class CONTENT_EXPORT ManifestParser { // Returns a vector of Manifest::Icon::IconPurpose with the successfully // parsed icon purposes, and a vector with Manifest::Icon::IconPurpose::Any if // the parsing failed. - std::vector<blink::Manifest::Icon::IconPurpose> ParseIconPurpose( + std::vector<blink::Manifest::ImageResource::Purpose> ParseIconPurpose( const base::DictionaryValue& icon); // Parses the 'icons' field of a Manifest, as defined in: // https://w3c.github.io/manifest/#dfn-steps-for-processing-an-array-of-images // Returns a vector of Manifest::Icon with the successfully parsed icons, if // any. An empty vector if the field was not present or empty. - std::vector<blink::Manifest::Icon> ParseIcons( + std::vector<blink::Manifest::ImageResource> ParseIcons( const base::DictionaryValue& dictionary); // Parses the 'url_template' field of a Share Target, as defined in: diff --git a/chromium/content/renderer/manifest/manifest_parser_unittest.cc b/chromium/content/renderer/manifest/manifest_parser_unittest.cc index 016020e6f17..a47995053f4 100644 --- a/chromium/content/renderer/manifest/manifest_parser_unittest.cc +++ b/chromium/content/renderer/manifest/manifest_parser_unittest.cc @@ -931,7 +931,7 @@ TEST_F(ManifestParserTest, IconPurposeParseRules) { ParseManifest("{ \"icons\": [ {\"src\": \"\" } ] }"); EXPECT_EQ(manifest.icons[0].purpose.size(), 1u); EXPECT_EQ(manifest.icons[0].purpose[0], - blink::Manifest::Icon::IconPurpose::ANY); + blink::Manifest::ImageResource::Purpose::ANY); EXPECT_EQ(0u, GetErrorCount()); } @@ -943,7 +943,7 @@ TEST_F(ManifestParserTest, IconPurposeParseRules) { "\"purpose\": 42 } ] }"); EXPECT_EQ(manifest.icons[0].purpose.size(), 1u); EXPECT_EQ(manifest.icons[0].purpose[0], - blink::Manifest::Icon::IconPurpose::ANY); + blink::Manifest::ImageResource::Purpose::ANY); ASSERT_EQ(1u, GetErrorCount()); EXPECT_EQ(kPurposeParseStringError, errors()[0]); } @@ -956,7 +956,7 @@ TEST_F(ManifestParserTest, IconPurposeParseRules) { "\"purpose\": {} } ] }"); EXPECT_EQ(manifest.icons[0].purpose.size(), 1u); EXPECT_EQ(manifest.icons[0].purpose[0], - blink::Manifest::Icon::IconPurpose::ANY); + blink::Manifest::ImageResource::Purpose::ANY); ASSERT_EQ(1u, GetErrorCount()); EXPECT_EQ(kPurposeParseStringError, errors()[0]); } @@ -968,9 +968,9 @@ TEST_F(ManifestParserTest, IconPurposeParseRules) { "\"purpose\": \"Any Badge\" } ] }"); ASSERT_EQ(manifest.icons[0].purpose.size(), 2u); EXPECT_EQ(manifest.icons[0].purpose[0], - blink::Manifest::Icon::IconPurpose::ANY); + blink::Manifest::ImageResource::Purpose::ANY); EXPECT_EQ(manifest.icons[0].purpose[1], - blink::Manifest::Icon::IconPurpose::BADGE); + blink::Manifest::ImageResource::Purpose::BADGE); EXPECT_EQ(0u, GetErrorCount()); } @@ -981,9 +981,9 @@ TEST_F(ManifestParserTest, IconPurposeParseRules) { "\"purpose\": \" Any Badge \" } ] }"); ASSERT_EQ(manifest.icons[0].purpose.size(), 2u); EXPECT_EQ(manifest.icons[0].purpose[0], - blink::Manifest::Icon::IconPurpose::ANY); + blink::Manifest::ImageResource::Purpose::ANY); EXPECT_EQ(manifest.icons[0].purpose[1], - blink::Manifest::Icon::IconPurpose::BADGE); + blink::Manifest::ImageResource::Purpose::BADGE); EXPECT_EQ(0u, GetErrorCount()); } @@ -994,9 +994,9 @@ TEST_F(ManifestParserTest, IconPurposeParseRules) { "\"purpose\": \"badge badge\" } ] }"); ASSERT_EQ(manifest.icons[0].purpose.size(), 2u); EXPECT_EQ(manifest.icons[0].purpose[0], - blink::Manifest::Icon::IconPurpose::BADGE); + blink::Manifest::ImageResource::Purpose::BADGE); EXPECT_EQ(manifest.icons[0].purpose[1], - blink::Manifest::Icon::IconPurpose::BADGE); + blink::Manifest::ImageResource::Purpose::BADGE); EXPECT_EQ(0u, GetErrorCount()); } @@ -1007,7 +1007,7 @@ TEST_F(ManifestParserTest, IconPurposeParseRules) { "\"purpose\": \"badge notification\" } ] }"); ASSERT_EQ(manifest.icons[0].purpose.size(), 1u); EXPECT_EQ(manifest.icons[0].purpose[0], - blink::Manifest::Icon::IconPurpose::BADGE); + blink::Manifest::ImageResource::Purpose::BADGE); ASSERT_EQ(1u, GetErrorCount()); EXPECT_EQ(kPurposeInvalidValueError, errors()[0]); } @@ -1019,7 +1019,7 @@ TEST_F(ManifestParserTest, IconPurposeParseRules) { "\"purpose\": \"notification\" } ] }"); ASSERT_EQ(manifest.icons[0].purpose.size(), 1u); EXPECT_EQ(manifest.icons[0].purpose[0], - blink::Manifest::Icon::IconPurpose::ANY); + blink::Manifest::ImageResource::Purpose::ANY); ASSERT_EQ(1u, GetErrorCount()); EXPECT_EQ(kPurposeInvalidValueError, errors()[0]); } diff --git a/chromium/content/renderer/media/android/renderer_media_player_manager.cc b/chromium/content/renderer/media/android/renderer_media_player_manager.cc index 72ae5491082..70fd8ec9954 100644 --- a/chromium/content/renderer/media/android/renderer_media_player_manager.cc +++ b/chromium/content/renderer/media/android/renderer_media_player_manager.cc @@ -248,10 +248,6 @@ void RendererMediaPlayerManager::OnRemoteRouteAvailabilityChanged( player->OnRemoteRouteAvailabilityChanged(availability); } -void RendererMediaPlayerManager::EnterFullscreen(int player_id) { - Send(new MediaPlayerHostMsg_EnterFullscreen(routing_id(), player_id)); -} - int RendererMediaPlayerManager::RegisterMediaPlayer( media::RendererMediaPlayerInterface* player) { media_players_[next_media_player_id_] = player; diff --git a/chromium/content/renderer/media/android/renderer_media_player_manager.h b/chromium/content/renderer/media/android/renderer_media_player_manager.h index d8b2a58d6f0..08c4116168e 100644 --- a/chromium/content/renderer/media/android/renderer_media_player_manager.h +++ b/chromium/content/renderer/media/android/renderer_media_player_manager.h @@ -78,9 +78,6 @@ class RendererMediaPlayerManager : // Requests stopping remote playback void RequestRemotePlaybackStop(int player_id) override; - // Requests the player to enter fullscreen. - void EnterFullscreen(int player_id); - // Registers and unregisters a WebMediaPlayerAndroid object. int RegisterMediaPlayer(media::RendererMediaPlayerInterface* player) override; void UnregisterMediaPlayer(int player_id) override; diff --git a/chromium/content/renderer/media/android/renderer_surface_view_manager.cc b/chromium/content/renderer/media/android/renderer_surface_view_manager.cc deleted file mode 100644 index 0402460b7e6..00000000000 --- a/chromium/content/renderer/media/android/renderer_surface_view_manager.cc +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/media/android/renderer_surface_view_manager.h" - -#include "content/common/media/surface_view_manager_messages_android.h" -#include "ipc/ipc_message_macros.h" -#include "ui/gfx/geometry/size.h" - -namespace content { - -RendererSurfaceViewManager::RendererSurfaceViewManager( - RenderFrame* render_frame) - : RenderFrameObserver(render_frame) {} - -RendererSurfaceViewManager::~RendererSurfaceViewManager() {} - -bool RendererSurfaceViewManager::OnMessageReceived(const IPC::Message& msg) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(RendererSurfaceViewManager, msg) - IPC_MESSAGE_HANDLER(SurfaceViewManagerMsg_FullscreenSurfaceCreated, - OnFullscreenSurfaceCreated) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled; -} - -void RendererSurfaceViewManager::CreateFullscreenSurface( - const gfx::Size& video_natural_size, - const media::SurfaceCreatedCB& surface_created_cb) { - DCHECK(!surface_created_cb.is_null()); - pending_surface_created_cb_ = surface_created_cb; - Send(new SurfaceViewManagerHostMsg_CreateFullscreenSurface( - routing_id(), video_natural_size)); -} - -void RendererSurfaceViewManager::NaturalSizeChanged(const gfx::Size& size) { - DVLOG(3) << __func__ << ": size: " << size.ToString(); - Send(new SurfaceViewManagerHostMsg_NaturalSizeChanged(routing_id(), size)); -} - -void RendererSurfaceViewManager::OnFullscreenSurfaceCreated(int surface_id) { - DVLOG(3) << __func__ << ": surface_id: " << surface_id; - if (!pending_surface_created_cb_.is_null()) { - pending_surface_created_cb_.Run(surface_id); - pending_surface_created_cb_.Reset(); - } -} - -void RendererSurfaceViewManager::OnDestruct() { - delete this; -} - -} // namespace content diff --git a/chromium/content/renderer/media/android/renderer_surface_view_manager.h b/chromium/content/renderer/media/android/renderer_surface_view_manager.h deleted file mode 100644 index f2918f37877..00000000000 --- a/chromium/content/renderer/media/android/renderer_surface_view_manager.h +++ /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. - -#ifndef CONTENT_RENDERER_MEDIA_ANDROID_RENDERER_SURFACE_VIEW_MANAGER_H_ -#define CONTENT_RENDERER_MEDIA_ANDROID_RENDERER_SURFACE_VIEW_MANAGER_H_ - -#include "base/callback.h" -#include "content/common/content_export.h" -#include "content/public/renderer/render_frame_observer.h" -#include "media/base/surface_manager.h" -#include "ui/gfx/geometry/size.h" - -namespace content { - -// RendererSurfaceViewManager creates delegates requests for video SurfaceViews -// to BrowserSurfaceViewManager. The returned surface ids may be invalidated -// at any time (e.g., when the app is backgrounded), so clients should handle -// this gracefully. It should be created and used on a single thread only. -class CONTENT_EXPORT RendererSurfaceViewManager : public media::SurfaceManager, - public RenderFrameObserver { - public: - explicit RendererSurfaceViewManager(RenderFrame* render_frame); - ~RendererSurfaceViewManager() override; - - // RenderFrameObserver override. - bool OnMessageReceived(const IPC::Message& msg) override; - - // SurfaceManager overrides. - void CreateFullscreenSurface( - const gfx::Size& video_natural_size, - const media::SurfaceCreatedCB& surface_created_cb) override; - void NaturalSizeChanged(const gfx::Size& size) override; - - private: - // RenderFrameObserver implementation. - void OnDestruct() override; - - void OnFullscreenSurfaceCreated(int surface_id); - - // Set when a surface request is in progress. - media::SurfaceCreatedCB pending_surface_created_cb_; - - DISALLOW_COPY_AND_ASSIGN(RendererSurfaceViewManager); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_ANDROID_RENDERER_SURFACE_VIEW_MANAGER_H_ diff --git a/chromium/content/renderer/media/android/stream_texture_factory.cc b/chromium/content/renderer/media/android/stream_texture_factory.cc index 5e982601dab..86b022e7e59 100644 --- a/chromium/content/renderer/media/android/stream_texture_factory.cc +++ b/chromium/content/renderer/media/android/stream_texture_factory.cc @@ -119,7 +119,6 @@ unsigned StreamTextureFactory::CreateStreamTexture( *texture_id = 0; *texture_mailbox = gpu::Mailbox(); } else { - gl->GenMailboxCHROMIUM(texture_mailbox->name); gl->ProduceTextureDirectCHROMIUM(*texture_id, texture_mailbox->name); } return route_id; diff --git a/chromium/content/renderer/media/audio_device_factory.cc b/chromium/content/renderer/media/audio/audio_device_factory.cc index 52a260eb6fe..d20dbe3a5b0 100644 --- a/chromium/content/renderer/media/audio_device_factory.cc +++ b/chromium/content/renderer/media/audio/audio_device_factory.cc @@ -2,19 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/renderer/media/audio_device_factory.h" +#include "content/renderer/media/audio/audio_device_factory.h" #include <algorithm> #include "base/logging.h" #include "base/metrics/histogram_macros.h" +#include "base/threading/platform_thread.h" #include "build/build_config.h" #include "content/common/content_constants_internal.h" #include "content/common/media/renderer_audio_input_stream_factory.mojom.h" -#include "content/renderer/media/audio_input_ipc_factory.h" -#include "content/renderer/media/audio_output_ipc_factory.h" -#include "content/renderer/media/audio_renderer_mixer_manager.h" -#include "content/renderer/media/mojo_audio_input_ipc.h" +#include "content/renderer/media/audio/audio_input_ipc_factory.h" +#include "content/renderer/media/audio/audio_output_ipc_factory.h" +#include "content/renderer/media/audio/audio_renderer_mixer_manager.h" +#include "content/renderer/media/audio/mojo_audio_input_ipc.h" #include "content/renderer/render_frame_impl.h" #include "content/renderer/render_thread_impl.h" #include "media/audio/audio_input_device.h" @@ -168,7 +169,8 @@ AudioDeviceFactory::NewAudioCapturerSource(int render_frame_id, return base::MakeRefCounted<media::AudioInputDevice>( AudioInputIPCFactory::get()->CreateAudioInputIPC(render_frame_id, - session_id)); + session_id), + base::ThreadPriority::REALTIME_AUDIO); } // static diff --git a/chromium/content/renderer/media/audio_device_factory.h b/chromium/content/renderer/media/audio/audio_device_factory.h index 6184e7a0eca..d4f3704a70e 100644 --- a/chromium/content/renderer/media/audio_device_factory.h +++ b/chromium/content/renderer/media/audio/audio_device_factory.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_RENDERER_MEDIA_AUDIO_DEVICE_FACTORY_H_ -#define CONTENT_RENDERER_MEDIA_AUDIO_DEVICE_FACTORY_H_ +#ifndef CONTENT_RENDERER_MEDIA_AUDIO_AUDIO_DEVICE_FACTORY_H_ +#define CONTENT_RENDERER_MEDIA_AUDIO_AUDIO_DEVICE_FACTORY_H_ #include <string> @@ -142,4 +142,4 @@ class CONTENT_EXPORT AudioDeviceFactory { } // namespace content -#endif // CONTENT_RENDERER_MEDIA_AUDIO_DEVICE_FACTORY_H_ +#endif // CONTENT_RENDERER_MEDIA_AUDIO_AUDIO_DEVICE_FACTORY_H_ diff --git a/chromium/content/renderer/media/audio_input_ipc_factory.cc b/chromium/content/renderer/media/audio/audio_input_ipc_factory.cc index 7cafd730916..f301aace7c4 100644 --- a/chromium/content/renderer/media/audio_input_ipc_factory.cc +++ b/chromium/content/renderer/media/audio/audio_input_ipc_factory.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/renderer/media/audio_input_ipc_factory.h" +#include "content/renderer/media/audio/audio_input_ipc_factory.h" #include <utility> @@ -10,7 +10,7 @@ #include "base/sequenced_task_runner.h" #include "base/single_thread_task_runner.h" #include "content/common/media/renderer_audio_input_stream_factory.mojom.h" -#include "content/renderer/media/mojo_audio_input_ipc.h" +#include "content/renderer/media/audio/mojo_audio_input_ipc.h" #include "content/renderer/render_frame_impl.h" #include "services/service_manager/public/cpp/interface_provider.h" diff --git a/chromium/content/renderer/media/audio_input_ipc_factory.h b/chromium/content/renderer/media/audio/audio_input_ipc_factory.h index 7921cb74635..ea3956945f3 100644 --- a/chromium/content/renderer/media/audio_input_ipc_factory.h +++ b/chromium/content/renderer/media/audio/audio_input_ipc_factory.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_RENDERER_MEDIA_AUDIO_INPUT_IPC_FACTORY_H_ -#define CONTENT_RENDERER_MEDIA_AUDIO_INPUT_IPC_FACTORY_H_ +#ifndef CONTENT_RENDERER_MEDIA_AUDIO_AUDIO_INPUT_IPC_FACTORY_H_ +#define CONTENT_RENDERER_MEDIA_AUDIO_AUDIO_INPUT_IPC_FACTORY_H_ #include <memory> @@ -57,4 +57,4 @@ class CONTENT_EXPORT AudioInputIPCFactory { } // namespace content -#endif // CONTENT_RENDERER_MEDIA_AUDIO_INPUT_IPC_FACTORY_H_ +#endif // CONTENT_RENDERER_MEDIA_AUDIO_AUDIO_INPUT_IPC_FACTORY_H_ diff --git a/chromium/content/renderer/media/audio_output_ipc_factory.cc b/chromium/content/renderer/media/audio/audio_output_ipc_factory.cc index 829d85a8e6c..4bcab6233fd 100644 --- a/chromium/content/renderer/media/audio_output_ipc_factory.cc +++ b/chromium/content/renderer/media/audio/audio_output_ipc_factory.cc @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/renderer/media/audio_output_ipc_factory.h" +#include "content/renderer/media/audio/audio_output_ipc_factory.h" #include <utility> #include "base/logging.h" #include "base/single_thread_task_runner.h" -#include "content/renderer/media/mojo_audio_output_ipc.h" +#include "content/renderer/media/audio/mojo_audio_output_ipc.h" #include "services/service_manager/public/cpp/interface_provider.h" namespace content { diff --git a/chromium/content/renderer/media/audio_output_ipc_factory.h b/chromium/content/renderer/media/audio/audio_output_ipc_factory.h index 6cb588204f5..0f87cfdd9b0 100644 --- a/chromium/content/renderer/media/audio_output_ipc_factory.h +++ b/chromium/content/renderer/media/audio/audio_output_ipc_factory.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_RENDERER_MEDIA_AUDIO_OUTPUT_IPC_FACTORY_H_ -#define CONTENT_RENDERER_MEDIA_AUDIO_OUTPUT_IPC_FACTORY_H_ +#ifndef CONTENT_RENDERER_MEDIA_AUDIO_AUDIO_OUTPUT_IPC_FACTORY_H_ +#define CONTENT_RENDERER_MEDIA_AUDIO_AUDIO_OUTPUT_IPC_FACTORY_H_ #include <memory> @@ -89,4 +89,4 @@ class CONTENT_EXPORT AudioOutputIPCFactory { } // namespace content -#endif // CONTENT_RENDERER_MEDIA_AUDIO_OUTPUT_IPC_FACTORY_H_ +#endif // CONTENT_RENDERER_MEDIA_AUDIO_AUDIO_OUTPUT_IPC_FACTORY_H_ diff --git a/chromium/content/renderer/media/audio_output_ipc_factory_unittest.cc b/chromium/content/renderer/media/audio/audio_output_ipc_factory_unittest.cc index 6f675a57444..cefb2a3c533 100644 --- a/chromium/content/renderer/media/audio_output_ipc_factory_unittest.cc +++ b/chromium/content/renderer/media/audio/audio_output_ipc_factory_unittest.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/renderer/media/audio_output_ipc_factory.h" +#include "content/renderer/media/audio/audio_output_ipc_factory.h" #include <string> #include <utility> @@ -72,7 +72,7 @@ class FakeAudioOutputIPCDelegate : public media::AudioOutputIPCDelegate { void OnDeviceAuthorized(media::OutputDeviceStatus device_status, const media::AudioParameters& output_params, const std::string& matched_device_id) override {} - void OnStreamCreated(base::SharedMemoryHandle handle, + void OnStreamCreated(base::UnsafeSharedMemoryRegion region, base::SyncSocket::Handle socket_handle, bool playing_automatically) override {} void OnIPCClosed() override {} diff --git a/chromium/content/renderer/media/audio_renderer_mixer_manager.cc b/chromium/content/renderer/media/audio/audio_renderer_mixer_manager.cc index 942553572ad..b457f7ce47c 100644 --- a/chromium/content/renderer/media/audio_renderer_mixer_manager.cc +++ b/chromium/content/renderer/media/audio/audio_renderer_mixer_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 "content/renderer/media/audio_renderer_mixer_manager.h" +#include "content/renderer/media/audio/audio_renderer_mixer_manager.h" #include <algorithm> #include <string> @@ -14,7 +14,7 @@ #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "build/build_config.h" -#include "content/renderer/media/audio_renderer_sink_cache.h" +#include "content/renderer/media/audio/audio_renderer_sink_cache.h" #include "media/audio/audio_device_description.h" #include "media/base/audio_renderer_mixer.h" #include "media/base/audio_renderer_mixer_input.h" @@ -90,6 +90,9 @@ media::AudioParameters GetMixerOutputParams( if (input_params.channel_layout() == media::CHANNEL_LAYOUT_DISCRETE) params.set_channels_for_discrete(input_params.channels()); + // Specify the effects info the passed to the browser side. + params.set_effects(input_params.effects()); + // Specify the latency info to be passed to the browser side. params.set_latency_tag(latency); return params; @@ -168,9 +171,6 @@ media::AudioRendererMixer* AudioRendererMixerManager::GetMixer( media::AudioLatency::LatencyType latency, const std::string& device_id, media::OutputDeviceStatus* device_status) { - // Effects are not passed through to output creation, so ensure none are set. - DCHECK_EQ(input_params.effects(), media::AudioParameters::NO_EFFECTS); - const MixerKey key(source_render_frame_id, input_params, latency, device_id); base::AutoLock auto_lock(mixers_lock_); diff --git a/chromium/content/renderer/media/audio_renderer_mixer_manager.h b/chromium/content/renderer/media/audio/audio_renderer_mixer_manager.h index f7821b05759..be586bcd703 100644 --- a/chromium/content/renderer/media/audio_renderer_mixer_manager.h +++ b/chromium/content/renderer/media/audio/audio_renderer_mixer_manager.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_RENDERER_MEDIA_AUDIO_RENDERER_MIXER_MANAGER_H_ -#define CONTENT_RENDERER_MEDIA_AUDIO_RENDERER_MIXER_MANAGER_H_ +#ifndef CONTENT_RENDERER_MEDIA_AUDIO_AUDIO_RENDERER_MIXER_MANAGER_H_ +#define CONTENT_RENDERER_MEDIA_AUDIO_AUDIO_RENDERER_MIXER_MANAGER_H_ #include <bitset> #include <map> @@ -111,11 +111,13 @@ class CONTENT_EXPORT AudioRendererMixerManager // adding support for it. DCHECK_NE(media::AudioLatency::LATENCY_EXACT_MS, a.latency); - // Ignore effects(), format(), and frames_per_buffer(), these parameters - // do not affect mixer reuse. All AudioRendererMixer units disable FIFO, - // so frames_per_buffer() can be safely ignored. + // Ignore format(), and frames_per_buffer(), these parameters do not + // affect mixer reuse. All AudioRendererMixer units disable FIFO, so + // frames_per_buffer() can be safely ignored. if (a.params.channel_layout() != b.params.channel_layout()) return a.params.channel_layout() < b.params.channel_layout(); + if (a.params.effects() != b.params.effects()) + return a.params.effects() < b.params.effects(); if (media::AudioDeviceDescription::IsDefaultDevice(a.device_id) && media::AudioDeviceDescription::IsDefaultDevice(b.device_id)) { @@ -157,4 +159,4 @@ class CONTENT_EXPORT AudioRendererMixerManager } // namespace content -#endif // CONTENT_RENDERER_MEDIA_AUDIO_RENDERER_MIXER_MANAGER_H_ +#endif // CONTENT_RENDERER_MEDIA_AUDIO_AUDIO_RENDERER_MIXER_MANAGER_H_ diff --git a/chromium/content/renderer/media/audio_renderer_mixer_manager_unittest.cc b/chromium/content/renderer/media/audio/audio_renderer_mixer_manager_unittest.cc index bba7a3e8224..03e1a7d415f 100644 --- a/chromium/content/renderer/media/audio_renderer_mixer_manager_unittest.cc +++ b/chromium/content/renderer/media/audio/audio_renderer_mixer_manager_unittest.cc @@ -2,16 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/renderer/media/audio_renderer_mixer_manager.h" +#include "content/renderer/media/audio/audio_renderer_mixer_manager.h" #include <memory> #include "base/bind.h" -#include "build/build_config.h" #include "base/logging.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "content/renderer/media/audio_renderer_sink_cache.h" +#include "build/build_config.h" +#include "content/renderer/media/audio/audio_renderer_sink_cache.h" #include "media/audio/audio_device_description.h" #include "media/base/audio_parameters.h" #include "media/base/audio_renderer_mixer.h" @@ -536,6 +536,72 @@ TEST_F(AudioRendererMixerManagerTest, LatencyMixing) { EXPECT_EQ(0, mixer_count()); } +// Verify GetMixer() correctly deduplicate mixers basing on the effects +// requirements. +TEST_F(AudioRendererMixerManagerTest, EffectsMixing) { + EXPECT_CALL(*mock_sink_.get(), Start()).Times(3); + EXPECT_CALL(*mock_sink_.get(), Stop()).Times(3); + EXPECT_CALL(*this, ReleaseSinkPtr(mock_sink_.get())).Times(3); + + EXPECT_EQ(0, mixer_count()); + + media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, + kChannelLayout, kSampleRate, kBufferSize); + params.set_effects(1); + media::AudioRendererMixer* mixer1 = + GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK, + kDefaultDeviceId, nullptr); + ASSERT_TRUE(mixer1); + EXPECT_EQ(1, mixer_count()); + + media::AudioRendererMixer* mixer2 = + GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK, + kDefaultDeviceId, nullptr); + ASSERT_TRUE(mixer2); + EXPECT_EQ(mixer1, mixer2); // Same effects => same mixer. + EXPECT_EQ(1, mixer_count()); + + params.set_effects(2); + media::AudioRendererMixer* mixer3 = + GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK, + kDefaultDeviceId, nullptr); + ASSERT_TRUE(mixer3); + EXPECT_NE(mixer1, mixer3); + EXPECT_EQ(2, mixer_count()); // Another effects => another mixer. + + media::AudioRendererMixer* mixer4 = + GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK, + kDefaultDeviceId, nullptr); + EXPECT_EQ(mixer3, mixer4); + EXPECT_EQ(2, mixer_count()); // Same effects => same mixer. + + params.set_effects(3); + media::AudioRendererMixer* mixer5 = + GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK, + kDefaultDeviceId, nullptr); + ASSERT_TRUE(mixer5); + EXPECT_EQ(3, mixer_count()); // Another effects => another mixer. + + media::AudioRendererMixer* mixer6 = + GetMixer(kRenderFrameId, params, AudioLatency::LATENCY_PLAYBACK, + kDefaultDeviceId, nullptr); + EXPECT_EQ(mixer5, mixer6); + EXPECT_EQ(3, mixer_count()); // Same effects => same mixer. + + ReturnMixer(mixer1); + EXPECT_EQ(3, mixer_count()); + ReturnMixer(mixer2); + EXPECT_EQ(2, mixer_count()); + ReturnMixer(mixer3); + EXPECT_EQ(2, mixer_count()); + ReturnMixer(mixer4); + EXPECT_EQ(1, mixer_count()); + ReturnMixer(mixer5); + EXPECT_EQ(1, mixer_count()); + ReturnMixer(mixer6); + EXPECT_EQ(0, mixer_count()); +} + // Verify output bufer size of the mixer is correctly adjusted for Playback // latency. TEST_F(AudioRendererMixerManagerTest, MixerParamsLatencyPlayback) { diff --git a/chromium/content/renderer/media/audio_renderer_sink_cache.h b/chromium/content/renderer/media/audio/audio_renderer_sink_cache.h index 4a06a3fc0c6..598e023d0c8 100644 --- a/chromium/content/renderer/media/audio_renderer_sink_cache.h +++ b/chromium/content/renderer/media/audio/audio_renderer_sink_cache.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_RENDERER_MEDIA_AUDIO_RENDERER_SINK_CACHE_H_ -#define CONTENT_RENDERER_MEDIA_AUDIO_RENDERER_SINK_CACHE_H_ +#ifndef CONTENT_RENDERER_MEDIA_AUDIO_AUDIO_RENDERER_SINK_CACHE_H_ +#define CONTENT_RENDERER_MEDIA_AUDIO_AUDIO_RENDERER_SINK_CACHE_H_ #include <memory> #include <string> @@ -60,4 +60,4 @@ class CONTENT_EXPORT AudioRendererSinkCache { } // namespace content -#endif // CONTENT_RENDERER_MEDIA_AUDIO_RENDERER_SINK_CACHE_H_ +#endif // CONTENT_RENDERER_MEDIA_AUDIO_AUDIO_RENDERER_SINK_CACHE_H_ diff --git a/chromium/content/renderer/media/audio_renderer_sink_cache_impl.cc b/chromium/content/renderer/media/audio/audio_renderer_sink_cache_impl.cc index 3dc8bebc611..a28bcf9eed6 100644 --- a/chromium/content/renderer/media/audio_renderer_sink_cache_impl.cc +++ b/chromium/content/renderer/media/audio/audio_renderer_sink_cache_impl.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/renderer/media/audio_renderer_sink_cache_impl.h" +#include "content/renderer/media/audio/audio_renderer_sink_cache_impl.h" #include <algorithm> #include <memory> @@ -17,7 +17,7 @@ #include "base/trace_event/trace_event.h" #include "content/public/renderer/render_frame.h" #include "content/public/renderer/render_frame_observer.h" -#include "content/renderer/media/audio_device_factory.h" +#include "content/renderer/media/audio/audio_device_factory.h" #include "media/audio/audio_device_description.h" #include "media/base/audio_renderer_sink.h" diff --git a/chromium/content/renderer/media/audio_renderer_sink_cache_impl.h b/chromium/content/renderer/media/audio/audio_renderer_sink_cache_impl.h index 93dd9adb2e3..0b6e872f4b9 100644 --- a/chromium/content/renderer/media/audio_renderer_sink_cache_impl.h +++ b/chromium/content/renderer/media/audio/audio_renderer_sink_cache_impl.h @@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_RENDERER_MEDIA_AUDIO_RENDERER_SINK_CACHE_IMPL_H_ -#define CONTENT_RENDERER_MEDIA_AUDIO_RENDERER_SINK_CACHE_IMPL_H_ +#ifndef CONTENT_RENDERER_MEDIA_AUDIO_AUDIO_RENDERER_SINK_CACHE_IMPL_H_ +#define CONTENT_RENDERER_MEDIA_AUDIO_AUDIO_RENDERER_SINK_CACHE_IMPL_H_ -#include "content/renderer/media/audio_renderer_sink_cache.h" +#include "content/renderer/media/audio/audio_renderer_sink_cache.h" #include <string> #include <vector> @@ -118,4 +118,4 @@ class CONTENT_EXPORT AudioRendererSinkCacheImpl } // namespace content -#endif // CONTENT_RENDERER_MEDIA_AUDIO_RENDERER_SINK_CACHE_IMPL_H_ +#endif // CONTENT_RENDERER_MEDIA_AUDIO_AUDIO_RENDERER_SINK_CACHE_IMPL_H_ diff --git a/chromium/content/renderer/media/audio_renderer_sink_cache_unittest.cc b/chromium/content/renderer/media/audio/audio_renderer_sink_cache_unittest.cc index bd510528654..3c3172e277d 100644 --- a/chromium/content/renderer/media/audio_renderer_sink_cache_unittest.cc +++ b/chromium/content/renderer/media/audio/audio_renderer_sink_cache_unittest.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/renderer/media/audio_renderer_sink_cache_impl.h" +#include "content/renderer/media/audio/audio_renderer_sink_cache_impl.h" #include <utility> diff --git a/chromium/content/renderer/media/mock_audio_device_factory.cc b/chromium/content/renderer/media/audio/mock_audio_device_factory.cc index d4517c7250c..69c1589a53b 100644 --- a/chromium/content/renderer/media/mock_audio_device_factory.cc +++ b/chromium/content/renderer/media/audio/mock_audio_device_factory.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/renderer/media/mock_audio_device_factory.h" +#include "content/renderer/media/audio/mock_audio_device_factory.h" namespace content { diff --git a/chromium/content/renderer/media/mock_audio_device_factory.h b/chromium/content/renderer/media/audio/mock_audio_device_factory.h index 33be7bf046c..0958cc23b47 100644 --- a/chromium/content/renderer/media/mock_audio_device_factory.h +++ b/chromium/content/renderer/media/audio/mock_audio_device_factory.h @@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CONTENT_RENDERER_MEDIA_MOCK_AUDIO_DEVICE_FACTORY_H_ -#define CONTENT_RENDERER_MEDIA_MOCK_AUDIO_DEVICE_FACTORY_H_ +#ifndef CONTENT_RENDERER_MEDIA_AUDIO_MOCK_AUDIO_DEVICE_FACTORY_H_ +#define CONTENT_RENDERER_MEDIA_AUDIO_MOCK_AUDIO_DEVICE_FACTORY_H_ #include <string> -#include "content/renderer/media/audio_device_factory.h" +#include "content/renderer/media/audio/audio_device_factory.h" #include "media/base/audio_capturer_source.h" #include "media/base/audio_renderer_sink.h" #include "testing/gmock/include/gmock/gmock.h" @@ -78,4 +78,4 @@ class MockAudioDeviceFactory : public AudioDeviceFactory { } // namespace content -#endif // CONTENT_RENDERER_MEDIA_MOCK_AUDIO_DEVICE_FACTORY_H_ +#endif // CONTENT_RENDERER_MEDIA_AUDIO_MOCK_AUDIO_DEVICE_FACTORY_H_ diff --git a/chromium/content/renderer/media/mojo_audio_input_ipc.cc b/chromium/content/renderer/media/audio/mojo_audio_input_ipc.cc index 44b2e55fb11..490b3cd0a6b 100644 --- a/chromium/content/renderer/media/mojo_audio_input_ipc.cc +++ b/chromium/content/renderer/media/audio/mojo_audio_input_ipc.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/renderer/media/mojo_audio_input_ipc.h" +#include "content/renderer/media/audio/mojo_audio_input_ipc.h" #include <utility> @@ -81,7 +81,7 @@ void MojoAudioInputIPC::CloseStream() { void MojoAudioInputIPC::StreamCreated( media::mojom::AudioInputStreamPtr stream, media::mojom::AudioInputStreamClientRequest stream_client_request, - media::mojom::AudioDataPipePtr data_pipe, + media::mojom::ReadOnlyAudioDataPipePtr data_pipe, bool initially_muted, const base::Optional<base::UnguessableToken>& stream_id) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -104,14 +104,12 @@ void MojoAudioInputIPC::StreamCreated( mojo::UnwrapPlatformFile(std::move(data_pipe->socket), &socket_handle); DCHECK_EQ(result, MOJO_RESULT_OK); - base::SharedMemoryHandle memory_handle; - mojo::UnwrappedSharedMemoryHandleProtection protection; - result = mojo::UnwrapSharedMemoryHandle(std::move(data_pipe->shared_memory), - &memory_handle, nullptr, &protection); - DCHECK_EQ(result, MOJO_RESULT_OK); - DCHECK_EQ(protection, mojo::UnwrappedSharedMemoryHandleProtection::kReadOnly); + base::ReadOnlySharedMemoryRegion& shared_memory_region = + data_pipe->shared_memory; + DCHECK(shared_memory_region.IsValid()); - delegate_->OnStreamCreated(memory_handle, socket_handle, initially_muted); + delegate_->OnStreamCreated(std::move(shared_memory_region), socket_handle, + initially_muted); } void MojoAudioInputIPC::OnError() { diff --git a/chromium/content/renderer/media/mojo_audio_input_ipc.h b/chromium/content/renderer/media/audio/mojo_audio_input_ipc.h index 9161a53c62f..b47c1d0fcea 100644 --- a/chromium/content/renderer/media/mojo_audio_input_ipc.h +++ b/chromium/content/renderer/media/audio/mojo_audio_input_ipc.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_RENDERER_MEDIA_MOJO_AUDIO_INPUT_IPC_H_ -#define CONTENT_RENDERER_MEDIA_MOJO_AUDIO_INPUT_IPC_H_ +#ifndef CONTENT_RENDERER_MEDIA_AUDIO_MOJO_AUDIO_INPUT_IPC_H_ +#define CONTENT_RENDERER_MEDIA_AUDIO_MOJO_AUDIO_INPUT_IPC_H_ #include <string> @@ -59,7 +59,7 @@ class CONTENT_EXPORT MojoAudioInputIPC void StreamCreated( media::mojom::AudioInputStreamPtr stream, media::mojom::AudioInputStreamClientRequest stream_client_request, - media::mojom::AudioDataPipePtr data_pipe, + media::mojom::ReadOnlyAudioDataPipePtr data_pipe, bool initially_muted, const base::Optional<base::UnguessableToken>& stream_id) override; void OnError() override; @@ -86,4 +86,4 @@ class CONTENT_EXPORT MojoAudioInputIPC } // namespace content -#endif // CONTENT_RENDERER_MEDIA_MOJO_AUDIO_INPUT_IPC_H_ +#endif // CONTENT_RENDERER_MEDIA_AUDIO_MOJO_AUDIO_INPUT_IPC_H_ diff --git a/chromium/content/renderer/media/mojo_audio_input_ipc_unittest.cc b/chromium/content/renderer/media/audio/mojo_audio_input_ipc_unittest.cc index 540cb3125cd..f9f33fe2e11 100644 --- a/chromium/content/renderer/media/mojo_audio_input_ipc_unittest.cc +++ b/chromium/content/renderer/media/audio/mojo_audio_input_ipc_unittest.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/renderer/media/mojo_audio_input_ipc.h" +#include "content/renderer/media/audio/mojo_audio_input_ipc.h" #include <algorithm> #include <memory> @@ -52,11 +52,9 @@ class MockDelegate : public media::AudioInputIPCDelegate { MockDelegate() {} ~MockDelegate() override {} - void OnStreamCreated(base::SharedMemoryHandle mem_handle, + void OnStreamCreated(base::ReadOnlySharedMemoryRegion mem_handle, base::SyncSocket::Handle socket_handle, bool initially_muted) override { - base::SharedMemory sh_mem( - mem_handle, /*read_only*/ true); // Releases the shared memory handle. base::SyncSocket socket(socket_handle); // Releases the socket descriptor. GotOnStreamCreated(initially_muted); } @@ -88,8 +86,7 @@ class FakeStreamCreator { factory_client_->StreamCreated( std::move(stream_ptr), mojo::MakeRequest(&stream_client_), {base::in_place, - mojo::SharedBufferHandle::Create(kMemoryLength) - ->Clone(mojo::SharedBufferHandle::AccessMode::READ_ONLY), + base::ReadOnlySharedMemoryRegion::Create(kMemoryLength).region, mojo::WrapPlatformFile(foreign_socket.Release())}, initially_muted_, base::UnguessableToken::Create()); } diff --git a/chromium/content/renderer/media/mojo_audio_output_ipc.cc b/chromium/content/renderer/media/audio/mojo_audio_output_ipc.cc index 35ead19d6b9..1782dd20420 100644 --- a/chromium/content/renderer/media/mojo_audio_output_ipc.cc +++ b/chromium/content/renderer/media/audio/mojo_audio_output_ipc.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/renderer/media/mojo_audio_output_ipc.h" +#include "content/renderer/media/audio/mojo_audio_output_ipc.h" #include <utility> @@ -214,8 +214,9 @@ void MojoAudioOutputIPC::ReceivedDeviceAuthorization( delegate_->OnDeviceAuthorized(status, params, device_id); } -void MojoAudioOutputIPC::Created(media::mojom::AudioOutputStreamPtr stream, - media::mojom::AudioDataPipePtr data_pipe) { +void MojoAudioOutputIPC::Created( + media::mojom::AudioOutputStreamPtr stream, + media::mojom::ReadWriteAudioDataPipePtr data_pipe) { DCHECK(io_task_runner_->RunsTasksInCurrentSequence()); DCHECK(delegate_); @@ -228,17 +229,11 @@ void MojoAudioOutputIPC::Created(media::mojom::AudioOutputStreamPtr stream, mojo::UnwrapPlatformFile(std::move(data_pipe->socket), &socket_handle); DCHECK_EQ(result, MOJO_RESULT_OK); - base::SharedMemoryHandle memory_handle; - mojo::UnwrappedSharedMemoryHandleProtection protection; - size_t memory_length = 0; - result = mojo::UnwrapSharedMemoryHandle(std::move(data_pipe->shared_memory), - &memory_handle, &memory_length, - &protection); - DCHECK_EQ(result, MOJO_RESULT_OK); - DCHECK_EQ(protection, - mojo::UnwrappedSharedMemoryHandleProtection::kReadWrite); + base::UnsafeSharedMemoryRegion& shared_memory_region = + data_pipe->shared_memory; + DCHECK(shared_memory_region.IsValid()); - delegate_->OnStreamCreated(memory_handle, socket_handle, + delegate_->OnStreamCreated(std::move(shared_memory_region), socket_handle, expected_state_ == kPlaying); if (volume_) diff --git a/chromium/content/renderer/media/mojo_audio_output_ipc.h b/chromium/content/renderer/media/audio/mojo_audio_output_ipc.h index bd78a490a92..00084e5928e 100644 --- a/chromium/content/renderer/media/mojo_audio_output_ipc.h +++ b/chromium/content/renderer/media/audio/mojo_audio_output_ipc.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_RENDERER_MEDIA_MOJO_AUDIO_OUTPUT_IPC_H_ -#define CONTENT_RENDERER_MEDIA_MOJO_AUDIO_OUTPUT_IPC_H_ +#ifndef CONTENT_RENDERER_MEDIA_AUDIO_MOJO_AUDIO_OUTPUT_IPC_H_ +#define CONTENT_RENDERER_MEDIA_AUDIO_MOJO_AUDIO_OUTPUT_IPC_H_ #include <string> @@ -52,7 +52,7 @@ class CONTENT_EXPORT MojoAudioOutputIPC // media::mojom::AudioOutputStreamProviderClient implementation. void Created(media::mojom::AudioOutputStreamPtr stream, - media::mojom::AudioDataPipePtr data_pipe) override; + media::mojom::ReadWriteAudioDataPipePtr data_pipe) override; private: static constexpr double kDefaultVolume = 1.0; @@ -104,4 +104,4 @@ class CONTENT_EXPORT MojoAudioOutputIPC } // namespace content -#endif // CONTENT_RENDERER_MEDIA_MOJO_AUDIO_OUTPUT_IPC_H_ +#endif // CONTENT_RENDERER_MEDIA_AUDIO_MOJO_AUDIO_OUTPUT_IPC_H_ diff --git a/chromium/content/renderer/media/mojo_audio_output_ipc_unittest.cc b/chromium/content/renderer/media/audio/mojo_audio_output_ipc_unittest.cc index 58be5468279..100687c928c 100644 --- a/chromium/content/renderer/media/mojo_audio_output_ipc_unittest.cc +++ b/chromium/content/renderer/media/audio/mojo_audio_output_ipc_unittest.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/renderer/media/mojo_audio_output_ipc.h" +#include "content/renderer/media/audio/mojo_audio_output_ipc.h" #include <algorithm> #include <memory> @@ -70,7 +70,7 @@ class TestStreamProvider : public media::mojom::AudioOutputStreamProvider { base::CancelableSyncSocket::CreatePair(&socket_, &foreign_socket)); provider_client_->Created( std::move(stream_ptr), - {base::in_place, mojo::SharedBufferHandle::Create(kMemoryLength), + {base::in_place, base::UnsafeSharedMemoryRegion::Create(kMemoryLength), mojo::WrapPlatformFile(foreign_socket.Release())}); } @@ -180,11 +180,9 @@ class MockDelegate : public media::AudioOutputIPCDelegate { MockDelegate() {} ~MockDelegate() override {} - void OnStreamCreated(base::SharedMemoryHandle mem_handle, + void OnStreamCreated(base::UnsafeSharedMemoryRegion mem_handle, base::SyncSocket::Handle socket_handle, bool playing_automatically) override { - base::SharedMemory sh_mem( - mem_handle, /*read_only*/ false); // Releases the shared memory handle. base::SyncSocket socket(socket_handle); // Releases the socket descriptor. GotOnStreamCreated(); } 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 8336e384eec..6022a765b1b 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 @@ -223,7 +223,6 @@ bool GpuVideoAcceleratorFactoriesImpl::CreateTextures( gles2->TexImage2D(texture_target, 0, GL_RGBA, size.width(), size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); } - gles2->GenMailboxCHROMIUM(texture_mailboxes->at(i).name); gles2->ProduceTextureDirectCHROMIUM(texture_id, texture_mailboxes->at(i).name); } @@ -312,9 +311,8 @@ GpuVideoAcceleratorFactoriesImpl::VideoFrameOutputFormat(size_t bit_depth) { if (rendering_color_space_.IsHDR()) return media::GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED; -#if defined(OS_MACOSX) || defined(OS_LINUX) - // TODO(mcasas): enable other platforms https://crbug.com/776093 - // https://crbug.com/803451. +#if !defined(OS_WIN) + // TODO(mcasas): enable Win https://crbug.com/803451. // TODO(mcasas): remove the |bit_depth| check when libyuv supports more than // just x010ToAR30 conversions, https://crbug.com/libyuv/751. if (bit_depth == 10) { diff --git a/chromium/content/renderer/media/media_factory.cc b/chromium/content/renderer/media/media_factory.cc index 5e2119c7f4c..fe25c6b87ab 100644 --- a/chromium/content/renderer/media/media_factory.cc +++ b/chromium/content/renderer/media/media_factory.cc @@ -15,7 +15,7 @@ #include "build/buildflag.h" #include "content/public/common/content_client.h" #include "content/public/renderer/content_renderer_client.h" -#include "content/renderer/media/audio_device_factory.h" +#include "content/renderer/media/audio/audio_device_factory.h" #include "content/renderer/media/render_media_log.h" #include "content/renderer/media/renderer_webmediaplayer_delegate.h" #include "content/renderer/media/stream/media_stream_renderer_factory_impl.h" @@ -28,7 +28,6 @@ #include "media/base/decoder_factory.h" #include "media/base/media_switches.h" #include "media/base/renderer_factory_selector.h" -#include "media/base/surface_manager.h" #include "media/blink/remote_playback_client_wrapper_impl.h" #include "media/blink/resource_fetch_context.h" #include "media/blink/webencryptedmediaclient_impl.h" @@ -46,12 +45,12 @@ #include "third_party/blink/public/platform/web_video_frame_submitter.h" #include "third_party/blink/public/web/blink.h" #include "third_party/blink/public/web/web_local_frame.h" +#include "ui/base/ui_base_features.h" #include "url/origin.h" #if defined(OS_ANDROID) #include "content/renderer/media/android/media_player_renderer_client_factory.h" #include "content/renderer/media/android/renderer_media_player_manager.h" -#include "content/renderer/media/android/renderer_surface_view_manager.h" #include "content/renderer/media/android/stream_texture_wrapper_impl.h" #include "media/base/android/media_codec_util.h" #include "media/base/media.h" @@ -139,6 +138,21 @@ void PostMediaContextProviderToCallback( namespace content { +// static +bool MediaFactory::VideoSurfaceLayerEnabled() { + // 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 false; + } + + return base::FeatureList::IsEnabled(media::kUseSurfaceLayerForVideo) && + features::IsAshInBrowserProcess(); +} + MediaFactory::MediaFactory( RenderFrameImpl* render_frame, media::RequestRoutingTokenCallback request_routing_token_cb) @@ -223,8 +237,6 @@ blink::WebMediaPlayer* MediaFactory::CreateMediaPlayer( bool use_media_player_renderer = false; #if defined(OS_ANDROID) use_media_player_renderer = UseMediaPlayerRenderer(url); - if (!use_media_player_renderer && !media_surface_manager_) - media_surface_manager_ = new RendererSurfaceViewManager(render_frame_); embedded_media_experience_enabled = webkit_preferences.embedded_media_experience_enabled; #endif // defined(OS_ANDROID) @@ -278,8 +290,7 @@ 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 = - base::FeatureList::IsEnabled(media::kUseSurfaceLayerForVideo); + bool use_surface_layer_for_video = VideoSurfaceLayerEnabled(); if (use_surface_layer_for_video) { // TODO(lethalantidote): Use a separate task_runner. https://crbug/753605. video_frame_compositor_task_runner = @@ -298,25 +309,36 @@ blink::WebMediaPlayer* MediaFactory::CreateMediaPlayer( } DCHECK(layer_tree_view); + scoped_refptr<base::SingleThreadTaskRunner> media_task_runner = + render_thread->GetMediaThreadTaskRunner(); + + if (!media_task_runner) { + // If the media thread failed to start, we will receive a null task runner. + // Fail the creation by returning null, and let callers handle the error. + // See https://crbug.com/775393. + return nullptr; + } + std::unique_ptr<media::WebMediaPlayerParams> params( new media::WebMediaPlayerParams( std::move(media_log), - base::Bind(&ContentRendererClient::DeferMediaLoad, - base::Unretained(GetContentClient()->renderer()), - static_cast<RenderFrame*>(render_frame_), - GetWebMediaPlayerDelegate()->has_played_media()), - audio_renderer_sink, render_thread->GetMediaThreadTaskRunner(), + base::BindRepeating(&ContentRendererClient::DeferMediaLoad, + base::Unretained(GetContentClient()->renderer()), + static_cast<RenderFrame*>(render_frame_), + GetWebMediaPlayerDelegate()->has_played_media()), + audio_renderer_sink, media_task_runner, render_thread->GetWorkerTaskRunner(), render_thread->compositor_task_runner(), video_frame_compositor_task_runner, base::Bind(&v8::Isolate::AdjustAmountOfExternalAllocatedMemory, base::Unretained(blink::MainThreadIsolate())), - initial_cdm, media_surface_manager_, request_routing_token_cb_, - media_observer, max_keyframe_distance_to_disable_background_video, + initial_cdm, request_routing_token_cb_, media_observer, + max_keyframe_distance_to_disable_background_video, max_keyframe_distance_to_disable_background_video_mse, enable_instant_source_buffer_gc, embedded_media_experience_enabled, std::move(metrics_provider), - base::Bind(&blink::WebSurfaceLayerBridge::Create, layer_tree_view), + base::BindOnce(&blink::WebSurfaceLayerBridge::Create, + layer_tree_view), RenderThreadImpl::current()->SharedMainThreadContextProvider(), use_surface_layer_for_video)); diff --git a/chromium/content/renderer/media/media_factory.h b/chromium/content/renderer/media/media_factory.h index 1d5aeece741..7c4ea973a11 100644 --- a/chromium/content/renderer/media/media_factory.h +++ b/chromium/content/renderer/media/media_factory.h @@ -45,7 +45,6 @@ class MediaLog; class MediaObserver; class RemotePlaybackClientWrapper; class RendererWebMediaPlayerDelegate; -class SurfaceManager; class WebEncryptedMediaClientImpl; #if defined(OS_ANDROID) class RendererMediaPlayerManager; @@ -72,6 +71,9 @@ class RendererMediaPlayerManager; // Assist to RenderFrameImpl in creating various media clients. class MediaFactory { public: + // Helper function returning whether VideoSurfaceLayer should be enabled. + static bool VideoSurfaceLayerEnabled(); + // Create a MediaFactory to assist the |render_frame| with media tasks. // |request_routing_token_cb| bound to |render_frame| IPC functions for // obtaining overlay tokens. @@ -172,10 +174,6 @@ class MediaFactory { RendererMediaPlayerManager* media_player_manager_ = nullptr; #endif - // Handles requests for SurfaceViews for MediaPlayers. - // Lifetime is tied to the RenderFrame via the RenderFrameObserver interface. - media::SurfaceManager* media_surface_manager_ = nullptr; - // Manages play, pause notifications for WebMediaPlayer implementations; its // lifetime is tied to the RenderFrame via the RenderFrameObserver interface. media::RendererWebMediaPlayerDelegate* media_player_delegate_ = nullptr; diff --git a/chromium/content/renderer/media/pepper/pepper_to_video_track_adapter_unittest.cc b/chromium/content/renderer/media/pepper/pepper_to_video_track_adapter_unittest.cc index 9f8eb121f4c..ce350d3026f 100644 --- a/chromium/content/renderer/media/pepper/pepper_to_video_track_adapter_unittest.cc +++ b/chromium/content/renderer/media/pepper/pepper_to_video_track_adapter_unittest.cc @@ -71,8 +71,8 @@ TEST_F(PepperToVideoTrackAdapterTest, PutFrame) { // Verify the video track has been added. const blink::WebMediaStream test_stream = registry_->test_stream(); - blink::WebVector<blink::WebMediaStreamTrack> video_tracks; - test_stream.VideoTracks(video_tracks); + blink::WebVector<blink::WebMediaStreamTrack> video_tracks = + test_stream.VideoTracks(); ASSERT_EQ(1u, video_tracks.size()); // Verify the native video track has been added. diff --git a/chromium/content/renderer/media/pepper/video_track_to_pepper_adapter.cc b/chromium/content/renderer/media/pepper/video_track_to_pepper_adapter.cc index 6787c2ea278..a87b792ff77 100644 --- a/chromium/content/renderer/media/pepper/video_track_to_pepper_adapter.cc +++ b/chromium/content/renderer/media/pepper/video_track_to_pepper_adapter.cc @@ -106,8 +106,8 @@ blink::WebMediaStreamTrack VideoTrackToPepperAdapter::GetFirstVideoTrack( } // Get the first video track from the stream. - blink::WebVector<blink::WebMediaStreamTrack> video_tracks; - stream.VideoTracks(video_tracks); + blink::WebVector<blink::WebMediaStreamTrack> video_tracks = + stream.VideoTracks(); if (video_tracks.IsEmpty()) { LOG(ERROR) << "GetFirstVideoSource - no video tracks. url: " << url; return blink::WebMediaStreamTrack(); diff --git a/chromium/content/renderer/media/renderer_webaudiodevice_impl.cc b/chromium/content/renderer/media/renderer_webaudiodevice_impl.cc index 8c6ca64ef59..1c57ddf3713 100644 --- a/chromium/content/renderer/media/renderer_webaudiodevice_impl.cc +++ b/chromium/content/renderer/media/renderer_webaudiodevice_impl.cc @@ -13,7 +13,7 @@ #include "base/command_line.h" #include "base/logging.h" #include "base/time/time.h" -#include "content/renderer/media/audio_device_factory.h" +#include "content/renderer/media/audio/audio_device_factory.h" #include "content/renderer/render_frame_impl.h" #include "content/renderer/render_thread_impl.h" #include "media/base/audio_timestamp_helper.h" diff --git a/chromium/content/renderer/media/renderer_webaudiodevice_impl_unittest.cc b/chromium/content/renderer/media/renderer_webaudiodevice_impl_unittest.cc index 5b338c5e67b..337fff50fc4 100644 --- a/chromium/content/renderer/media/renderer_webaudiodevice_impl_unittest.cc +++ b/chromium/content/renderer/media/renderer_webaudiodevice_impl_unittest.cc @@ -8,7 +8,7 @@ #include "base/message_loop/message_loop.h" #include "base/strings/stringprintf.h" #include "build/build_config.h" -#include "content/renderer/media/audio_device_factory.h" +#include "content/renderer/media/audio/audio_device_factory.h" #include "media/base/audio_capturer_source.h" #include "media/base/limits.h" #include "media/base/mock_audio_renderer_sink.h" diff --git a/chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc b/chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc index 31ba7ced7ae..f644a25e76f 100644 --- a/chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc +++ b/chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc @@ -276,6 +276,8 @@ bool RendererWebMediaPlayerDelegate::OnMessageReceived( OnMediaDelegateBecamePersistentVideo) IPC_MESSAGE_HANDLER(MediaPlayerDelegateMsg_EndPictureInPictureMode, OnPictureInPictureModeEnded) + IPC_MESSAGE_HANDLER(MediaPlayerDelegateMsg_ClickPictureInPictureControl, + OnPictureInPictureControlClicked) IPC_MESSAGE_HANDLER(MediaPlayerDelegateMsg_OnPictureInPictureModeEnded_ACK, OnPictureInPictureModeEndedAck) IPC_MESSAGE_HANDLER( @@ -394,6 +396,14 @@ void RendererWebMediaPlayerDelegate::OnPictureInPictureModeEnded( observer->OnPictureInPictureModeEnded(); } +void RendererWebMediaPlayerDelegate::OnPictureInPictureControlClicked( + int player_id, + const std::string& control_id) { + Observer* observer = id_map_.Lookup(player_id); + if (observer) + observer->OnPictureInPictureControlClicked(control_id); +} + void RendererWebMediaPlayerDelegate::OnPictureInPictureModeEndedAck( int player_id, int request_id) { diff --git a/chromium/content/renderer/media/renderer_webmediaplayer_delegate.h b/chromium/content/renderer/media/renderer_webmediaplayer_delegate.h index 171141ef960..5897004debb 100644 --- a/chromium/content/renderer/media/renderer_webmediaplayer_delegate.h +++ b/chromium/content/renderer/media/renderer_webmediaplayer_delegate.h @@ -107,6 +107,8 @@ class CONTENT_EXPORT RendererWebMediaPlayerDelegate void OnMediaDelegateVolumeMultiplierUpdate(int player_id, double multiplier); void OnMediaDelegateBecamePersistentVideo(int player_id, bool value); void OnPictureInPictureModeEnded(int player_id); + void OnPictureInPictureControlClicked(int player_id, + const std::string& control_id); void OnPictureInPictureModeEndedAck(int player_id, int request_id); void OnPictureInPictureModeStartedAck(int player_id, int request_id, diff --git a/chromium/content/renderer/media/renderer_webmediaplayer_delegate_browsertest.cc b/chromium/content/renderer/media/renderer_webmediaplayer_delegate_browsertest.cc index 26d8e6ab43b..8c2cf76c616 100644 --- a/chromium/content/renderer/media/renderer_webmediaplayer_delegate_browsertest.cc +++ b/chromium/content/renderer/media/renderer_webmediaplayer_delegate_browsertest.cc @@ -9,7 +9,7 @@ #include "base/location.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" -#include "base/test/histogram_tester.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/simple_test_tick_clock.h" #include "base/threading/thread_task_runner_handle.h" #include "content/common/media/media_player_delegate_messages.h" @@ -49,6 +49,7 @@ class MockWebMediaPlayerDelegateObserver MOCK_METHOD1(OnVolumeMultiplierUpdate, void(double)); MOCK_METHOD1(OnBecamePersistentVideo, void(bool)); MOCK_METHOD0(OnPictureInPictureModeEnded, void()); + MOCK_METHOD1(OnPictureInPictureControlClicked, void(const std::string&)); }; class RendererWebMediaPlayerDelegateTest : public content::RenderViewTest { 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 25d43bf45c8..a51cc04af8f 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 @@ -4,7 +4,7 @@ #include "content/renderer/media/stream/local_media_stream_audio_source.h" -#include "content/renderer/media/audio_device_factory.h" +#include "content/renderer/media/audio/audio_device_factory.h" #include "content/renderer/media/webrtc_logging.h" #include "content/renderer/render_frame_impl.h" 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 9b76c672c26..d71f25992ac 100644 --- a/chromium/content/renderer/media/stream/media_stream_audio_processor.cc +++ b/chromium/content/renderer/media/stream/media_stream_audio_processor.cc @@ -36,6 +36,8 @@ namespace content { +using EchoCancellationType = AudioProcessingProperties::EchoCancellationType; + namespace { using webrtc::AudioProcessing; @@ -104,19 +106,6 @@ bool UseAecRefinedAdaptiveFilter() { switches::kAecRefinedAdaptiveFilter); } -webrtc::Point WebrtcPointFromMediaPoint(const media::Point& point) { - return webrtc::Point(point.x(), point.y(), point.z()); -} - -std::vector<webrtc::Point> WebrtcPointsFromMediaPoints( - const std::vector<media::Point>& points) { - std::vector<webrtc::Point> webrtc_points; - webrtc_points.reserve(webrtc_points.size()); - for (const auto& point : points) - webrtc_points.push_back(WebrtcPointFromMediaPoint(point)); - return webrtc_points; -} - } // namespace // Wraps AudioBus to provide access to the array of channel pointers, since this @@ -425,8 +414,9 @@ void MediaStreamAudioProcessor::OnAecDumpFile( // webrtc::AudioProcessing instance is destroyed. StartEchoCancellationDump(audio_processing_.get(), std::move(file), worker_queue_.get()); - } else + } else { file.Close(); + } } void MediaStreamAudioProcessor::OnDisableAecDump() { @@ -454,7 +444,7 @@ bool MediaStreamAudioProcessor::WouldModifyAudio( return true; #if !defined(OS_IOS) - if (properties.enable_sw_echo_cancellation || + if (properties.EchoCancellationIsWebRtcProvided() || properties.goog_auto_gain_control) { return true; } @@ -469,7 +459,7 @@ bool MediaStreamAudioProcessor::WouldModifyAudio( if (properties.goog_noise_suppression || properties.goog_experimental_noise_suppression || - properties.goog_beamforming || properties.goog_highpass_filter) { + properties.goog_highpass_filter) { return true; } @@ -568,11 +558,11 @@ void MediaStreamAudioProcessor::InitializeAudioProcessingModule( // Return immediately if none of the goog constraints requiring // webrtc::AudioProcessing are enabled. - if (!properties.enable_sw_echo_cancellation && !goog_experimental_aec && - !properties.goog_noise_suppression && !properties.goog_highpass_filter && - !goog_typing_detection && !properties.goog_auto_gain_control && - !properties.goog_experimental_noise_suppression && - !properties.goog_beamforming) { + if (!properties.EchoCancellationIsWebRtcProvided() && + !goog_experimental_aec && !properties.goog_noise_suppression && + !properties.goog_highpass_filter && !goog_typing_detection && + !properties.goog_auto_gain_control && + !properties.goog_experimental_noise_suppression) { // Sanity-check: WouldModifyAudio() should return true iff // |audio_mirroring_| is true. DCHECK_EQ(audio_mirroring_, WouldModifyAudio(properties)); @@ -595,12 +585,6 @@ void MediaStreamAudioProcessor::InitializeAudioProcessingModule( config.Set<webrtc::RefinedAdaptiveFilter>( new webrtc::RefinedAdaptiveFilter(true)); } - if (properties.goog_beamforming) { - // Only enable beamforming if we have at least two mics. - config.Set<webrtc::Beamforming>(new webrtc::Beamforming( - properties.goog_array_geometry.size() > 1, - WebrtcPointsFromMediaPoints(properties.goog_array_geometry))); - } // If the experimental AGC is enabled, check for overridden config params. if (properties.goog_experimental_auto_gain_control) { @@ -609,21 +593,10 @@ void MediaStreamAudioProcessor::InitializeAudioProcessingModule( new webrtc::ExperimentalAgc(true, startup_min_volume.value_or(0))); } - // Check if experimental echo canceller should be used. - if (properties.enable_sw_echo_cancellation) { - base::Optional<bool> override_aec3; - // 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_) - override_aec3 = aec_dump_message_filter_->GetOverrideAec3(); - using_aec3_ = override_aec3.value_or( - base::FeatureList::IsEnabled(features::kWebRtcUseEchoCanceller3)); - } - // Create and configure the webrtc::AudioProcessing. webrtc::AudioProcessingBuilder ap_builder; - if (using_aec3_) { + if (properties.echo_cancellation_type == + EchoCancellationType::kEchoCancellationAec3) { webrtc::EchoCanceller3Config aec3_config; aec3_config.ep_strength.bounded_erl = base::FeatureList::IsEnabled(features::kWebRtcAecBoundedErlSetup); @@ -645,25 +618,20 @@ void MediaStreamAudioProcessor::InitializeAudioProcessingModule( playout_data_source_->AddPlayoutSink(this); } - if (properties.enable_sw_echo_cancellation) { + if (properties.EchoCancellationIsWebRtcProvided()) { EnableEchoCancellation(audio_processing_.get()); // Prepare for logging echo information. Do not log any echo information // when AEC3 is active, as the echo information then will not be properly // updated. - if (!using_aec3_) + if (properties.echo_cancellation_type != + EchoCancellationType::kEchoCancellationAec3) { echo_information_ = std::make_unique<EchoInformation>(); + } } - if (properties.goog_noise_suppression) { - // The beamforming postfilter is effective at suppressing stationary noise, - // so reduce the single-channel NS aggressiveness when enabled. - const NoiseSuppression::Level ns_level = - config.Get<webrtc::Beamforming>().enabled ? NoiseSuppression::kLow - : NoiseSuppression::kHigh; - - EnableNoiseSuppression(audio_processing_.get(), ns_level); - } + if (properties.goog_noise_suppression) + EnableNoiseSuppression(audio_processing_.get(), NoiseSuppression::kHigh); apm_config.high_pass_filter.enabled = properties.goog_highpass_filter; 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 c7b1d1c1287..c5237570077 100644 --- a/chromium/content/renderer/media/stream/media_stream_audio_processor.h +++ b/chromium/content/renderer/media/stream/media_stream_audio_processor.h @@ -120,10 +120,6 @@ class CONTENT_EXPORT MediaStreamAudioProcessor protected: ~MediaStreamAudioProcessor() override; - // True if AEC3 is used, false if it's not or no AEC is used at all. Used for - // verification in tests. - bool using_aec3_ = false; - private: friend class MediaStreamAudioProcessorTest; 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 4c471a4ea36..7a5a6274a5c 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 @@ -67,25 +67,29 @@ AudioProcessingProperties::AudioProcessingProperties( const AudioProcessingProperties& other) = default; AudioProcessingProperties& AudioProcessingProperties::operator=( const AudioProcessingProperties& other) = default; -AudioProcessingProperties::AudioProcessingProperties( - AudioProcessingProperties&& other) = default; -AudioProcessingProperties& AudioProcessingProperties::operator=( - AudioProcessingProperties&& other) = default; -AudioProcessingProperties::~AudioProcessingProperties() = default; void AudioProcessingProperties::DisableDefaultProperties() { - enable_sw_echo_cancellation = false; - disable_hw_echo_cancellation = false; + echo_cancellation_type = EchoCancellationType::kEchoCancellationDisabled; goog_auto_gain_control = false; goog_experimental_echo_cancellation = false; goog_typing_noise_detection = false; goog_noise_suppression = false; goog_experimental_noise_suppression = false; - goog_beamforming = false; goog_highpass_filter = false; goog_experimental_auto_gain_control = false; } +bool AudioProcessingProperties::EchoCancellationEnabled() const { + return echo_cancellation_type != + EchoCancellationType::kEchoCancellationDisabled; +} + +bool AudioProcessingProperties::EchoCancellationIsWebRtcProvided() const { + return echo_cancellation_type == + EchoCancellationType::kEchoCancellationAec2 || + echo_cancellation_type == EchoCancellationType::kEchoCancellationAec3; +} + EchoInformation::EchoInformation() : delay_stats_time_ms_(0), echo_frames_received_(false), @@ -271,8 +275,7 @@ void EnableAutomaticGainControl(AudioProcessing* audio_processing) { void GetAudioProcessingStats( AudioProcessing* audio_processing, webrtc::AudioProcessorInterface::AudioProcessorStats* stats) { - // TODO(ivoc): Change the APM stats to use rtc::Optional instead of default - // values. + // TODO(ivoc): Change the APM stats to use optional instead of default values. auto apm_stats = audio_processing->GetStatistics(); stats->echo_return_loss = apm_stats.echo_return_loss.instant(); stats->echo_return_loss_enhancement = 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 235fd87a925..75dd60a9879 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 @@ -33,21 +33,35 @@ using webrtc::AudioProcessing; // Simple struct with audio-processing properties. struct CONTENT_EXPORT AudioProcessingProperties { + enum class EchoCancellationType { + // Echo cancellation disabled. + kEchoCancellationDisabled, + // The WebRTC-provided AEC2 echo canceller. + kEchoCancellationAec2, + // The WebRTC-provided AEC3 echo canceller. + kEchoCancellationAec3, + // System echo canceller, for example an OS-provided or hardware echo + // canceller. + kEchoCancellationSystem + }; + // Creates an AudioProcessingProperties object with fields initialized to // their default values. AudioProcessingProperties(); AudioProcessingProperties(const AudioProcessingProperties& other); AudioProcessingProperties& operator=(const AudioProcessingProperties& other); - AudioProcessingProperties(AudioProcessingProperties&& other); - AudioProcessingProperties& operator=(AudioProcessingProperties&& other); - ~AudioProcessingProperties(); // Disables properties that are enabled by default. void DisableDefaultProperties(); - bool enable_sw_echo_cancellation = true; - bool disable_hw_echo_cancellation = true; - bool enable_experimental_hw_echo_cancellation = false; + // Returns whether echo cancellation is enabled. + bool EchoCancellationEnabled() const; + + // Returns whether WebRTC-provided echo cancellation is enabled. + bool EchoCancellationIsWebRtcProvided() const; + + EchoCancellationType echo_cancellation_type = + EchoCancellationType::kEchoCancellationAec2; bool disable_hw_noise_suppression = false; bool goog_audio_mirroring = false; bool goog_auto_gain_control = true; @@ -60,10 +74,8 @@ struct CONTENT_EXPORT AudioProcessingProperties { bool goog_typing_noise_detection = true; bool goog_noise_suppression = true; bool goog_experimental_noise_suppression = true; - bool goog_beamforming = true; bool goog_highpass_filter = true; bool goog_experimental_auto_gain_control = true; - std::vector<media::Point> goog_array_geometry; }; // A helper class to log echo information in general and Echo Cancellation diff --git a/chromium/content/renderer/media/stream/media_stream_audio_processor_unittest.cc b/chromium/content/renderer/media/stream/media_stream_audio_processor_unittest.cc index 16e71069bdb..19dff280a73 100644 --- a/chromium/content/renderer/media/stream/media_stream_audio_processor_unittest.cc +++ b/chromium/content/renderer/media/stream/media_stream_audio_processor_unittest.cc @@ -40,14 +40,6 @@ using ::testing::Return; using media::AudioParameters; -namespace webrtc { - -bool operator==(const webrtc::Point& lhs, const webrtc::Point& rhs) { - return lhs.x() == rhs.x() && lhs.y() == rhs.y() && lhs.z() == rhs.z(); -} - -} // namespace webrtc - namespace content { namespace { @@ -80,35 +72,6 @@ void ReadDataFromSpeechFile(char* data, int length) { } // namespace -class AecDumpMessageFilterForTest : public AecDumpMessageFilter { - public: - // This class is only used for setting |override_aec3_|, so we simply inject - // the current task runner. - AecDumpMessageFilterForTest() - : AecDumpMessageFilter(base::MessageLoopCurrent::Get()->task_runner(), - base::MessageLoopCurrent::Get()->task_runner()) {} - - void set_override_aec3(base::Optional<bool> override_aec3) { - override_aec3_ = override_aec3; - } - - protected: - ~AecDumpMessageFilterForTest() override {} -}; - -class MediaStreamAudioProcessorUnderTest : public MediaStreamAudioProcessor { - public: - MediaStreamAudioProcessorUnderTest( - const AudioProcessingProperties& properties, - WebRtcPlayoutDataSource* playout_data_source) - : MediaStreamAudioProcessor(properties, playout_data_source) {} - - bool using_aec3() { return using_aec3_; } - - protected: - ~MediaStreamAudioProcessorUnderTest() override {} -}; - class MediaStreamAudioProcessorTest : public ::testing::Test { public: MediaStreamAudioProcessorTest() @@ -247,8 +210,8 @@ TEST_F(MediaStreamAudioProcessorTest, MAYBE_WithAudioProcessing) { scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device( new rtc::RefCountedObject<WebRtcAudioDeviceImpl>()); AudioProcessingProperties properties; - scoped_refptr<MediaStreamAudioProcessorUnderTest> audio_processor( - new rtc::RefCountedObject<MediaStreamAudioProcessorUnderTest>( + scoped_refptr<MediaStreamAudioProcessor> audio_processor( + new rtc::RefCountedObject<MediaStreamAudioProcessor>( properties, webrtc_audio_device.get())); EXPECT_TRUE(audio_processor->has_audio_processing()); audio_processor->OnCaptureFormatChanged(params_); @@ -270,8 +233,8 @@ TEST_F(MediaStreamAudioProcessorTest, TurnOffDefaultConstraints) { properties.DisableDefaultProperties(); scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device( new rtc::RefCountedObject<WebRtcAudioDeviceImpl>()); - scoped_refptr<MediaStreamAudioProcessorUnderTest> audio_processor( - new rtc::RefCountedObject<MediaStreamAudioProcessorUnderTest>( + scoped_refptr<MediaStreamAudioProcessor> audio_processor( + new rtc::RefCountedObject<MediaStreamAudioProcessor>( properties, webrtc_audio_device.get())); EXPECT_FALSE(audio_processor->has_audio_processing()); audio_processor->OnCaptureFormatChanged(params_); @@ -296,8 +259,8 @@ TEST_F(MediaStreamAudioProcessorTest, MAYBE_TestAllSampleRates) { scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device( new rtc::RefCountedObject<WebRtcAudioDeviceImpl>()); AudioProcessingProperties properties; - scoped_refptr<MediaStreamAudioProcessorUnderTest> audio_processor( - new rtc::RefCountedObject<MediaStreamAudioProcessorUnderTest>( + scoped_refptr<MediaStreamAudioProcessor> audio_processor( + new rtc::RefCountedObject<MediaStreamAudioProcessor>( properties, webrtc_audio_device.get())); EXPECT_TRUE(audio_processor->has_audio_processing()); @@ -334,8 +297,8 @@ TEST_F(MediaStreamAudioProcessorTest, GetAecDumpMessageFilter) { scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device( new rtc::RefCountedObject<WebRtcAudioDeviceImpl>()); AudioProcessingProperties properties; - scoped_refptr<MediaStreamAudioProcessorUnderTest> audio_processor( - new rtc::RefCountedObject<MediaStreamAudioProcessorUnderTest>( + scoped_refptr<MediaStreamAudioProcessor> audio_processor( + new rtc::RefCountedObject<MediaStreamAudioProcessor>( properties, webrtc_audio_device.get())); EXPECT_TRUE(audio_processor->aec_dump_message_filter_.get()); @@ -356,8 +319,8 @@ TEST_F(MediaStreamAudioProcessorTest, StartStopAecDump) { ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_directory.GetPath(), &temp_file_path)); { - scoped_refptr<MediaStreamAudioProcessorUnderTest> audio_processor( - new rtc::RefCountedObject<MediaStreamAudioProcessorUnderTest>( + scoped_refptr<MediaStreamAudioProcessor> audio_processor( + new rtc::RefCountedObject<MediaStreamAudioProcessor>( properties, webrtc_audio_device.get())); // Start and stop recording. @@ -386,8 +349,8 @@ TEST_F(MediaStreamAudioProcessorTest, TestStereoAudio) { // Turn off the audio processing and turn on the stereo channels mirroring. properties.DisableDefaultProperties(); properties.goog_audio_mirroring = true; - scoped_refptr<MediaStreamAudioProcessorUnderTest> audio_processor( - new rtc::RefCountedObject<MediaStreamAudioProcessorUnderTest>( + scoped_refptr<MediaStreamAudioProcessor> audio_processor( + new rtc::RefCountedObject<MediaStreamAudioProcessor>( properties, webrtc_audio_device.get())); EXPECT_FALSE(audio_processor->has_audio_processing()); const media::AudioParameters source_params( @@ -447,8 +410,8 @@ TEST_F(MediaStreamAudioProcessorTest, MAYBE_TestWithKeyboardMicChannel) { scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device( new rtc::RefCountedObject<WebRtcAudioDeviceImpl>()); AudioProcessingProperties properties; - scoped_refptr<MediaStreamAudioProcessorUnderTest> audio_processor( - new rtc::RefCountedObject<MediaStreamAudioProcessorUnderTest>( + scoped_refptr<MediaStreamAudioProcessor> audio_processor( + new rtc::RefCountedObject<MediaStreamAudioProcessor>( properties, webrtc_audio_device.get())); EXPECT_TRUE(audio_processor->has_audio_processing()); @@ -467,47 +430,4 @@ TEST_F(MediaStreamAudioProcessorTest, MAYBE_TestWithKeyboardMicChannel) { audio_processor->Stop(); } -// Test that setting AEC3 override has the desired effect on the APM -// configuration. -TEST_F(MediaStreamAudioProcessorTest, TestAec3Switch) { - scoped_refptr<AecDumpMessageFilterForTest> admf = - new AecDumpMessageFilterForTest(); - admf->set_override_aec3(true); - - scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device( - new rtc::RefCountedObject<WebRtcAudioDeviceImpl>()); - AudioProcessingProperties properties; - scoped_refptr<MediaStreamAudioProcessorUnderTest> audio_processor( - new rtc::RefCountedObject<MediaStreamAudioProcessorUnderTest>( - properties, webrtc_audio_device.get())); - - EXPECT_TRUE(audio_processor->using_aec3()); - - // Stop |audio_processor| so that it removes itself from - // |webrtc_audio_device| and clears its pointer to it. - audio_processor->Stop(); -} - -// Same test as above, but when AEC is disabled in the constraints. The expected -// outcome is that AEC3 should be disabled in all cases. -TEST_F(MediaStreamAudioProcessorTest, TestAec3Switch_AecOff) { - scoped_refptr<AecDumpMessageFilterForTest> admf = - new AecDumpMessageFilterForTest(); - admf->set_override_aec3(true); - - scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device( - new rtc::RefCountedObject<WebRtcAudioDeviceImpl>()); - AudioProcessingProperties properties; - properties.enable_sw_echo_cancellation = false; - scoped_refptr<MediaStreamAudioProcessorUnderTest> audio_processor( - new rtc::RefCountedObject<MediaStreamAudioProcessorUnderTest>( - properties, webrtc_audio_device.get())); - - EXPECT_FALSE(audio_processor->using_aec3()); - - // Stop |audio_processor| so that it removes itself from - // |webrtc_audio_device| and clears its pointer to it. - audio_processor->Stop(); -} - } // namespace content diff --git a/chromium/content/renderer/media/stream/media_stream_center.cc b/chromium/content/renderer/media/stream/media_stream_center.cc index f2972e9353a..a5e056ff5ef 100644 --- a/chromium/content/renderer/media/stream/media_stream_center.cc +++ b/chromium/content/renderer/media/stream/media_stream_center.cc @@ -7,6 +7,7 @@ #include <stddef.h> #include <string> +#include <vector> #include "base/command_line.h" #include "base/logging.h" @@ -17,11 +18,12 @@ #include "content/renderer/media/stream/media_stream_source.h" #include "content/renderer/media/stream/media_stream_video_source.h" #include "content/renderer/media/stream/media_stream_video_track.h" +#include "content/renderer/media/stream/processed_local_audio_source.h" #include "content/renderer/media/stream/webaudio_media_stream_source.h" #include "content/renderer/media/webrtc_local_audio_source_provider.h" +#include "media/base/sample_format.h" #include "third_party/blink/public/platform/web_media_constraints.h" #include "third_party/blink/public/platform/web_media_stream.h" -#include "third_party/blink/public/platform/web_media_stream_center_client.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_vector.h" @@ -99,11 +101,9 @@ void CloneNativeVideoMediaStreamTrack( } // namespace -MediaStreamCenter::MediaStreamCenter( - blink::WebMediaStreamCenterClient* client, - PeerConnectionDependencyFactory* factory) {} +MediaStreamCenter::MediaStreamCenter() = default; -MediaStreamCenter::~MediaStreamCenter() {} +MediaStreamCenter::~MediaStreamCenter() = default; void MediaStreamCenter::DidCreateMediaStreamTrack( const blink::WebMediaStreamTrack& track) { @@ -191,4 +191,28 @@ void MediaStreamCenter::DidStopMediaStreamSource( source->StopSource(); } +void MediaStreamCenter::GetSourceSettings( + const blink::WebMediaStreamSource& web_source, + blink::WebMediaStreamTrack::Settings& settings) { + MediaStreamAudioSource* const source = + MediaStreamAudioSource::From(web_source); + if (!source) + return; + + media::AudioParameters audio_parameters = source->GetAudioParameters(); + settings.sample_rate = audio_parameters.sample_rate(); + // kSampleFormatS16 is the format used for all audio input streams. + settings.sample_size = + media::SampleFormatToBitsPerChannel(media::kSampleFormatS16); + settings.channel_count = audio_parameters.channels(); + settings.latency = audio_parameters.GetBufferDuration().InSecondsF(); + + ProcessedLocalAudioSource* const processed_source = + ProcessedLocalAudioSource::From(source); + settings.volume = processed_source + ? static_cast<double>(processed_source->Volume()) / + processed_source->MaxVolume() + : 1.0; +} + } // namespace content diff --git a/chromium/content/renderer/media/stream/media_stream_center.h b/chromium/content/renderer/media/stream/media_stream_center.h index c057c16e9f5..a548a8db632 100644 --- a/chromium/content/renderer/media/stream/media_stream_center.h +++ b/chromium/content/renderer/media/stream/media_stream_center.h @@ -5,9 +5,6 @@ #ifndef CONTENT_RENDERER_MEDIA_STREAM_MEDIA_STREAM_CENTER_H_ #define CONTENT_RENDERER_MEDIA_STREAM_MEDIA_STREAM_CENTER_H_ -#include <map> - -#include "base/compiler_specific.h" #include "base/macros.h" #include "content/common/content_export.h" #include "third_party/blink/public/platform/web_media_stream.h" @@ -16,18 +13,13 @@ namespace blink { class WebAudioSourceProvider; -class WebMediaStreamCenterClient; } namespace content { -class PeerConnectionDependencyFactory; class CONTENT_EXPORT MediaStreamCenter : public blink::WebMediaStreamCenter { public: - // TODO(miu): Remove these constructor args. They are no longer used. - // http://crbug.com/577874 - MediaStreamCenter(blink::WebMediaStreamCenterClient* client, - PeerConnectionDependencyFactory* factory); + MediaStreamCenter(); ~MediaStreamCenter() override; private: @@ -52,6 +44,10 @@ class CONTENT_EXPORT MediaStreamCenter : public blink::WebMediaStreamCenter { void DidStopMediaStreamSource( const blink::WebMediaStreamSource& web_source) override; + void GetSourceSettings( + const blink::WebMediaStreamSource& web_source, + blink::WebMediaStreamTrack::Settings& settings) override; + DISALLOW_COPY_AND_ASSIGN(MediaStreamCenter); }; diff --git a/chromium/content/renderer/media/stream/media_stream_constraints_util.cc b/chromium/content/renderer/media/stream/media_stream_constraints_util.cc index 52a4824eae8..d4111ac35b1 100644 --- a/chromium/content/renderer/media/stream/media_stream_constraints_util.cc +++ b/chromium/content/renderer/media/stream/media_stream_constraints_util.cc @@ -235,16 +235,6 @@ bool GetConstraintValueAsString( return false; } -rtc::Optional<bool> ConstraintToOptional( - const blink::WebMediaConstraints& constraints, - const blink::BooleanConstraint blink::WebMediaTrackConstraintSet::*picker) { - bool value; - if (GetConstraintValueAsBoolean(constraints, picker, &value)) { - return rtc::Optional<bool>(value); - } - return rtc::Optional<bool>(); -} - std::string GetMediaStreamSource( const blink::WebMediaConstraints& constraints) { std::string source; @@ -266,12 +256,13 @@ bool IsDeviceCapture(const blink::WebMediaConstraints& constraints) { VideoTrackAdapterSettings SelectVideoTrackAdapterSettings( const blink::WebMediaTrackConstraintSet& basic_constraint_set, - const ResolutionSet& resolution_set, - const NumericRangeSet<double>& frame_rate_set, + const media_constraints::ResolutionSet& resolution_set, + const media_constraints::NumericRangeSet<double>& frame_rate_set, const media::VideoCaptureFormat& source_format) { - ResolutionSet::Point resolution = resolution_set.SelectClosestPointToIdeal( - basic_constraint_set, source_format.frame_size.height(), - source_format.frame_size.width()); + media_constraints::ResolutionSet::Point resolution = + resolution_set.SelectClosestPointToIdeal( + basic_constraint_set, source_format.frame_size.height(), + source_format.frame_size.width()); int track_max_height = static_cast<int>(std::round(resolution.height())); int track_max_width = static_cast<int>(std::round(resolution.width())); double track_min_aspect_ratio = diff --git a/chromium/content/renderer/media/stream/media_stream_constraints_util.h b/chromium/content/renderer/media/stream/media_stream_constraints_util.h index 0e40d0790ab..fd2267d2086 100644 --- a/chromium/content/renderer/media/stream/media_stream_constraints_util.h +++ b/chromium/content/renderer/media/stream/media_stream_constraints_util.h @@ -16,13 +16,14 @@ #include "third_party/blink/public/platform/modules/mediastream/media_devices.mojom.h" #include "third_party/blink/public/platform/web_media_constraints.h" #include "third_party/blink/public/platform/web_media_stream_source.h" -#include "third_party/webrtc/api/optional.h" namespace content { +namespace media_constraints { class ResolutionSet; template <typename T> class NumericRangeSet; +} // namespace media_constraints // This class represents the output the SelectSettings algorithm for video // constraints (see https://w3c.github.io/mediacapture-main/#dfn-selectsettings) @@ -287,10 +288,6 @@ bool CONTENT_EXPORT GetConstraintValueAsString( const blink::StringConstraint blink::WebMediaTrackConstraintSet::*picker, std::string* value); -rtc::Optional<bool> ConstraintToOptional( - const blink::WebMediaConstraints& constraints, - const blink::BooleanConstraint blink::WebMediaTrackConstraintSet::*picker); - template <typename ConstraintType> bool ConstraintHasMax(const ConstraintType& constraint) { return constraint.HasMax() || constraint.HasExact(); @@ -355,8 +352,8 @@ bool IsDeviceCapture(const blink::WebMediaConstraints& constraints); // |frame_rate_set| are empty. VideoTrackAdapterSettings CONTENT_EXPORT SelectVideoTrackAdapterSettings( const blink::WebMediaTrackConstraintSet& basic_constraint_set, - const ResolutionSet& resolution_set, - const NumericRangeSet<double>& frame_rate_set, + const media_constraints::ResolutionSet& resolution_set, + const media_constraints::NumericRangeSet<double>& frame_rate_set, const media::VideoCaptureFormat& source_format); // Generic distance function between two values for numeric constraints. Based 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 2b48e570ee7..faf854cacbb 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 @@ -11,6 +11,7 @@ #include "base/strings/string_number_conversions.h" #include "content/common/media/media_stream_controls.h" +#include "content/public/common/content_features.h" #include "content/renderer/media/stream/media_stream_audio_source.h" #include "content/renderer/media/stream/media_stream_constraints_util_sets.h" #include "content/renderer/media/stream/media_stream_video_source.h" @@ -22,8 +23,13 @@ namespace content { +using EchoCancellationType = AudioProcessingProperties::EchoCancellationType; + namespace { +template <class T> +using DiscreteSet = media_constraints::DiscreteSet<T>; + enum BoolConstraint { // Constraints not related to audio processing. HOTWORD_ENABLED, @@ -41,7 +47,6 @@ enum BoolConstraint { GOOG_TYPING_NOISE_DETECTION, GOOG_NOISE_SUPPRESSION, GOOG_EXPERIMENTAL_NOISE_SUPPRESSION, - GOOG_BEAMFORMING, GOOG_HIGHPASS_FILTER, GOOG_EXPERIMENTAL_AUTO_GAIN_CONTROL, NUM_BOOL_CONSTRAINTS @@ -67,37 +72,10 @@ const AudioPropertyConstraintPair kAudioPropertyConstraintMap[] = { GOOG_NOISE_SUPPRESSION}, {&AudioProcessingProperties::goog_experimental_noise_suppression, GOOG_EXPERIMENTAL_NOISE_SUPPRESSION}, - {&AudioProcessingProperties::goog_beamforming, GOOG_BEAMFORMING}, {&AudioProcessingProperties::goog_highpass_filter, GOOG_HIGHPASS_FILTER}, {&AudioProcessingProperties::goog_experimental_auto_gain_control, GOOG_EXPERIMENTAL_AUTO_GAIN_CONTROL}}; -// TODO(guidou): Remove this function. http://crbug.com/796955 -std::string MediaPointToString(const media::Point& point) { - std::string point_string; - point_string.append(base::NumberToString(point.x())); - point_string.append(" "); - point_string.append(base::NumberToString(point.y())); - point_string.append(" "); - point_string.append(base::NumberToString(point.z())); - - return point_string; -} - -// TODO(guidou): Remove this function. http://crbug.com/796955 -std::string MediaPointsToString(const std::vector<media::Point>& points) { - std::string points_string; - if (!points.empty()) { - for (size_t i = 0; i < points.size() - 1; ++i) { - points_string.append(MediaPointToString(points[i])); - points_string.append(" "); - } - points_string.append(MediaPointToString(points.back())); - } - - return points_string; -} - // Selects the best value from the nonempty |set|, subject to |constraint|. The // first selection criteria is equality to |constraint.Ideal()|, followed by // equality to |default_value|. There is always a single best value. @@ -153,27 +131,6 @@ std::string SelectString(const DiscreteSet<std::string>& set, return set.FirstElement(); } -// Selects the best value from the nonempty |set|, subject to |constraint|. The -// only decision criteria is inclusion in |constraint.Ideal()|. If there is no -// single best value in |set|, returns nullopt. -base::Optional<std::string> SelectOptionalString( - const DiscreteSet<std::string>& set, - const blink::StringConstraint& constraint) { - DCHECK(!set.IsEmpty()); - if (constraint.HasIdeal()) { - for (const auto& ideal_candidate : constraint.Ideal()) { - std::string candidate = ideal_candidate.Utf8(); - if (set.Contains(candidate)) - return candidate; - } - } - - if (set.is_universal()) - return base::Optional<std::string>(); - - return set.FirstElement(); -} - bool SelectUseEchoCancellation(base::Optional<bool> echo_cancellation, base::Optional<bool> goog_echo_cancellation, bool is_device_capture) { @@ -195,12 +152,16 @@ std::vector<std::string> GetEchoCancellationTypesFromParameters( if (audio_parameters.effects() & (media::AudioParameters::EXPERIMENTAL_ECHO_CANCELLER | media::AudioParameters::ECHO_CANCELLER)) { - // If the hardware supports echo cancellation, return both echo cancellers. + // If the system/hardware supports echo cancellation, return all echo + // cancellers. return {blink::kEchoCancellationTypeBrowser, + blink::kEchoCancellationTypeAec3, blink::kEchoCancellationTypeSystem}; } - // The browser echo canceller is always available. - return {blink::kEchoCancellationTypeBrowser}; + + // The browser and AEC3 echo cancellers are always available. + return {blink::kEchoCancellationTypeBrowser, + blink::kEchoCancellationTypeAec3}; } // This class represents all the candidates settings for a single audio device. @@ -215,6 +176,9 @@ class SingleDeviceCandidateSet { if (!capability.DeviceID().empty()) device_id_set_ = DiscreteSet<std::string>({capability.DeviceID()}); + if (!capability.GroupID().empty()) + group_id_set_ = DiscreteSet<std::string>({capability.GroupID()}); + MediaStreamAudioSource* source = capability.source(); // Set up echo cancellation types. Depending on if we have a source or not @@ -235,38 +199,46 @@ class SingleDeviceCandidateSet { // Properties related with audio processing. AudioProcessingProperties properties; - if (ProcessedLocalAudioSource* processed_source = - ProcessedLocalAudioSource::From(source)) { + ProcessedLocalAudioSource* processed_source = + ProcessedLocalAudioSource::From(source); + if (processed_source) properties = processed_source->audio_processing_properties(); - } else { + else properties.DisableDefaultProperties(); - } - - const bool experimental_hardware_cancellation_available = - properties.enable_experimental_hw_echo_cancellation && - (parameters_.effects() & - media::AudioParameters::EXPERIMENTAL_ECHO_CANCELLER); - const bool hardware_echo_cancellation_available = + const bool system_echo_cancellation_available = + (properties.echo_cancellation_type == + EchoCancellationType::kEchoCancellationSystem || + !processed_source) && parameters_.effects() & media::AudioParameters::ECHO_CANCELLER; - const bool hardware_echo_cancellation_enabled = - !properties.disable_hw_echo_cancellation && - (hardware_echo_cancellation_available || - experimental_hardware_cancellation_available); + const bool experimental_system_cancellation_available = + properties.echo_cancellation_type == + EchoCancellationType::kEchoCancellationSystem && + parameters_.effects() & + media::AudioParameters::EXPERIMENTAL_ECHO_CANCELLER; + + const bool system_echo_cancellation_enabled = + system_echo_cancellation_available || + experimental_system_cancellation_available; const bool echo_cancellation_enabled = - properties.enable_sw_echo_cancellation || - hardware_echo_cancellation_enabled; + properties.EchoCancellationIsWebRtcProvided() || + system_echo_cancellation_enabled; bool_sets_[ECHO_CANCELLATION] = DiscreteSet<bool>({echo_cancellation_enabled}); bool_sets_[GOOG_ECHO_CANCELLATION] = bool_sets_[ECHO_CANCELLATION]; - if (properties.enable_sw_echo_cancellation) { + if (properties.echo_cancellation_type == + EchoCancellationType::kEchoCancellationAec2) { echo_cancellation_type_set_ = DiscreteSet<std::string>({blink::kEchoCancellationTypeBrowser}); - } else if (hardware_echo_cancellation_enabled) { + } else if (properties.echo_cancellation_type == + EchoCancellationType::kEchoCancellationAec3) { + echo_cancellation_type_set_ = + DiscreteSet<std::string>({blink::kEchoCancellationTypeAec3}); + } else if (system_echo_cancellation_enabled) { echo_cancellation_type_set_ = DiscreteSet<std::string>({blink::kEchoCancellationTypeSystem}); } @@ -285,15 +257,6 @@ class SingleDeviceCandidateSet { DCHECK(!bool_set.IsEmpty()); } #endif - - // This fails with input strings that are equivalent to - // |properties.goog_array_geometry|, but not exactly equal to the string - // returned by MediaPointsToString(). - // TODO(guidou): Change |goog_array_geometry_set_| to be a set of vectors of - // points instead of a set of strings. http://crbug.com/796955 - std::string mic_positions = - MediaPointsToString(properties.goog_array_geometry); - goog_array_geometry_set_ = DiscreteSet<std::string>({mic_positions}); } // Accessors @@ -307,22 +270,23 @@ class SingleDeviceCandidateSet { void ApplyConstraintSet( const blink::WebMediaTrackConstraintSet& constraint_set) { device_id_set_ = device_id_set_.Intersection( - StringSetFromConstraint(constraint_set.device_id)); + media_constraints::StringSetFromConstraint(constraint_set.device_id)); if (device_id_set_.IsEmpty()) { failed_constraint_name_ = constraint_set.device_id.GetName(); return; } - goog_array_geometry_set_ = goog_array_geometry_set_.Intersection( - StringSetFromConstraint(constraint_set.goog_array_geometry)); - if (goog_array_geometry_set_.IsEmpty()) { - failed_constraint_name_ = constraint_set.goog_array_geometry.GetName(); + group_id_set_ = group_id_set_.Intersection( + media_constraints::StringSetFromConstraint(constraint_set.group_id)); + if (group_id_set_.IsEmpty()) { + failed_constraint_name_ = constraint_set.group_id.GetName(); return; } for (size_t i = 0; i < NUM_BOOL_CONSTRAINTS; ++i) { - bool_sets_[i] = bool_sets_[i].Intersection( - BoolSetFromConstraint(constraint_set.*kBlinkBoolConstraintFields[i])); + bool_sets_[i] = + bool_sets_[i].Intersection(media_constraints::BoolSetFromConstraint( + constraint_set.*kBlinkBoolConstraintFields[i])); if (bool_sets_[i].IsEmpty()) { failed_constraint_name_ = (constraint_set.*kBlinkBoolConstraintFields[i]).GetName(); @@ -342,7 +306,8 @@ class SingleDeviceCandidateSet { } echo_cancellation_type_set_ = echo_cancellation_type_set_.Intersection( - StringSetFromConstraint(constraint_set.echo_cancellation_type)); + media_constraints::StringSetFromConstraint( + constraint_set.echo_cancellation_type)); if (echo_cancellation_type_set_.IsEmpty()) { failed_constraint_name_ = constraint_set.echo_cancellation_type.GetName(); return; @@ -373,6 +338,16 @@ class SingleDeviceCandidateSet { } } + if (constraint_set.group_id.HasIdeal()) { + for (const blink::WebString& ideal_value : + constraint_set.group_id.Ideal()) { + if (group_id_set_.Contains(ideal_value.Utf8())) { + fitness += 1.0; + break; + } + } + } + for (size_t i = 0; i < NUM_BOOL_CONSTRAINTS; ++i) { if ((constraint_set.*kBlinkBoolConstraintFields[i]).HasIdeal() && bool_sets_[i].Contains( @@ -381,16 +356,6 @@ class SingleDeviceCandidateSet { } } - if (constraint_set.goog_array_geometry.HasIdeal()) { - for (const blink::WebString& ideal_value : - constraint_set.goog_array_geometry.Ideal()) { - if (goog_array_geometry_set_.Contains(ideal_value.Utf8())) { - fitness += 1.0; - break; - } - } - } - // If echo cancellation constraint is not set to true, the type shall be // ignored. if ((constraint_set.*kBlinkBoolConstraintFields[ECHO_CANCELLATION]) @@ -441,10 +406,9 @@ class SingleDeviceCandidateSet { } private: - void SelectEchoCancellationFlags( + EchoCancellationType SelectEchoCancellationType( const blink::StringConstraint& echo_cancellation_type, - const media::AudioParameters& audio_parameters, - AudioProcessingProperties* properties_out) const { + const media::AudioParameters& audio_parameters) const { // Try to use an ideal candidate, if supplied. base::Optional<std::string> selected_type; if (echo_cancellation_type.HasIdeal()) { @@ -466,26 +430,38 @@ class SingleDeviceCandidateSet { } } - // Set properties based the type selected. + // Return type based the selected type. if (selected_type == blink::kEchoCancellationTypeBrowser) { - properties_out->enable_sw_echo_cancellation = true; - properties_out->disable_hw_echo_cancellation = true; - properties_out->enable_experimental_hw_echo_cancellation = false; + return EchoCancellationType::kEchoCancellationAec2; + } else if (selected_type == blink::kEchoCancellationTypeAec3) { + return EchoCancellationType::kEchoCancellationAec3; } else if (selected_type == blink::kEchoCancellationTypeSystem) { - properties_out->enable_sw_echo_cancellation = false; - properties_out->disable_hw_echo_cancellation = false; - properties_out->enable_experimental_hw_echo_cancellation = true; - } else { - // If no type has been selected, choose 'system' if the device has the - // ECHO_CANCELLER flag set. Choose 'browser' otherwise. Never - // automatically enable an experimental hardware echo canceller. - const bool has_hw_echo_canceller = - audio_parameters.IsValid() && - (audio_parameters.effects() & media::AudioParameters::ECHO_CANCELLER); - properties_out->enable_sw_echo_cancellation = !has_hw_echo_canceller; - properties_out->disable_hw_echo_cancellation = !has_hw_echo_canceller; - properties_out->enable_experimental_hw_echo_cancellation = false; + return EchoCancellationType::kEchoCancellationSystem; + } + + // If no type has been selected, choose system if the device has the + // ECHO_CANCELLER flag set. Never automatically enable an experimental + // system echo canceller. + if (audio_parameters.IsValid() && + audio_parameters.effects() & media::AudioParameters::ECHO_CANCELLER) { + return EchoCancellationType::kEchoCancellationSystem; } + + // Finally, choose the browser provided AEC2 or AEC3 based on an optional + // override setting for AEC3 or feature. + // 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. + base::Optional<bool> override_aec3; + scoped_refptr<AecDumpMessageFilter> aec_dump_message_filter = + AecDumpMessageFilter::Get(); + if (aec_dump_message_filter) + override_aec3 = aec_dump_message_filter->GetOverrideAec3(); + const bool use_aec3 = override_aec3.value_or( + base::FeatureList::IsEnabled(features::kWebRtcUseEchoCanceller3)); + + return use_aec3 ? EchoCancellationType::kEchoCancellationAec3 + : EchoCancellationType::kEchoCancellationAec2; } // Returns the audio-processing properties supported by this @@ -513,17 +489,17 @@ class SingleDeviceCandidateSet { AudioProcessingProperties properties; if (use_echo_cancellation) { - SelectEchoCancellationFlags(basic_constraint_set.echo_cancellation_type, - parameters_, &properties); + properties.echo_cancellation_type = SelectEchoCancellationType( + basic_constraint_set.echo_cancellation_type, parameters_); } else { - properties.enable_sw_echo_cancellation = false; - properties.disable_hw_echo_cancellation = true; - properties.enable_experimental_hw_echo_cancellation = false; + properties.echo_cancellation_type = + EchoCancellationType::kEchoCancellationDisabled; } properties.disable_hw_noise_suppression = should_disable_hardware_noise_suppression && - !properties.disable_hw_echo_cancellation; + properties.echo_cancellation_type == + EchoCancellationType::kEchoCancellationSystem; properties.goog_audio_mirroring = SelectBool(bool_sets_[GOOG_AUDIO_MIRRORING], @@ -538,18 +514,6 @@ class SingleDeviceCandidateSet { default_audio_processing_value && properties.*entry.audio_property); } - base::Optional<std::string> array_geometry = SelectOptionalString( - goog_array_geometry_set_, basic_constraint_set.goog_array_geometry); - std::vector<media::Point> parsed_positions; - if (array_geometry) - parsed_positions = media::ParsePointsFromString(*array_geometry); - bool are_valid_parsed_positions = - !parsed_positions.empty() || - (array_geometry && array_geometry->empty()); - properties.goog_array_geometry = are_valid_parsed_positions - ? std::move(parsed_positions) - : parameters_.mic_positions(); - return properties; } @@ -569,15 +533,14 @@ class SingleDeviceCandidateSet { &blink::WebMediaTrackConstraintSet::goog_noise_suppression, &blink::WebMediaTrackConstraintSet:: goog_experimental_noise_suppression, - &blink::WebMediaTrackConstraintSet::goog_beamforming, &blink::WebMediaTrackConstraintSet::goog_highpass_filter, &blink::WebMediaTrackConstraintSet:: goog_experimental_auto_gain_control}; const char* failed_constraint_name_ = nullptr; DiscreteSet<std::string> device_id_set_; + DiscreteSet<std::string> group_id_set_; std::array<DiscreteSet<bool>, NUM_BOOL_CONSTRAINTS> bool_sets_; - DiscreteSet<std::string> goog_array_geometry_set_; DiscreteSet<std::string> echo_cancellation_type_set_; media::AudioParameters parameters_; }; @@ -587,16 +550,15 @@ constexpr blink::BooleanConstraint blink::WebMediaTrackConstraintSet::* const // This class represents a set of possible candidate settings. // The SelectSettings algorithm starts with a set containing all possible -// candidates based on hardware capabilities and/or allowed values for supported -// properties. The set is then reduced progressively as the basic and advanced -// constraint sets are applied. -// In the end, if the set of candidates is empty, SelectSettings fails. -// If not, the ideal values (if any) or tie breaker rules are used to select -// the final settings based on the candidates that survived the application -// of the constraint sets. -// This class is implemented as a collection of more specific sets for the -// various supported properties. If any of the specific sets is empty, the -// whole AudioCaptureCandidates set is considered empty as well. +// candidates based on system/hardware capabilities and/or allowed values for +// supported properties. The set is then reduced progressively as the basic and +// advanced constraint sets are applied. In the end, if the set of candidates is +// empty, SelectSettings fails. If not, the ideal values (if any) or tie breaker +// rules are used to select the final settings based on the candidates that +// survived the application of the constraint sets. This class is implemented as +// a collection of more specific sets for the various supported properties. If +// any of the specific sets is empty, the whole AudioCaptureCandidates set is +// considered empty as well. class AudioCaptureCandidates { public: AudioCaptureCandidates( @@ -689,15 +651,26 @@ AudioDeviceCaptureCapability::AudioDeviceCaptureCapability( AudioDeviceCaptureCapability::AudioDeviceCaptureCapability( std::string device_id, + std::string group_id, const media::AudioParameters& parameters) - : device_id_(std::move(device_id)), parameters_(parameters) { + : device_id_(std::move(device_id)), + group_id_(std::move(group_id)), + parameters_(parameters) { DCHECK(!device_id_.empty()); } +AudioDeviceCaptureCapability::AudioDeviceCaptureCapability( + const AudioDeviceCaptureCapability& other) = default; + const std::string& AudioDeviceCaptureCapability::DeviceID() const { return source_ ? source_->device().id : device_id_; } +const std::string& AudioDeviceCaptureCapability::GroupID() const { + return source_ && source_->device().group_id ? *source_->device().group_id + : group_id_; +} + const media::AudioParameters& AudioDeviceCaptureCapability::Parameters() const { return source_ ? source_->device().input : parameters_; } diff --git a/chromium/content/renderer/media/stream/media_stream_constraints_util_audio.h b/chromium/content/renderer/media/stream/media_stream_constraints_util_audio.h index 6eb84383ff8..c1006f6c6d9 100644 --- a/chromium/content/renderer/media/stream/media_stream_constraints_util_audio.h +++ b/chromium/content/renderer/media/stream/media_stream_constraints_util_audio.h @@ -41,10 +41,12 @@ class CONTENT_EXPORT AudioDeviceCaptureCapability { AudioDeviceCaptureCapability(); // This creates an AudioDeviceCaptureCapability where the device ID is limited - // to |device_id| and other settings are limited by the given |parameters|. - // |device_id| must not be empty. Intended to be used by getUserMedia() with - // device capture for devices that are not currently in use. + // to |device_id|, the group ID is limited to |group_id| and other settings + // are limited by the given |parameters|. |device_id| must not be empty. + // Intended to be used by getUserMedia() with device capture for devices that + // are not currently in use. AudioDeviceCaptureCapability(std::string device_id, + std::string group_id, const media::AudioParameters& parameters); // This creates an AudioDeviceCaptureCapability where the device ID and other @@ -53,6 +55,8 @@ class CONTENT_EXPORT AudioDeviceCaptureCapability { // getUserMedia() with device capture for devices that are currently in use. explicit AudioDeviceCaptureCapability(MediaStreamAudioSource* source); + AudioDeviceCaptureCapability(const AudioDeviceCaptureCapability& other); + // If this capability represents a device currently in use, this method // returns a pointer to the MediaStreamAudioSource object associated with the // device. Otherwise, it returns null. @@ -64,6 +68,9 @@ class CONTENT_EXPORT AudioDeviceCaptureCapability { // processing constraints. const std::string& DeviceID() const; + // Returns the group ID of the device associated with this capability. + const std::string& GroupID() const; + // Returns the audio parameters for the device associated with this // capability. If DeviceID() returns an empty string, these parameters contain // default values that work well for content capture. @@ -72,6 +79,7 @@ class CONTENT_EXPORT AudioDeviceCaptureCapability { private: MediaStreamAudioSource* source_ = nullptr; std::string device_id_; + std::string group_id_; media::AudioParameters parameters_; }; @@ -81,17 +89,17 @@ using AudioDeviceCaptureCapabilities = // This function implements the SelectSettings algorithm for audio tracks as // described in https://w3c.github.io/mediacapture-main/#dfn-selectsettings // The algorithm starts with a set containing all possible candidate settings -// based on hardware capabilities (passed via the |capabilities| parameter) and -// supported values for properties not involved in device selection. Candidates -// that do not support the basic constraint set from |constraints| are removed. -// If the set of candidates is empty after this step, the function returns an -// AudioCaptureSettings object without value and whose failed_constraint_name() -// method returns the name of one of the (possibly many) constraints that could -// not be satisfied or an empty string if the set of candidates was initially -// empty (e.g., if there are no devices in the system). -// After the basic constraint set is applied, advanced constraint sets are -// applied. If no candidates can satisfy an advanced set, the advanced set is -// ignored, otherwise the candidates that cannot satisfy the advanced set are +// based on system/hardware capabilities (passed via the |capabilities| +// parameter) and supported values for properties not involved in device +// selection. Candidates that do not support the basic constraint set from +// |constraints| are removed. If the set of candidates is empty after this step, +// the function returns an AudioCaptureSettings object without value and whose +// failed_constraint_name() method returns the name of one of the (possibly +// many) constraints that could not be satisfied or an empty string if the set +// of candidates was initially empty (e.g., if there are no devices in the +// system). After the basic constraint set is applied, advanced constraint sets +// are applied. If no candidates can satisfy an advanced set, the advanced set +// is ignored, otherwise the candidates that cannot satisfy the advanced set are // removed. // Once all constraint sets are applied, the result is selected from the // remaining candidates by giving preference to candidates closest to the ideal @@ -112,16 +120,10 @@ using AudioDeviceCaptureCapabilities = // * Audio processing. The remaining constraints are used to control audio // processing. This is how audio-processing properties are set for device // capture(see the content::AudioProcessingProperties struct) : -// - enable_sw_echo_cancellation: If the selected device has hardware echo -// cancellation, software echo cancellation is disabled regardless of -// any constraint values. Otherwise, it is enabled by default unless -// either the echo_cancellation or the goog_echo_cancellation constraint -// has a final value of false after applying all constraint sets. Note -// that if these constraints have contradictory values, SelectSettings -// fails and returns no value. -// - disable_hw_echo_cancellation: For devices that have hardware echo -// cancellation, the feature is disabled if the echo_cancellation or -// goog_echo_cancellation constraints have a final value of false. +// - echo_cancellation_type: mapped from the experimental constraint with +// the same name. "System" is selected only if the device supports it. +// If constraint is not specified, "system" is selected if supported, +// with exception for experimental system echo cancellation. // - goog_audio_mirroring: This property is mapped directly from the final // value of the goog_audio_mirroring constraint. If no value is // explicitly specified, the default value is false. @@ -140,7 +142,7 @@ using AudioDeviceCaptureCapabilities = // all constraints and properties. For example, the echo_cancellation and // goog_echo_cancellation constraints are not directly mapped to any // property, but they, together with hardware characteristics, influence the -// enabling and disabling of software and hardware echo cancellation. +// selection of echo cancellation type. // Moreover, the echo_cancellation constraint influences most other // audio-processing properties for which no explicit value is provided in // their corresponding constraints. diff --git a/chromium/content/renderer/media/stream/media_stream_constraints_util_audio_unittest.cc b/chromium/content/renderer/media/stream/media_stream_constraints_util_audio_unittest.cc index 00bb3314bd7..2977c75f436 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 @@ -25,6 +25,8 @@ namespace content { +using EchoCancellationType = AudioProcessingProperties::EchoCancellationType; + namespace { using BoolSetFunction = void (blink::BooleanConstraint::*)(bool); @@ -59,6 +61,22 @@ static bool Contains(const std::vector<T>& vector, T value) { } // namespace +// This class is only used for setting |override_aec3_|. We simply inject the +// current task runner since they are not used. +class AecDumpMessageFilterForTest : public AecDumpMessageFilter { + public: + AecDumpMessageFilterForTest() + : AecDumpMessageFilter(base::MessageLoopCurrent::Get()->task_runner(), + base::MessageLoopCurrent::Get()->task_runner()) {} + + void set_override_aec3(base::Optional<bool> override_aec3) { + override_aec3_ = override_aec3; + } + + protected: + ~AecDumpMessageFilterForTest() override {} +}; + class MediaStreamConstraintsUtilAudioTest : public testing::TestWithParam<std::string> { public: @@ -66,31 +84,23 @@ class MediaStreamConstraintsUtilAudioTest ResetFactory(); if (IsDeviceCapture()) { capabilities_.emplace_back( - "default_device", + "default_device", "fake_group1", media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, media::CHANNEL_LAYOUT_STEREO, media::AudioParameters::kAudioCDSampleRate, 1000)); - media::AudioParameters hw_echo_canceller_parameters( + media::AudioParameters system_echo_canceller_parameters( media::AudioParameters::AUDIO_PCM_LOW_LATENCY, media::CHANNEL_LAYOUT_STEREO, media::AudioParameters::kAudioCDSampleRate, 1000); - hw_echo_canceller_parameters.set_effects( + system_echo_canceller_parameters.set_effects( media::AudioParameters::ECHO_CANCELLER); - capabilities_.emplace_back("hw_echo_canceller_device", - hw_echo_canceller_parameters); - - media::AudioParameters geometry_parameters( - media::AudioParameters::AUDIO_PCM_LOW_LATENCY, - media::CHANNEL_LAYOUT_STEREO, - media::AudioParameters::kAudioCDSampleRate, 1000); - geometry_parameters.set_mic_positions(kMicPositions); - capabilities_.emplace_back("geometry device", geometry_parameters); + capabilities_.emplace_back("system_echo_canceller_device", "fake_group2", + system_echo_canceller_parameters); default_device_ = &capabilities_[0]; - hw_echo_canceller_device_ = &capabilities_[1]; - geometry_device_ = &capabilities_[2]; + system_echo_canceller_device_ = &capabilities_[1]; } else { // For content capture, use a single capability that admits all possible // settings. @@ -99,15 +109,16 @@ class MediaStreamConstraintsUtilAudioTest } protected: - void MakeHardwareEchoCancellerDeviceExperimental() { - media::AudioParameters experimental_hw_echo_canceller_parameters( + void MakeSystemEchoCancellerDeviceExperimental() { + media::AudioParameters experimental_system_echo_canceller_parameters( media::AudioParameters::AUDIO_PCM_LOW_LATENCY, media::CHANNEL_LAYOUT_STEREO, media::AudioParameters::kAudioCDSampleRate, 1000); - experimental_hw_echo_canceller_parameters.set_effects( + experimental_system_echo_canceller_parameters.set_effects( media::AudioParameters::EXPERIMENTAL_ECHO_CANCELLER); - capabilities_[1] = {"experimental_hw_echo_canceller_device", - experimental_hw_echo_canceller_parameters}; + capabilities_[1] = {"experimental_system_echo_canceller_device", + "fake_group3", + experimental_system_echo_canceller_parameters}; } void SetMediaStreamSource(const std::string& source) {} @@ -160,13 +171,13 @@ class MediaStreamConstraintsUtilAudioTest } std::unique_ptr<LocalMediaStreamAudioSource> GetLocalMediaStreamAudioSource( - bool enable_hardware_echo_canceller, + bool enable_system_echo_canceller, bool hotword_enabled, bool disable_local_echo, bool render_to_associated_sink) { MediaStreamDevice device; device.type = GetMediaStreamType(); - if (enable_hardware_echo_canceller) + if (enable_system_echo_canceller) device.input.set_effects(media::AudioParameters::ECHO_CANCELLER); if (render_to_associated_sink) device.matched_output_device_id = std::string("some_device_id"); @@ -214,19 +225,6 @@ class MediaStreamConstraintsUtilAudioTest const auto& properties = result.audio_processing_properties(); if (!Contains(exclude_audio_properties, - &AudioProcessingProperties::enable_sw_echo_cancellation)) { - EXPECT_TRUE(properties.enable_sw_echo_cancellation); - } - if (!Contains(exclude_audio_properties, - &AudioProcessingProperties::disable_hw_echo_cancellation)) { - EXPECT_TRUE(properties.disable_hw_echo_cancellation); - } - if (!Contains(exclude_audio_properties, - &AudioProcessingProperties:: - enable_experimental_hw_echo_cancellation)) { - EXPECT_FALSE(properties.enable_experimental_hw_echo_cancellation); - } - if (!Contains(exclude_audio_properties, &AudioProcessingProperties::goog_audio_mirroring)) { EXPECT_FALSE(properties.goog_audio_mirroring); } @@ -253,10 +251,6 @@ class MediaStreamConstraintsUtilAudioTest EXPECT_TRUE(properties.goog_experimental_noise_suppression); } if (!Contains(exclude_audio_properties, - &AudioProcessingProperties::goog_beamforming)) { - EXPECT_TRUE(properties.goog_beamforming); - } - if (!Contains(exclude_audio_properties, &AudioProcessingProperties::goog_highpass_filter)) { EXPECT_TRUE(properties.goog_highpass_filter); } @@ -287,19 +281,6 @@ class MediaStreamConstraintsUtilAudioTest const auto& properties = result.audio_processing_properties(); if (!Contains(exclude_audio_properties, - &AudioProcessingProperties::enable_sw_echo_cancellation)) { - EXPECT_FALSE(properties.enable_sw_echo_cancellation); - } - if (!Contains(exclude_audio_properties, - &AudioProcessingProperties::disable_hw_echo_cancellation)) { - EXPECT_TRUE(properties.disable_hw_echo_cancellation); - } - if (!Contains(exclude_audio_properties, - &AudioProcessingProperties:: - enable_experimental_hw_echo_cancellation)) { - EXPECT_FALSE(properties.enable_experimental_hw_echo_cancellation); - } - if (!Contains(exclude_audio_properties, &AudioProcessingProperties::goog_audio_mirroring)) { EXPECT_FALSE(properties.goog_audio_mirroring); } @@ -326,10 +307,6 @@ class MediaStreamConstraintsUtilAudioTest EXPECT_FALSE(properties.goog_experimental_noise_suppression); } if (!Contains(exclude_audio_properties, - &AudioProcessingProperties::goog_beamforming)) { - EXPECT_FALSE(properties.goog_beamforming); - } - if (!Contains(exclude_audio_properties, &AudioProcessingProperties::goog_highpass_filter)) { EXPECT_FALSE(properties.goog_highpass_filter); } @@ -353,6 +330,17 @@ class MediaStreamConstraintsUtilAudioTest } } + void CheckEchoCancellationTypeDefault(const AudioCaptureSettings& result) { + const auto& properties = result.audio_processing_properties(); + if (IsDeviceCapture()) { + EXPECT_EQ(properties.echo_cancellation_type, + EchoCancellationType::kEchoCancellationAec2); + } else { + EXPECT_EQ(properties.echo_cancellation_type, + EchoCancellationType::kEchoCancellationDisabled); + } + } + void CheckDevice(const AudioDeviceCaptureCapability& expected_device, const AudioCaptureSettings& result) { EXPECT_EQ(expected_device.DeviceID(), result.device_id()); @@ -371,23 +359,18 @@ class MediaStreamConstraintsUtilAudioTest EXPECT_TRUE(result.device_id().empty()); } - void CheckGeometryDefaults(const AudioCaptureSettings& result) { - EXPECT_TRUE( - result.audio_processing_properties().goog_array_geometry.empty()); - } - void CheckAllDefaults( const AudioSettingsBoolMembers& exclude_main_settings, const AudioPropertiesBoolMembers& exclude_audio_properties, const AudioCaptureSettings& result) { CheckBoolDefaults(exclude_main_settings, exclude_audio_properties, result); + CheckEchoCancellationTypeDefault(result); CheckDeviceDefaults(result); - CheckGeometryDefaults(result); } // Assumes that echoCancellation is set to true as a basic, exact constraint. void CheckAudioProcessingPropertiesForExactEchoCancellationType( - bool request_hw_echo_cancellation, + const blink::WebString& echo_cancellation_type_constraint, const AudioCaptureSettings& result) { const AudioProcessingProperties& properties = result.audio_processing_properties(); @@ -397,31 +380,28 @@ class MediaStreamConstraintsUtilAudioTest // With content capture, the echo_cancellation constraint controls // only the echo_cancellation properties. The other audio processing // properties default to false. - const bool enable_sw_audio_processing = IsDeviceCapture(); - - if (IsDeviceCapture()) { - EXPECT_NE(request_hw_echo_cancellation, - properties.enable_sw_echo_cancellation); - EXPECT_NE(request_hw_echo_cancellation, - properties.disable_hw_echo_cancellation); - EXPECT_EQ(request_hw_echo_cancellation, - properties.enable_experimental_hw_echo_cancellation); - } else { - EXPECT_TRUE(properties.enable_sw_echo_cancellation); - EXPECT_TRUE(properties.disable_hw_echo_cancellation); - EXPECT_FALSE(properties.enable_experimental_hw_echo_cancellation); + const EchoCancellationType expected_ec_type = + GetEchoCancellationTypeFromConstraintString( + echo_cancellation_type_constraint); + if (!IsDeviceCapture()) { + ASSERT_NE(EchoCancellationType::kEchoCancellationSystem, + expected_ec_type); } - EXPECT_EQ(enable_sw_audio_processing, properties.goog_auto_gain_control); - CheckGoogExperimentalEchoCancellationDefault(properties, - enable_sw_audio_processing); - EXPECT_EQ(enable_sw_audio_processing, + EXPECT_EQ(expected_ec_type, properties.echo_cancellation_type); + + const bool enable_webrtc_audio_processing = IsDeviceCapture(); + EXPECT_EQ(enable_webrtc_audio_processing, + properties.goog_auto_gain_control); + CheckGoogExperimentalEchoCancellationDefault( + properties, enable_webrtc_audio_processing); + EXPECT_EQ(enable_webrtc_audio_processing, properties.goog_typing_noise_detection); - EXPECT_EQ(enable_sw_audio_processing, properties.goog_noise_suppression); - EXPECT_EQ(enable_sw_audio_processing, + EXPECT_EQ(enable_webrtc_audio_processing, + properties.goog_noise_suppression); + EXPECT_EQ(enable_webrtc_audio_processing, properties.goog_experimental_noise_suppression); - EXPECT_EQ(enable_sw_audio_processing, properties.goog_beamforming); - EXPECT_EQ(enable_sw_audio_processing, properties.goog_highpass_filter); - EXPECT_EQ(enable_sw_audio_processing, + EXPECT_EQ(enable_webrtc_audio_processing, properties.goog_highpass_filter); + EXPECT_EQ(enable_webrtc_audio_processing, properties.goog_experimental_auto_gain_control); // The following are not audio processing. @@ -431,9 +411,11 @@ class MediaStreamConstraintsUtilAudioTest result.disable_local_echo()); EXPECT_FALSE(result.render_to_associated_sink()); if (IsDeviceCapture()) { - CheckDevice(request_hw_echo_cancellation ? *hw_echo_canceller_device_ - : *default_device_, - result); + CheckDevice( + expected_ec_type == EchoCancellationType::kEchoCancellationSystem + ? *system_echo_canceller_device_ + : *default_device_, + result); } else { EXPECT_TRUE(result.device_id().empty()); } @@ -444,15 +426,13 @@ class MediaStreamConstraintsUtilAudioTest const AudioProcessingProperties& properties = result.audio_processing_properties(); - EXPECT_FALSE(properties.enable_sw_echo_cancellation); - EXPECT_FALSE(properties.disable_hw_echo_cancellation); - EXPECT_TRUE(properties.enable_experimental_hw_echo_cancellation); + EXPECT_EQ(EchoCancellationType::kEchoCancellationSystem, + properties.echo_cancellation_type); EXPECT_TRUE(properties.goog_auto_gain_control); CheckGoogExperimentalEchoCancellationDefault(properties, true); EXPECT_TRUE(properties.goog_typing_noise_detection); EXPECT_TRUE(properties.goog_noise_suppression); EXPECT_TRUE(properties.goog_experimental_noise_suppression); - EXPECT_TRUE(properties.goog_beamforming); EXPECT_TRUE(properties.goog_highpass_filter); EXPECT_TRUE(properties.goog_experimental_auto_gain_control); @@ -462,17 +442,34 @@ class MediaStreamConstraintsUtilAudioTest EXPECT_EQ(GetMediaStreamSource() != kMediaStreamSourceDesktop, result.disable_local_echo()); EXPECT_FALSE(result.render_to_associated_sink()); - CheckDevice(*hw_echo_canceller_device_, result); + CheckDevice(*system_echo_canceller_device_, result); + } + + EchoCancellationType GetEchoCancellationTypeFromConstraintString( + const blink::WebString& constraint_string) { + if (constraint_string == kEchoCancellationTypeValues[0]) + return EchoCancellationType::kEchoCancellationAec2; + if (constraint_string == kEchoCancellationTypeValues[1]) + return EchoCancellationType::kEchoCancellationAec3; + if (constraint_string == kEchoCancellationTypeValues[2]) + return EchoCancellationType::kEchoCancellationSystem; + + ADD_FAILURE() << "Invalid echo cancellation type constraint: " + << constraint_string.Ascii(); + return EchoCancellationType::kEchoCancellationDisabled; } MockConstraintFactory constraint_factory_; AudioDeviceCaptureCapabilities capabilities_; const AudioDeviceCaptureCapability* default_device_ = nullptr; - const AudioDeviceCaptureCapability* hw_echo_canceller_device_ = nullptr; - const AudioDeviceCaptureCapability* geometry_device_ = nullptr; + const AudioDeviceCaptureCapability* system_echo_canceller_device_ = nullptr; const std::vector<media::Point> kMicPositions = {{8, 8, 8}, {4, 4, 4}}; + + // TODO(grunell): Store these as separate constants and compare against those + // in tests, instead of indexing the vector. const std::vector<blink::WebString> kEchoCancellationTypeValues = { blink::WebString::FromASCII("browser"), + blink::WebString::FromASCII("aec3"), blink::WebString::FromASCII("system")}; private: @@ -541,7 +538,6 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, SingleBoolConstraint) { &AudioProcessingProperties::goog_typing_noise_detection, &AudioProcessingProperties::goog_noise_suppression, &AudioProcessingProperties::goog_experimental_noise_suppression, - &AudioProcessingProperties::goog_beamforming, &AudioProcessingProperties::goog_highpass_filter, &AudioProcessingProperties::goog_experimental_auto_gain_control}; @@ -556,7 +552,6 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, SingleBoolConstraint) { &blink::WebMediaTrackConstraintSet::goog_noise_suppression, &blink::WebMediaTrackConstraintSet:: goog_experimental_noise_suppression, - &blink::WebMediaTrackConstraintSet::goog_beamforming, &blink::WebMediaTrackConstraintSet::goog_highpass_filter, &blink::WebMediaTrackConstraintSet:: goog_experimental_auto_gain_control, @@ -608,7 +603,7 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, ExactArbitraryDeviceID) { EXPECT_EQ(kArbitraryDeviceID, result.device_id()); CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(), result); - CheckGeometryDefaults(result); + CheckEchoCancellationTypeDefault(result); } } @@ -628,7 +623,7 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, IdealArbitraryDeviceID) { EXPECT_EQ(kArbitraryDeviceID, result.device_id()); CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(), result); - CheckGeometryDefaults(result); + CheckEchoCancellationTypeDefault(result); } TEST_P(MediaStreamConstraintsUtilAudioTest, ExactValidDeviceID) { @@ -638,30 +633,52 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, ExactValidDeviceID) { auto result = SelectSettings(); EXPECT_TRUE(result.HasValue()); CheckDevice(device, result); - CheckBoolDefaults( - AudioSettingsBoolMembers(), - {&AudioProcessingProperties::enable_sw_echo_cancellation, - &AudioProcessingProperties::disable_hw_echo_cancellation}, - result); - bool has_hw_echo_cancellation = - device.Parameters().effects() & media::AudioParameters::ECHO_CANCELLER; - EXPECT_EQ(IsDeviceCapture() && !has_hw_echo_cancellation, - result.audio_processing_properties().enable_sw_echo_cancellation); - EXPECT_NE( - IsDeviceCapture() && has_hw_echo_cancellation, - result.audio_processing_properties().disable_hw_echo_cancellation); - if (&device == geometry_device_) { - EXPECT_EQ(kMicPositions, - result.audio_processing_properties().goog_array_geometry); - } else { - CheckGeometryDefaults(result); + CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(), + result); + EchoCancellationType expected_echo_cancellation_type = + EchoCancellationType::kEchoCancellationDisabled; + if (IsDeviceCapture()) { + const bool has_system_echo_cancellation = + device.Parameters().effects() & + media::AudioParameters::ECHO_CANCELLER; + expected_echo_cancellation_type = + has_system_echo_cancellation + ? EchoCancellationType::kEchoCancellationSystem + : EchoCancellationType::kEchoCancellationAec2; + } + EXPECT_EQ(expected_echo_cancellation_type, + result.audio_processing_properties().echo_cancellation_type); + } +} + +TEST_P(MediaStreamConstraintsUtilAudioTest, ExactGroupID) { + for (const auto& device : capabilities_) { + constraint_factory_.basic().group_id.SetExact( + blink::WebString::FromASCII(device.GroupID())); + auto result = SelectSettings(); + EXPECT_TRUE(result.HasValue()); + CheckDevice(device, result); + CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(), + result); + EchoCancellationType expected_echo_cancellation_type = + EchoCancellationType::kEchoCancellationDisabled; + if (IsDeviceCapture()) { + const bool has_system_echo_cancellation = + device.Parameters().effects() & + media::AudioParameters::ECHO_CANCELLER; + expected_echo_cancellation_type = + has_system_echo_cancellation + ? EchoCancellationType::kEchoCancellationSystem + : EchoCancellationType::kEchoCancellationAec2; } + EXPECT_EQ(expected_echo_cancellation_type, + result.audio_processing_properties().echo_cancellation_type); } } -// Tests the echoCancellation constraint with a device without hardware echo +// Tests the echoCancellation constraint with a device without system echo // cancellation. -TEST_P(MediaStreamConstraintsUtilAudioTest, EchoCancellationWithSw) { +TEST_P(MediaStreamConstraintsUtilAudioTest, EchoCancellationWithWebRtc) { for (auto set_function : kBoolSetFunctions) { for (auto accessor : kFactoryAccessors) { // Ideal advanced is ignored by the SelectSettings algorithm. @@ -684,22 +701,26 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, EchoCancellationWithSw) { // With content capture, the echo_cancellation constraint controls // only the echo_cancellation properties. The other audio processing // properties default to false. - bool enable_sw_audio_processing = IsDeviceCapture() ? value : false; - EXPECT_EQ(value, properties.enable_sw_echo_cancellation); - EXPECT_TRUE(properties.disable_hw_echo_cancellation); - EXPECT_EQ(enable_sw_audio_processing, + const EchoCancellationType expected_echo_cancellation_type = + value ? EchoCancellationType::kEchoCancellationAec2 + : EchoCancellationType::kEchoCancellationDisabled; + EXPECT_EQ(expected_echo_cancellation_type, + properties.echo_cancellation_type); + const bool enable_webrtc_audio_processing = + IsDeviceCapture() ? value : false; + EXPECT_EQ(enable_webrtc_audio_processing, properties.goog_auto_gain_control); CheckGoogExperimentalEchoCancellationDefault( - properties, enable_sw_audio_processing); - EXPECT_EQ(enable_sw_audio_processing, + properties, enable_webrtc_audio_processing); + EXPECT_EQ(enable_webrtc_audio_processing, properties.goog_typing_noise_detection); - EXPECT_EQ(enable_sw_audio_processing, + EXPECT_EQ(enable_webrtc_audio_processing, properties.goog_noise_suppression); - EXPECT_EQ(enable_sw_audio_processing, + EXPECT_EQ(enable_webrtc_audio_processing, properties.goog_experimental_noise_suppression); - EXPECT_EQ(enable_sw_audio_processing, properties.goog_beamforming); - EXPECT_EQ(enable_sw_audio_processing, properties.goog_highpass_filter); - EXPECT_EQ(enable_sw_audio_processing, + EXPECT_EQ(enable_webrtc_audio_processing, + properties.goog_highpass_filter); + EXPECT_EQ(enable_webrtc_audio_processing, properties.goog_experimental_auto_gain_control); // The following are not audio processing. @@ -718,10 +739,10 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, EchoCancellationWithSw) { } } -// Tests the echoCancellation constraint with a device with hardware echo +// Tests the echoCancellation constraint with a device with system echo // cancellation. -TEST_P(MediaStreamConstraintsUtilAudioTest, EchoCancellationWithHw) { - // With content capture, there is no hardware echo cancellation, so +TEST_P(MediaStreamConstraintsUtilAudioTest, EchoCancellationWithSystem) { + // With content capture, there is no system echo cancellation, so // nothing to test. if (!IsDeviceCapture()) return; @@ -738,25 +759,28 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, EchoCancellationWithHw) { for (bool value : kBoolValues) { ResetFactory(); constraint_factory_.basic().device_id.SetExact( - blink::WebString::FromASCII(hw_echo_canceller_device_->DeviceID())); + blink::WebString::FromASCII( + system_echo_canceller_device_->DeviceID())); ((constraint_factory_.*accessor)().echo_cancellation.* set_function)(value); auto result = SelectSettings(); EXPECT_TRUE(result.HasValue()); const AudioProcessingProperties& properties = result.audio_processing_properties(); - // With hardware echo cancellation, the echo_cancellation constraint - // enables/disables all audio processing by default, software echo - // cancellation is always disabled, and hardware echo cancellation is + // With system echo cancellation, the echo_cancellation constraint + // enables/disables all audio processing by default, WebRTC echo + // cancellation is always disabled, and system echo cancellation is // disabled if the echo_cancellation constraint is false. - EXPECT_FALSE(properties.enable_sw_echo_cancellation); - EXPECT_EQ(!value, properties.disable_hw_echo_cancellation); + const EchoCancellationType expected_echo_cancellation_type = + value ? EchoCancellationType::kEchoCancellationSystem + : EchoCancellationType::kEchoCancellationDisabled; + EXPECT_EQ(expected_echo_cancellation_type, + properties.echo_cancellation_type); EXPECT_EQ(value, properties.goog_auto_gain_control); CheckGoogExperimentalEchoCancellationDefault(properties, value); EXPECT_EQ(value, properties.goog_typing_noise_detection); EXPECT_EQ(value, properties.goog_noise_suppression); EXPECT_EQ(value, properties.goog_experimental_noise_suppression); - EXPECT_EQ(value, properties.goog_beamforming); EXPECT_EQ(value, properties.goog_highpass_filter); EXPECT_EQ(value, properties.goog_experimental_auto_gain_control); @@ -766,15 +790,15 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, EchoCancellationWithHw) { EXPECT_EQ(GetMediaStreamSource() != kMediaStreamSourceDesktop, result.disable_local_echo()); EXPECT_FALSE(result.render_to_associated_sink()); - CheckDevice(*hw_echo_canceller_device_, result); + CheckDevice(*system_echo_canceller_device_, result); } } } } -// Tests the googEchoCancellation constraint with a device without hardware echo +// Tests the googEchoCancellation constraint with a device without system echo // cancellation. -TEST_P(MediaStreamConstraintsUtilAudioTest, GoogEchoCancellationWithSw) { +TEST_P(MediaStreamConstraintsUtilAudioTest, GoogEchoCancellationWithWebRtc) { for (auto set_function : kBoolSetFunctions) { for (auto accessor : kFactoryAccessors) { // Ideal advanced is ignored by the SelectSettings algorithm. @@ -795,15 +819,13 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, GoogEchoCancellationWithSw) { // The goog_echo_cancellation constraint controls only the // echo_cancellation properties. The other audio processing properties // use the default values. - EXPECT_EQ(value, properties.enable_sw_echo_cancellation); - EXPECT_TRUE(properties.disable_hw_echo_cancellation); - CheckBoolDefaults( - AudioSettingsBoolMembers(), - { - &AudioProcessingProperties::enable_sw_echo_cancellation, - &AudioProcessingProperties::disable_hw_echo_cancellation, - }, - result); + const EchoCancellationType expected_echo_cancellation_type = + value ? EchoCancellationType::kEchoCancellationAec2 + : EchoCancellationType::kEchoCancellationDisabled; + EXPECT_EQ(expected_echo_cancellation_type, + properties.echo_cancellation_type); + CheckBoolDefaults(AudioSettingsBoolMembers(), + AudioPropertiesBoolMembers(), result); if (IsDeviceCapture()) { CheckDevice(*default_device_, result); } else { @@ -814,10 +836,10 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, GoogEchoCancellationWithSw) { } } -// Tests the googEchoCancellation constraint with a device with hardware echo +// Tests the googEchoCancellation constraint with a device with system echo // cancellation. -TEST_P(MediaStreamConstraintsUtilAudioTest, GoogEchoCancellationWithHw) { - // With content capture, there is no hardware echo cancellation, so +TEST_P(MediaStreamConstraintsUtilAudioTest, GoogEchoCancellationWithSystem) { + // With content capture, there is no system echo cancellation, so // nothing to test. if (!IsDeviceCapture()) return; @@ -834,44 +856,40 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, GoogEchoCancellationWithHw) { for (bool value : kBoolValues) { ResetFactory(); constraint_factory_.basic().device_id.SetExact( - blink::WebString::FromASCII(hw_echo_canceller_device_->DeviceID())); + blink::WebString::FromASCII( + system_echo_canceller_device_->DeviceID())); ((constraint_factory_.*accessor)().goog_echo_cancellation.* set_function)(value); auto result = SelectSettings(); EXPECT_TRUE(result.HasValue()); const AudioProcessingProperties& properties = result.audio_processing_properties(); - // With hardware echo cancellation, software echo cancellation is always - // disabled, and hardware echo cancellation is disabled if + // With system echo cancellation, WebRTC echo cancellation is always + // disabled, and system echo cancellation is disabled if // goog_echo_cancellation is false. - EXPECT_FALSE(properties.enable_sw_echo_cancellation); - EXPECT_EQ(!value, properties.disable_hw_echo_cancellation); - CheckBoolDefaults( - AudioSettingsBoolMembers(), - { - &AudioProcessingProperties::enable_sw_echo_cancellation, - &AudioProcessingProperties::disable_hw_echo_cancellation, - }, - result); - CheckDevice(*hw_echo_canceller_device_, result); + const EchoCancellationType expected_echo_cancellation_type = + value ? EchoCancellationType::kEchoCancellationSystem + : EchoCancellationType::kEchoCancellationDisabled; + EXPECT_EQ(expected_echo_cancellation_type, + properties.echo_cancellation_type); + CheckBoolDefaults(AudioSettingsBoolMembers(), + AudioPropertiesBoolMembers(), result); + CheckDevice(*system_echo_canceller_device_, result); } } } } // Tests the echoCancellationType constraint without constraining to a device -// with hardware echo cancellation. Tested as basic exact constraints. +// with system echo cancellation. Tested as basic exact constraints. TEST_P(MediaStreamConstraintsUtilAudioTest, EchoCancellationTypeExact) { for (blink::WebString value : kEchoCancellationTypeValues) { - const bool request_hw_echo_cancellation = - value == kEchoCancellationTypeValues[1]; - ResetFactory(); constraint_factory_.basic().echo_cancellation.SetExact(true); constraint_factory_.basic().echo_cancellation_type.SetExact(value); auto result = SelectSettings(); // If content capture and EC type "system", we expect failure. - if (!IsDeviceCapture() && request_hw_echo_cancellation) { + if (!IsDeviceCapture() && value == kEchoCancellationTypeValues[2]) { EXPECT_FALSE(result.HasValue()); EXPECT_EQ(result.failed_constraint_name(), constraint_factory_.basic().echo_cancellation_type.GetName()); @@ -879,22 +897,21 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, EchoCancellationTypeExact) { } ASSERT_TRUE(result.HasValue()); - CheckAudioProcessingPropertiesForExactEchoCancellationType( - request_hw_echo_cancellation, result); + CheckAudioProcessingPropertiesForExactEchoCancellationType(value, result); } } -// Like the test above, but changes the device with hardware echo cancellation -// support to only support experimental hardware echo cancellation. It should +// Like the test above, but changes the device with system echo cancellation +// support to only support experimental system echo cancellation. It should // still be picked if requested. TEST_P(MediaStreamConstraintsUtilAudioTest, EchoCancellationTypeExact_Experimental) { if (!IsDeviceCapture()) return; - // Replace the device with one that only supports experimental hardware echo + // Replace the device with one that only supports experimental system echo // cancellation. - MakeHardwareEchoCancellerDeviceExperimental(); + MakeSystemEchoCancellerDeviceExperimental(); for (blink::WebString value : kEchoCancellationTypeValues) { ResetFactory(); @@ -902,60 +919,57 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, constraint_factory_.basic().echo_cancellation_type.SetExact(value); auto result = SelectSettings(); ASSERT_TRUE(result.HasValue()); - const bool request_hw_echo_cancellation = - value == kEchoCancellationTypeValues[1]; - CheckAudioProcessingPropertiesForExactEchoCancellationType( - request_hw_echo_cancellation, result); + CheckAudioProcessingPropertiesForExactEchoCancellationType(value, result); } } // Tests the echoCancellationType constraint without constraining to a device -// with hardware echo cancellation. Tested as basic ideal constraints. +// with system echo cancellation. Tested as basic ideal constraints. TEST_P(MediaStreamConstraintsUtilAudioTest, EchoCancellationTypeIdeal) { - // With content capture, there is no hardware echo cancellation, so + // With content capture, there is no system echo cancellation, so // nothing to test. if (!IsDeviceCapture()) return; constraint_factory_.basic().echo_cancellation.SetExact(true); constraint_factory_.basic().echo_cancellation_type.SetIdeal( - kEchoCancellationTypeValues[1]); + kEchoCancellationTypeValues[2]); auto result = SelectSettings(); ASSERT_TRUE(result.HasValue()); CheckAudioProcessingPropertiesForIdealEchoCancellationType(result); } -// Like the test above, but only having a device with experimental hardware echo +// Like the test above, but only having a device with experimental system echo // cancellation available. TEST_P(MediaStreamConstraintsUtilAudioTest, EchoCancellationTypeIdeal_Experimental) { - // With content capture, there is no hardware echo cancellation, so + // With content capture, there is no system echo cancellation, so // nothing to test. if (!IsDeviceCapture()) return; - // Replace the device with one that only supports experimental hardware echo + // Replace the device with one that only supports experimental system echo // cancellation. - MakeHardwareEchoCancellerDeviceExperimental(); + MakeSystemEchoCancellerDeviceExperimental(); constraint_factory_.basic().echo_cancellation.SetExact(true); constraint_factory_.basic().echo_cancellation_type.SetIdeal( - kEchoCancellationTypeValues[1]); + kEchoCancellationTypeValues[2]); auto result = SelectSettings(); ASSERT_TRUE(result.HasValue()); CheckAudioProcessingPropertiesForIdealEchoCancellationType(result); } // Tests the echoCancellationType constraint with constraining to a device with -// experimental hardware echo cancellation. +// experimental system echo cancellation. TEST_P(MediaStreamConstraintsUtilAudioTest, - EchoCancellationTypeWithExpHwDeviceConstraint) { + EchoCancellationTypeWithExpSystemDeviceConstraint) { // With content capture, there is no system echo cancellation, so // nothing to test. if (!IsDeviceCapture()) return; - MakeHardwareEchoCancellerDeviceExperimental(); + MakeSystemEchoCancellerDeviceExperimental(); // Include leaving the echoCancellationType constraint unset in the tests. // It should then behave as before the constraint was introduced. @@ -976,7 +990,7 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, ResetFactory(); constraint_factory_.basic().device_id.SetExact( blink::WebString::FromASCII( - hw_echo_canceller_device_->DeviceID())); + system_echo_canceller_device_->DeviceID())); constraint_factory_.basic().echo_cancellation.SetExact(ec_value); if (!ec_type_value.IsNull()) ((constraint_factory_.*accessor)().echo_cancellation_type.* @@ -998,32 +1012,28 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, const AudioProcessingProperties& properties = result.audio_processing_properties(); - // With experimental hardware echo cancellation (echo canceller type + // With experimental system echo cancellation (echo canceller type // "system"), the echo_cancellation constraint enables/disables all - // audio processing by default, software echo cancellation is always - // disabled, and experimental hardware echo cancellation is disabled + // audio processing by default, WebRTC echo cancellation is always + // disabled, and experimental system echo cancellation is disabled // if the echo_cancellation constraint is false. - bool request_hw_echo_cancellation = - ec_type_value == kEchoCancellationTypeValues[1]; - if (ec_value) { - EXPECT_NE(request_hw_echo_cancellation, - properties.enable_sw_echo_cancellation); - EXPECT_NE(request_hw_echo_cancellation, - properties.disable_hw_echo_cancellation); - EXPECT_EQ(request_hw_echo_cancellation, - properties.enable_experimental_hw_echo_cancellation); + const EchoCancellationType expected_echo_cancellation_type = + ec_type_value == blink::WebString() + ? EchoCancellationType::kEchoCancellationAec2 + : GetEchoCancellationTypeFromConstraintString( + ec_type_value); + EXPECT_EQ(expected_echo_cancellation_type, + properties.echo_cancellation_type); } else { - EXPECT_FALSE(properties.enable_sw_echo_cancellation); - EXPECT_TRUE(properties.disable_hw_echo_cancellation); - EXPECT_FALSE(properties.enable_experimental_hw_echo_cancellation); + EXPECT_EQ(EchoCancellationType::kEchoCancellationDisabled, + properties.echo_cancellation_type); } EXPECT_EQ(ec_value, properties.goog_auto_gain_control); CheckGoogExperimentalEchoCancellationDefault(properties, ec_value); EXPECT_EQ(ec_value, properties.goog_typing_noise_detection); EXPECT_EQ(ec_value, properties.goog_noise_suppression); EXPECT_EQ(ec_value, properties.goog_experimental_noise_suppression); - EXPECT_EQ(ec_value, properties.goog_beamforming); EXPECT_EQ(ec_value, properties.goog_highpass_filter); EXPECT_EQ(ec_value, properties.goog_experimental_auto_gain_control); @@ -1033,7 +1043,7 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, EXPECT_EQ(GetMediaStreamSource() != kMediaStreamSourceDesktop, result.disable_local_echo()); EXPECT_FALSE(result.render_to_associated_sink()); - CheckDevice(*hw_echo_canceller_device_, result); + CheckDevice(*system_echo_canceller_device_, result); } } } @@ -1041,9 +1051,9 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, } // Tests the echoCancellationType constraint with constraining to a device -// without experimental hardware echo cancellation, which should fail. +// without experimental system echo cancellation, which should fail. TEST_P(MediaStreamConstraintsUtilAudioTest, - EchoCancellationTypeWithSwDeviceConstraint) { + EchoCancellationTypeWithWebRtcDeviceConstraint) { if (!IsDeviceCapture()) return; @@ -1051,7 +1061,7 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, blink::WebString::FromASCII(default_device_->DeviceID())); constraint_factory_.basic().echo_cancellation.SetExact(true); constraint_factory_.basic().echo_cancellation_type.SetExact( - kEchoCancellationTypeValues[1]); + kEchoCancellationTypeValues[2]); auto result = SelectSettings(); EXPECT_FALSE(result.HasValue()); @@ -1059,6 +1069,57 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, constraint_factory_.basic().device_id.GetName()); } +// Tests the echoCancellationType constraint when also the AEC3 has been +// selected via the extension API. That selection ends up in +// AecDumpMessageFilter and MediaStreamConstraintsUtil checks there if set and +// to what. It can be unset, true or false. The constraint has precedence over +// the extension API selection. Tested as basic exact constraints. +TEST_P(MediaStreamConstraintsUtilAudioTest, + EchoCancellationTypeAndAec3Selection) { + // First test AEC3 selection when no echo cancellation type constraint has + // been set. + scoped_refptr<AecDumpMessageFilterForTest> admf = + new AecDumpMessageFilterForTest(); + admf->set_override_aec3(true); + + ResetFactory(); + constraint_factory_.basic().echo_cancellation.SetExact(true); + auto result = SelectSettings(); + ASSERT_TRUE(result.HasValue()); + + CheckAudioProcessingPropertiesForExactEchoCancellationType( + kEchoCancellationTypeValues[1], // AEC3 + result); + + // Set the echo cancellation type constraint to browser and expect that as + // result. + ResetFactory(); + constraint_factory_.basic().echo_cancellation.SetExact(true); + constraint_factory_.basic().echo_cancellation_type.SetExact( + kEchoCancellationTypeValues[0]); + result = SelectSettings(); + ASSERT_TRUE(result.HasValue()); + + CheckAudioProcessingPropertiesForExactEchoCancellationType( + kEchoCancellationTypeValues[0], // Browser + result); + + // Set the AEC3 selection to false and echo cancellation type constraint to + // AEC3 and expect AEC3 as result. + admf->set_override_aec3(false); + + ResetFactory(); + constraint_factory_.basic().echo_cancellation.SetExact(true); + constraint_factory_.basic().echo_cancellation_type.SetExact( + kEchoCancellationTypeValues[1]); + result = SelectSettings(); + ASSERT_TRUE(result.HasValue()); + + CheckAudioProcessingPropertiesForExactEchoCancellationType( + kEchoCancellationTypeValues[1], // AEC3 + result); +} + // Test that having differing mandatory values for echoCancellation and // googEchoCancellation fails. TEST_P(MediaStreamConstraintsUtilAudioTest, ContradictoryEchoCancellation) { @@ -1083,7 +1144,6 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, &AudioProcessingProperties::goog_typing_noise_detection, &AudioProcessingProperties::goog_noise_suppression, &AudioProcessingProperties::goog_experimental_noise_suppression, - &AudioProcessingProperties::goog_beamforming, &AudioProcessingProperties::goog_highpass_filter, &AudioProcessingProperties::goog_experimental_auto_gain_control}; @@ -1098,7 +1158,6 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, &blink::WebMediaTrackConstraintSet::goog_noise_suppression, &blink::WebMediaTrackConstraintSet:: goog_experimental_noise_suppression, - &blink::WebMediaTrackConstraintSet::goog_beamforming, &blink::WebMediaTrackConstraintSet::goog_highpass_filter, &blink::WebMediaTrackConstraintSet:: goog_experimental_auto_gain_control, @@ -1123,10 +1182,8 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, set_function)(true); auto result = SelectSettings(); EXPECT_TRUE(result.HasValue()); - EXPECT_FALSE( - result.audio_processing_properties().enable_sw_echo_cancellation); - EXPECT_TRUE( - result.audio_processing_properties().disable_hw_echo_cancellation); + EXPECT_EQ(EchoCancellationType::kEchoCancellationDisabled, + result.audio_processing_properties().echo_cancellation_type); EXPECT_TRUE(result.audio_processing_properties().* kAudioProcessingProperties[i]); for (size_t j = 0; j < kAudioProcessingProperties.size(); ++j) { @@ -1152,7 +1209,7 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, AdvancedCompatibleConstraints) { &AudioCaptureSettings::render_to_associated_sink; CheckBoolDefaults({render_to_associated_sink}, {&AudioProcessingProperties::goog_audio_mirroring}, result); - CheckGeometryDefaults(result); + CheckEchoCancellationTypeDefault(result); EXPECT_TRUE(result.render_to_associated_sink()); EXPECT_TRUE(result.audio_processing_properties().goog_audio_mirroring); } @@ -1177,7 +1234,7 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, {&AudioProcessingProperties::goog_audio_mirroring, &AudioProcessingProperties::goog_highpass_filter}, result); - CheckGeometryDefaults(result); + CheckEchoCancellationTypeDefault(result); EXPECT_FALSE(result.hotword_enabled()); EXPECT_TRUE(result.audio_processing_properties().goog_audio_mirroring); EXPECT_TRUE(result.audio_processing_properties().goog_highpass_filter); @@ -1199,129 +1256,13 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, AdvancedConflictingLastConstraint) { {&AudioProcessingProperties::goog_audio_mirroring, &AudioProcessingProperties::goog_highpass_filter}, result); - CheckGeometryDefaults(result); + CheckEchoCancellationTypeDefault(result); // The fourth advanced set is ignored because it contradicts the second set. EXPECT_TRUE(result.hotword_enabled()); EXPECT_TRUE(result.audio_processing_properties().goog_audio_mirroring); EXPECT_TRUE(result.audio_processing_properties().goog_highpass_filter); } -// Test that a valid geometry is interpreted correctly in all the ways it can -// be set. -TEST_P(MediaStreamConstraintsUtilAudioTest, ValidGeometry) { - const blink::WebString kGeometry = - blink::WebString::FromASCII("-0.02 0 0 0.02 0 1.01"); - - for (auto set_function : kStringSetFunctions) { - for (auto accessor : kFactoryAccessors) { - // Ideal advanced is ignored by the SelectSettings algorithm. - // Using array elements instead of pointer values due to the comparison - // failing on some build configurations. - if (set_function == kStringSetFunctions[1] && - accessor == kFactoryAccessors[1]) { - continue; - } - ResetFactory(); - ((constraint_factory_.*accessor)().goog_array_geometry.* - set_function)(kGeometry); - auto result = SelectSettings(); - EXPECT_TRUE(result.HasValue()); - CheckDeviceDefaults(result); - CheckBoolDefaults(AudioSettingsBoolMembers(), - AudioPropertiesBoolMembers(), result); - const std::vector<media::Point>& geometry = - result.audio_processing_properties().goog_array_geometry; - EXPECT_EQ(2u, geometry.size()); - EXPECT_EQ(media::Point(-0.02, 0, 0), geometry[0]); - EXPECT_EQ(media::Point(0.02, 0, 1.01), geometry[1]); - } - } -} - -// Test that an invalid geometry is interpreted as empty in all the ways it can -// be set. -TEST_P(MediaStreamConstraintsUtilAudioTest, InvalidGeometry) { - const blink::WebString kGeometry = - blink::WebString::FromASCII("1 1 1 invalid"); - - for (auto set_function : kStringSetFunctions) { - for (auto accessor : kFactoryAccessors) { - // Ideal advanced is ignored by the SelectSettings algorithm. - // Using array elements instead of pointer values due to the comparison - // failing on some build configurations. - if (set_function == kStringSetFunctions[1] && - accessor == kFactoryAccessors[1]) { - continue; - } - ResetFactory(); - ((constraint_factory_.*accessor)().goog_array_geometry.* - set_function)(kGeometry); - auto result = SelectSettings(); - EXPECT_TRUE(result.HasValue()); - CheckDeviceDefaults(result); - CheckBoolDefaults(AudioSettingsBoolMembers(), - AudioPropertiesBoolMembers(), result); - const std::vector<media::Point>& geometry = - result.audio_processing_properties().goog_array_geometry; - EXPECT_EQ(0u, geometry.size()); - } - } -} - -// Test that an invalid geometry is interpreted as empty in all the ways it can -// be set. -TEST_P(MediaStreamConstraintsUtilAudioTest, DeviceGeometry) { - if (!IsDeviceCapture()) - return; - - constraint_factory_.basic().device_id.SetExact( - blink::WebString::FromASCII(geometry_device_->DeviceID())); - - { - const blink::WebString kValidGeometry = - blink::WebString::FromASCII("-0.02 0 0 0.02 0 1.01"); - constraint_factory_.basic().goog_array_geometry.SetExact(kValidGeometry); - auto result = SelectSettings(); - EXPECT_TRUE(result.HasValue()); - CheckDevice(*geometry_device_, result); - CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(), - result); - // Constraints geometry should be preferred over device geometry. - const std::vector<media::Point>& geometry = - result.audio_processing_properties().goog_array_geometry; - EXPECT_EQ(2u, geometry.size()); - EXPECT_EQ(media::Point(-0.02, 0, 0), geometry[0]); - EXPECT_EQ(media::Point(0.02, 0, 1.01), geometry[1]); - } - - { - constraint_factory_.basic().goog_array_geometry.SetExact( - blink::WebString()); - auto result = SelectSettings(); - EXPECT_TRUE(result.HasValue()); - CheckDevice(*geometry_device_, result); - CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(), - result); - // Empty geometry is valid and should be preferred over device geometry. - EXPECT_TRUE( - result.audio_processing_properties().goog_array_geometry.empty()); - } - - { - const blink::WebString kInvalidGeometry = - blink::WebString::FromASCII("1 1 1 invalid"); - constraint_factory_.basic().goog_array_geometry.SetExact(kInvalidGeometry); - auto result = SelectSettings(); - EXPECT_TRUE(result.HasValue()); - CheckDevice(*geometry_device_, result); - CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(), - result); - // Device geometry should be preferred over invalid constraints geometry. - EXPECT_EQ(kMicPositions, - result.audio_processing_properties().goog_array_geometry); - } -} - // NoDevices tests verify that the case with no devices is handled correctly. TEST_P(MediaStreamConstraintsUtilAudioTest, NoDevicesNoConstraints) { // This test makes sense only for device capture. @@ -1354,7 +1295,7 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, SourceWithNoAudioProcessing) { for (bool enable_properties : {true, false}) { std::unique_ptr<LocalMediaStreamAudioSource> source = GetLocalMediaStreamAudioSource( - enable_properties /* enable_hardware_echo_canceller */, + enable_properties /* enable_system_echo_canceller */, enable_properties /* hotword_enabled */, enable_properties /* disable_local_echo */, enable_properties /* render_to_associated_sink */); @@ -1406,10 +1347,10 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, EchoCancellationTypeWithSourceWithNoAudioProcessing) { for (blink::WebString value : kEchoCancellationTypeValues) { std::unique_ptr<LocalMediaStreamAudioSource> source = - GetLocalMediaStreamAudioSource( - false /* enable_hardware_echo_canceller */, - false /* hotword_enabled */, false /* disable_local_echo */, - false /* render_to_associated_sink */); + GetLocalMediaStreamAudioSource(false /* enable_system_echo_canceller */, + false /* hotword_enabled */, + false /* disable_local_echo */, + false /* render_to_associated_sink */); // No echo cancellation is available so we expect failure. constraint_factory_.Reset(); @@ -1436,10 +1377,9 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, SourceWithAudioProcessing) { for (bool use_defaults : {true, false}) { AudioProcessingProperties properties; - properties.disable_hw_echo_cancellation = true; if (!use_defaults) { - properties.enable_sw_echo_cancellation = - !properties.enable_sw_echo_cancellation; + properties.echo_cancellation_type = + EchoCancellationType::kEchoCancellationDisabled; properties.goog_audio_mirroring = !properties.goog_audio_mirroring; properties.goog_auto_gain_control = !properties.goog_auto_gain_control; properties.goog_experimental_echo_cancellation = @@ -1449,11 +1389,9 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, SourceWithAudioProcessing) { properties.goog_noise_suppression = !properties.goog_noise_suppression; properties.goog_experimental_noise_suppression = !properties.goog_experimental_noise_suppression; - properties.goog_beamforming = !properties.goog_beamforming; properties.goog_highpass_filter = !properties.goog_highpass_filter; properties.goog_experimental_auto_gain_control = !properties.goog_experimental_auto_gain_control; - properties.goog_array_geometry = {{1, 1, 1}, {2, 2, 2}}; } std::unique_ptr<ProcessedLocalAudioSource> source = @@ -1464,7 +1402,6 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, SourceWithAudioProcessing) { const std::vector< blink::BooleanConstraint blink::WebMediaTrackConstraintSet::*> kAudioProcessingConstraints = { - &blink::WebMediaTrackConstraintSet::echo_cancellation, &blink::WebMediaTrackConstraintSet::goog_audio_mirroring, &blink::WebMediaTrackConstraintSet::goog_auto_gain_control, &blink::WebMediaTrackConstraintSet:: @@ -1473,20 +1410,17 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, SourceWithAudioProcessing) { &blink::WebMediaTrackConstraintSet::goog_noise_suppression, &blink::WebMediaTrackConstraintSet:: goog_experimental_noise_suppression, - &blink::WebMediaTrackConstraintSet::goog_beamforming, &blink::WebMediaTrackConstraintSet::goog_highpass_filter, &blink::WebMediaTrackConstraintSet:: goog_experimental_auto_gain_control, }; const AudioPropertiesBoolMembers kAudioProcessingProperties = { - &AudioProcessingProperties::enable_sw_echo_cancellation, &AudioProcessingProperties::goog_audio_mirroring, &AudioProcessingProperties::goog_auto_gain_control, &AudioProcessingProperties::goog_experimental_echo_cancellation, &AudioProcessingProperties::goog_typing_noise_detection, &AudioProcessingProperties::goog_noise_suppression, &AudioProcessingProperties::goog_experimental_noise_suppression, - &AudioProcessingProperties::goog_beamforming, &AudioProcessingProperties::goog_highpass_filter, &AudioProcessingProperties::goog_experimental_auto_gain_control}; @@ -1524,24 +1458,34 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, SourceWithAudioProcessing) { EXPECT_TRUE(result.HasValue()); } - { - constraint_factory_.Reset(); - // TODO(guidou): Support any semantically equivalent strings for the - // goog_array_geometry constrainable property. http://crbug.com/796955 - constraint_factory_.basic().goog_array_geometry.SetExact( - blink::WebString("1 1 1 2 2 2")); - auto result = SelectSettingsAudioCapture( - source.get(), constraint_factory_.CreateWebMediaConstraints()); - EXPECT_EQ(result.HasValue(), !use_defaults); + // Test same as above but for echo cancellation. + constraint_factory_.Reset(); + constraint_factory_.basic().echo_cancellation.SetExact( + properties.echo_cancellation_type == + EchoCancellationType::kEchoCancellationAec2); + auto result = SelectSettingsAudioCapture( + source.get(), constraint_factory_.CreateWebMediaConstraints()); + EXPECT_TRUE(result.HasValue()); - // Setting ideal should succeed. - constraint_factory_.Reset(); - constraint_factory_.basic().goog_array_geometry.SetIdeal( - blink::WebString("4 4 4 5 5 5")); - result = SelectSettingsAudioCapture( - source.get(), constraint_factory_.CreateWebMediaConstraints()); - EXPECT_TRUE(result.HasValue()); - } + constraint_factory_.Reset(); + constraint_factory_.basic().echo_cancellation.SetExact( + properties.echo_cancellation_type != + EchoCancellationType::kEchoCancellationAec2); + result = SelectSettingsAudioCapture( + source.get(), constraint_factory_.CreateWebMediaConstraints()); + EXPECT_FALSE(result.HasValue()); + + constraint_factory_.Reset(); + constraint_factory_.basic().echo_cancellation.SetIdeal(true); + result = SelectSettingsAudioCapture( + source.get(), constraint_factory_.CreateWebMediaConstraints()); + EXPECT_TRUE(result.HasValue()); + + constraint_factory_.Reset(); + constraint_factory_.basic().echo_cancellation.SetIdeal(false); + result = SelectSettingsAudioCapture( + source.get(), constraint_factory_.CreateWebMediaConstraints()); + EXPECT_TRUE(result.HasValue()); // These constraints are false in |source|. const std::vector< @@ -1579,6 +1523,31 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, SourceWithAudioProcessing) { source.get(), constraint_factory_.CreateWebMediaConstraints()); EXPECT_TRUE(result.HasValue()); } + + // Test same as above for echo cancellation. + constraint_factory_.Reset(); + constraint_factory_.basic().echo_cancellation.SetExact(use_defaults); + result = SelectSettingsAudioCapture( + source.get(), constraint_factory_.CreateWebMediaConstraints()); + EXPECT_TRUE(result.HasValue()); + + constraint_factory_.Reset(); + constraint_factory_.basic().echo_cancellation.SetExact(!use_defaults); + result = SelectSettingsAudioCapture( + source.get(), constraint_factory_.CreateWebMediaConstraints()); + EXPECT_FALSE(result.HasValue()); + + constraint_factory_.Reset(); + constraint_factory_.basic().echo_cancellation.SetIdeal(true); + result = SelectSettingsAudioCapture( + source.get(), constraint_factory_.CreateWebMediaConstraints()); + EXPECT_TRUE(result.HasValue()); + + constraint_factory_.Reset(); + constraint_factory_.basic().echo_cancellation.SetIdeal(false); + result = SelectSettingsAudioCapture( + source.get(), constraint_factory_.CreateWebMediaConstraints()); + EXPECT_TRUE(result.HasValue()); } } @@ -1590,46 +1559,42 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, if (!IsDeviceCapture()) return; - for (bool enable_sw_ec : kBoolValues) { - for (bool enable_exp_hw_ec : kBoolValues) { - // Both sw and hw echo cancellation can't be enabled. - if (enable_sw_ec && enable_exp_hw_ec) - continue; + const EchoCancellationType kEchoCancellationTypes[] = { + EchoCancellationType::kEchoCancellationDisabled, + EchoCancellationType::kEchoCancellationAec2, + EchoCancellationType::kEchoCancellationAec3, + EchoCancellationType::kEchoCancellationSystem}; - AudioProcessingProperties properties; - properties.DisableDefaultProperties(); - properties.enable_sw_echo_cancellation = enable_sw_ec; - properties.enable_experimental_hw_echo_cancellation = enable_exp_hw_ec; - - std::unique_ptr<ProcessedLocalAudioSource> source = - GetProcessedLocalAudioSource( - properties, false /* hotword_enabled */, - false /* disable_local_echo */, - false /* render_to_associated_sink */, - enable_exp_hw_ec - ? media::AudioParameters::PlatformEffectsMask:: - EXPERIMENTAL_ECHO_CANCELLER - : media::AudioParameters::PlatformEffectsMask::NO_EFFECTS); - - for (blink::WebString value : kEchoCancellationTypeValues) { - bool system_ec_type = value == kEchoCancellationTypeValues[1]; - - constraint_factory_.Reset(); - constraint_factory_.basic().echo_cancellation_type.SetExact(value); - auto result = SelectSettingsAudioCapture( - source.get(), constraint_factory_.CreateWebMediaConstraints()); - const bool should_have_result_value = - (enable_sw_ec && !system_ec_type) || - (enable_exp_hw_ec && system_ec_type); - EXPECT_EQ(should_have_result_value, result.HasValue()); - - // Setting just ideal values should always succeed. - constraint_factory_.Reset(); - constraint_factory_.basic().echo_cancellation_type.SetIdeal(value); - result = SelectSettingsAudioCapture( - source.get(), constraint_factory_.CreateWebMediaConstraints()); - EXPECT_TRUE(result.HasValue()); - } + for (EchoCancellationType ec_type : kEchoCancellationTypes) { + AudioProcessingProperties properties; + properties.DisableDefaultProperties(); + properties.echo_cancellation_type = ec_type; + + std::unique_ptr<ProcessedLocalAudioSource> source = + GetProcessedLocalAudioSource( + properties, false /* hotword_enabled */, + false /* disable_local_echo */, + false /* render_to_associated_sink */, + ec_type == EchoCancellationType::kEchoCancellationSystem + ? media::AudioParameters::PlatformEffectsMask:: + EXPERIMENTAL_ECHO_CANCELLER + : media::AudioParameters::PlatformEffectsMask::NO_EFFECTS); + + for (blink::WebString value : kEchoCancellationTypeValues) { + constraint_factory_.Reset(); + constraint_factory_.basic().echo_cancellation_type.SetExact(value); + auto result = SelectSettingsAudioCapture( + source.get(), constraint_factory_.CreateWebMediaConstraints()); + const bool should_have_result_value = + ec_type == GetEchoCancellationTypeFromConstraintString(value); + EXPECT_EQ(should_have_result_value, result.HasValue()); + + // Setting just ideal values should always succeed. + constraint_factory_.Reset(); + constraint_factory_.basic().echo_cancellation_type.SetIdeal(value); + result = SelectSettingsAudioCapture( + source.get(), constraint_factory_.CreateWebMediaConstraints()); + EXPECT_TRUE(result.HasValue()); } } } @@ -1641,17 +1606,16 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, UsedAndUnusedSources) { return; AudioProcessingProperties properties; - properties.enable_sw_echo_cancellation = true; - std::unique_ptr<ProcessedLocalAudioSource> processed_source = GetProcessedLocalAudioSource(properties, false /* hotword_enabled */, false /* disable_local_echo */, false /* render_to_associated_sink */); const std::string kUnusedDeviceID = "unused_device"; + const std::string kGroupID = "fake_group"; AudioDeviceCaptureCapabilities capabilities; capabilities.emplace_back(processed_source.get()); - capabilities.emplace_back(kUnusedDeviceID, + capabilities.emplace_back(kUnusedDeviceID, kGroupID, media::AudioParameters::UnavailableDeviceParams()); { @@ -1663,8 +1627,8 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, UsedAndUnusedSources) { false /* should_disable_hardware_noise_suppression */); EXPECT_TRUE(result.HasValue()); EXPECT_EQ(result.device_id(), kUnusedDeviceID); - EXPECT_FALSE( - result.audio_processing_properties().enable_sw_echo_cancellation); + EXPECT_EQ(result.audio_processing_properties().echo_cancellation_type, + EchoCancellationType::kEchoCancellationDisabled); } { @@ -1675,8 +1639,8 @@ TEST_P(MediaStreamConstraintsUtilAudioTest, UsedAndUnusedSources) { false /* should_disable_hardware_noise_suppression */); EXPECT_TRUE(result.HasValue()); EXPECT_EQ(result.device_id(), processed_source->device().id); - EXPECT_TRUE( - result.audio_processing_properties().enable_sw_echo_cancellation); + EXPECT_EQ(result.audio_processing_properties().echo_cancellation_type, + EchoCancellationType::kEchoCancellationAec2); } } diff --git a/chromium/content/renderer/media/stream/media_stream_constraints_util_sets.cc b/chromium/content/renderer/media/stream/media_stream_constraints_util_sets.cc index 9ce80b68a18..385ff981515 100644 --- a/chromium/content/renderer/media/stream/media_stream_constraints_util_sets.cc +++ b/chromium/content/renderer/media/stream/media_stream_constraints_util_sets.cc @@ -10,6 +10,7 @@ #include "third_party/blink/public/platform/web_media_constraints.h" namespace content { +namespace media_constraints { using Point = ResolutionSet::Point; @@ -553,4 +554,5 @@ DiscreteSet<bool> BoolSetFromConstraint( return DiscreteSet<bool>({constraint.Exact()}); } +} // namespace media_constraints } // namespace content diff --git a/chromium/content/renderer/media/stream/media_stream_constraints_util_sets.h b/chromium/content/renderer/media/stream/media_stream_constraints_util_sets.h index 28b07606700..23509132424 100644 --- a/chromium/content/renderer/media/stream/media_stream_constraints_util_sets.h +++ b/chromium/content/renderer/media/stream/media_stream_constraints_util_sets.h @@ -22,6 +22,7 @@ struct WebMediaTrackConstraintSet; } namespace content { +namespace media_constraints { // This class template represents a set of candidates suitable for a numeric // range-based constraint. @@ -392,6 +393,7 @@ class CONTENT_EXPORT ResolutionSet { ResolutionSet::Point CONTENT_EXPORT operator*(double d, const ResolutionSet::Point& p); +} // namespace media_constraints } // namespace content #endif // CONTENT_RENDERER_MEDIA_STREAM_MEDIA_STREAM_CONSTRAINTS_UTIL_SETS_H_ 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 105ae0784e6..62f74c126cb 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 @@ -12,6 +12,7 @@ #include "testing/gtest/include/gtest/gtest.h" namespace content { +namespace media_constraints { using Point = ResolutionSet::Point; @@ -1266,4 +1267,5 @@ TEST_F(MediaStreamConstraintsUtilSetsTest, DiscreteSetBool) { EXPECT_TRUE(intersection.IsEmpty()); } +} // namespace media_constraints } // namespace content diff --git a/chromium/content/renderer/media/stream/media_stream_constraints_util_unittest.cc b/chromium/content/renderer/media/stream/media_stream_constraints_util_unittest.cc index 182870876bc..9b0a9ffdd62 100644 --- a/chromium/content/renderer/media/stream/media_stream_constraints_util_unittest.cc +++ b/chromium/content/renderer/media/stream/media_stream_constraints_util_unittest.cc @@ -29,7 +29,8 @@ namespace content { class MediaStreamConstraintsUtilTest : public testing::Test { protected: - using DoubleRangeSet = NumericRangeSet<double>; + using DoubleRangeSet = media_constraints::NumericRangeSet<double>; + using ResolutionSet = media_constraints::ResolutionSet; }; TEST_F(MediaStreamConstraintsUtilTest, BooleanConstraints) { 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 dfa2734c8a5..7fa6b1f9c08 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 @@ -39,9 +39,11 @@ const double kDefaultScreenCastFrameRate = namespace { +using ResolutionSet = media_constraints::ResolutionSet; using Point = ResolutionSet::Point; -using StringSet = DiscreteSet<std::string>; -using BoolSet = DiscreteSet<bool>; +using StringSet = media_constraints::DiscreteSet<std::string>; +using BoolSet = media_constraints::DiscreteSet<bool>; +using DoubleRangeSet = media_constraints::NumericRangeSet<double>; constexpr double kMinScreenCastAspectRatio = static_cast<double>(kMinScreenCastDimension) / @@ -50,7 +52,6 @@ constexpr double kMaxScreenCastAspectRatio = static_cast<double>(kMaxScreenCastDimension) / static_cast<double>(kMinScreenCastDimension); -using DoubleRangeSet = NumericRangeSet<double>; class VideoContentCaptureCandidates { public: @@ -69,9 +70,10 @@ class VideoContentCaptureCandidates { DoubleRangeSet::FromConstraint(constraint_set.frame_rate, 0.0, kMaxScreenCastFrameRate)), - device_id_set_(StringSetFromConstraint(constraint_set.device_id)), - noise_reduction_set_( - BoolSetFromConstraint(constraint_set.goog_noise_reduction)) {} + device_id_set_(media_constraints::StringSetFromConstraint( + constraint_set.device_id)), + noise_reduction_set_(media_constraints::BoolSetFromConstraint( + constraint_set.goog_noise_reduction)) {} VideoContentCaptureCandidates(VideoContentCaptureCandidates&& other) = default; 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 75e989191d3..cbc9db71fb4 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 @@ -9,7 +9,6 @@ #include "content/common/content_export.h" #include "content/renderer/media/stream/media_stream_constraints_util.h" -#include "third_party/webrtc/api/optional.h" namespace blink { class WebMediaConstraints; 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 1e361d3de3d..66c6cabdd42 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 @@ -21,6 +21,9 @@ namespace content { namespace { +using ResolutionSet = media_constraints::ResolutionSet; +using DoubleRangeSet = media_constraints::NumericRangeSet<double>; + // Number of default settings to be used as final tie-breaking criteria for // settings that are equally good at satisfying constraints: // device ID, power-line frequency, noise reduction, resolution and frame rate. @@ -40,7 +43,7 @@ blink::WebString ToWebString(media::VideoFacingMode facing_mode) { case media::MEDIA_VIDEO_FACING_ENVIRONMENT: return blink::WebString::FromASCII("environment"); default: - return blink::WebString::FromASCII(""); + return blink::WebString(); } } @@ -125,7 +128,7 @@ class ConstrainedFormat { const ResolutionSet& constrained_resolution() const { return constrained_resolution_; } - const NumericRangeSet<double>& constrained_frame_rate() const { + const DoubleRangeSet& constrained_frame_rate() const { return constrained_frame_rate_; } @@ -153,9 +156,8 @@ class ConstrainedFormat { auto resolution_intersection = constrained_resolution_.Intersection( ResolutionSet::FromConstraintSet(constraint_set)); auto frame_rate_intersection = constrained_frame_rate_.Intersection( - NumericRangeSet<double>::FromConstraint( - constraint_set.frame_rate, 0.0, - media::limits::kMaxFramesPerSecond)); + DoubleRangeSet::FromConstraint(constraint_set.frame_rate, 0.0, + media::limits::kMaxFramesPerSecond)); if (resolution_intersection.IsEmpty() || frame_rate_intersection.IsEmpty() || frame_rate_intersection.Min().value_or(0.0) > native_frame_rate_) { @@ -173,7 +175,7 @@ class ConstrainedFormat { long native_width_; double native_frame_rate_; ResolutionSet constrained_resolution_; - NumericRangeSet<double> constrained_frame_rate_; + DoubleRangeSet constrained_frame_rate_; }; VideoCaptureSettings ComputeVideoDeviceCaptureSettings( @@ -241,6 +243,25 @@ double StringConstraintSourceDistance(const blink::WebString& value, return HUGE_VAL; } +double FacingModeConstraintSourceDistance( + media::VideoFacingMode value, + const blink::StringConstraint& facing_mode_constraint, + const char** failed_constraint_name) { + blink::WebString string_value = ToWebString(value); + if (string_value.IsNull()) { + if (facing_mode_constraint.Exact().empty()) + return 0.0; + + if (failed_constraint_name) + *failed_constraint_name = facing_mode_constraint.GetName(); + return HUGE_VAL; + } + + double ret = StringConstraintSourceDistance( + string_value, facing_mode_constraint, failed_constraint_name); + return ret; +} + // Returns a custom distance between a source screen dimension and |constraint|. // The source supports the range [|min_source_value|, |max_source_value|], using // cropping if necessary. This range may differ from the native range of the @@ -446,9 +467,8 @@ double DeviceSourceDistance( StringConstraintSourceDistance(blink::WebString::FromASCII(group_id), constraint_set.group_id, failed_constraint_name) + - StringConstraintSourceDistance(ToWebString(facing_mode), - constraint_set.facing_mode, - failed_constraint_name); + FacingModeConstraintSourceDistance( + facing_mode, constraint_set.facing_mode, failed_constraint_name); } // Returns a custom distance between |constraint_set| and |format| given that diff --git a/chromium/content/renderer/media/stream/media_stream_constraints_util_video_device_unittest.cc b/chromium/content/renderer/media/stream/media_stream_constraints_util_video_device_unittest.cc index dc0188d8aaa..8a9a13eb380 100644 --- a/chromium/content/renderer/media/stream/media_stream_constraints_util_video_device_unittest.cc +++ b/chromium/content/renderer/media/stream/media_stream_constraints_util_video_device_unittest.cc @@ -260,6 +260,18 @@ TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, OverconstrainedOnFacingMode) { result.failed_constraint_name()); } +TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, + OverconstrainedOnEmptyFacingMode) { + constraint_factory_.Reset(); + // Empty is not a valid facingMode value. + constraint_factory_.basic().facing_mode.SetExact( + blink::WebString::FromASCII("")); + auto result = SelectSettings(); + EXPECT_FALSE(result.HasValue()); + EXPECT_EQ(constraint_factory_.basic().facing_mode.GetName(), + result.failed_constraint_name()); +} + TEST_F(MediaStreamConstraintsUtilVideoDeviceTest, OverconstrainedOnVideoKind) { constraint_factory_.Reset(); // No device in |capabilities_| has video kind infrared. diff --git a/chromium/content/renderer/media/stream/media_stream_renderer_factory_impl.cc b/chromium/content/renderer/media/stream/media_stream_renderer_factory_impl.cc index 4e60ebaab8a..65151b93498 100644 --- a/chromium/content/renderer/media/stream/media_stream_renderer_factory_impl.cc +++ b/chromium/content/renderer/media/stream/media_stream_renderer_factory_impl.cc @@ -59,8 +59,8 @@ MediaStreamRendererFactoryImpl::GetVideoRenderer( DVLOG(1) << "MediaStreamRendererFactoryImpl::GetVideoRenderer stream:" << web_stream.Id().Utf8(); - blink::WebVector<blink::WebMediaStreamTrack> video_tracks; - web_stream.VideoTracks(video_tracks); + blink::WebVector<blink::WebMediaStreamTrack> video_tracks = + web_stream.VideoTracks(); if (video_tracks.IsEmpty() || !MediaStreamVideoTrack::GetTrack(video_tracks[0])) { return nullptr; @@ -76,8 +76,8 @@ MediaStreamRendererFactoryImpl::GetAudioRenderer( int render_frame_id, const std::string& device_id) { DCHECK(!web_stream.IsNull()); - blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; - web_stream.AudioTracks(audio_tracks); + blink::WebVector<blink::WebMediaStreamTrack> audio_tracks = + web_stream.AudioTracks(); if (audio_tracks.IsEmpty()) { WebRtcLogMessage("No audio tracks in media stream (return null)."); return nullptr; diff --git a/chromium/content/renderer/media/stream/mock_constraint_factory.cc b/chromium/content/renderer/media/stream/mock_constraint_factory.cc index b68c7cf159d..7f07e50046f 100644 --- a/chromium/content/renderer/media/stream/mock_constraint_factory.cc +++ b/chromium/content/renderer/media/stream/mock_constraint_factory.cc @@ -39,7 +39,6 @@ void MockConstraintFactory::DisableDefaultAudioConstraints() { basic_.goog_highpass_filter.SetExact(false); basic_.goog_typing_noise_detection.SetExact(false); basic_.goog_experimental_noise_suppression.SetExact(false); - basic_.goog_beamforming.SetExact(false); } void MockConstraintFactory::DisableAecAudioConstraints() { 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 9a13797562c..1f4094f216d 100644 --- a/chromium/content/renderer/media/stream/processed_local_audio_source.cc +++ b/chromium/content/renderer/media/stream/processed_local_audio_source.cc @@ -10,7 +10,7 @@ #include "base/logging.h" #include "base/metrics/histogram_macros.h" #include "base/strings/stringprintf.h" -#include "content/renderer/media/audio_device_factory.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" #include "content/renderer/media/webrtc/peer_connection_dependency_factory.h" @@ -24,6 +24,8 @@ namespace content { +using EchoCancellationType = AudioProcessingProperties::EchoCancellationType; + namespace { // Used as an identifier for ProcessedLocalAudioSource::From(). void* const kProcessedLocalAudioSourceIdentifier = @@ -97,19 +99,22 @@ bool ProcessedLocalAudioSource::EnsureSourceIsStarted() { MediaStreamDevice modified_device(device()); bool device_is_modified = false; - // Disable HW echo cancellation if constraints explicitly specified no - // echo cancellation. - if (audio_processing_properties_.disable_hw_echo_cancellation && - (device().input.effects() & media::AudioParameters::ECHO_CANCELLER)) { + // Disable system echo cancellation if specified by + // |audio_processing_properties_|. + if (audio_processing_properties_.echo_cancellation_type != + EchoCancellationType::kEchoCancellationSystem && + device().input.effects() & media::AudioParameters::ECHO_CANCELLER) { modified_device.input.set_effects(modified_device.input.effects() & ~media::AudioParameters::ECHO_CANCELLER); device_is_modified = true; - } else if (audio_processing_properties_ - .enable_experimental_hw_echo_cancellation && + } else if (audio_processing_properties_.echo_cancellation_type == + EchoCancellationType::kEchoCancellationSystem && (device().input.effects() & media::AudioParameters::EXPERIMENTAL_ECHO_CANCELLER)) { // Set the ECHO_CANCELLER effect, since that is what controls what's // actually being used. The EXPERIMENTAL_ flag only indicates availability. + // TODO(grunell): AND with + // ~media::AudioParameters::EXPERIMENTAL_ECHO_CANCELLER. modified_device.input.set_effects(modified_device.input.effects() | media::AudioParameters::ECHO_CANCELLER); device_is_modified = true; diff --git a/chromium/content/renderer/media/stream/processed_local_audio_source_unittest.cc b/chromium/content/renderer/media/stream/processed_local_audio_source_unittest.cc index 19df6b92642..6cc48ae1c3e 100644 --- a/chromium/content/renderer/media/stream/processed_local_audio_source_unittest.cc +++ b/chromium/content/renderer/media/stream/processed_local_audio_source_unittest.cc @@ -9,7 +9,7 @@ #include "base/message_loop/message_loop.h" #include "build/build_config.h" #include "content/public/renderer/media_stream_audio_sink.h" -#include "content/renderer/media/mock_audio_device_factory.h" +#include "content/renderer/media/audio/mock_audio_device_factory.h" #include "content/renderer/media/stream/media_stream_audio_processor_options.h" #include "content/renderer/media/stream/media_stream_audio_track.h" #include "content/renderer/media/stream/processed_local_audio_source.h" diff --git a/chromium/content/renderer/media/stream/track_audio_renderer.cc b/chromium/content/renderer/media/stream/track_audio_renderer.cc index 826d403c76d..bcedaf56920 100644 --- a/chromium/content/renderer/media/stream/track_audio_renderer.cc +++ b/chromium/content/renderer/media/stream/track_audio_renderer.cc @@ -12,7 +12,7 @@ #include "base/synchronization/lock.h" #include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/trace_event.h" -#include "content/renderer/media/audio_device_factory.h" +#include "content/renderer/media/audio/audio_device_factory.h" #include "content/renderer/media/stream/media_stream_audio_track.h" #include "media/base/audio_bus.h" #include "media/base/audio_latency.h" diff --git a/chromium/content/renderer/media/stream/user_media_client_impl_unittest.cc b/chromium/content/renderer/media/stream/user_media_client_impl_unittest.cc index 0415951c66b..703ea988283 100644 --- a/chromium/content/renderer/media/stream/user_media_client_impl_unittest.cc +++ b/chromium/content/renderer/media/stream/user_media_client_impl_unittest.cc @@ -42,6 +42,8 @@ using testing::_; namespace content { +using EchoCancellationType = AudioProcessingProperties::EchoCancellationType; + namespace { blink::WebMediaConstraints CreateDefaultConstraints() { @@ -469,10 +471,10 @@ class UserMediaClientImplTest : public ::testing::Test { EXPECT_EQ(REQUEST_SUCCEEDED, request_state()); blink::WebMediaStream desc = user_media_processor_->last_generated_stream(); - blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; - desc.AudioTracks(audio_tracks); - blink::WebVector<blink::WebMediaStreamTrack> video_tracks; - desc.VideoTracks(video_tracks); + blink::WebVector<blink::WebMediaStreamTrack> audio_tracks = + desc.AudioTracks(); + blink::WebVector<blink::WebMediaStreamTrack> video_tracks = + desc.VideoTracks(); EXPECT_EQ(1u, audio_tracks.size()); EXPECT_EQ(1u, video_tracks.size()); @@ -490,10 +492,10 @@ class UserMediaClientImplTest : public ::testing::Test { blink::WebMediaStream web_stream = user_media_processor_->last_generated_stream(); - blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; - web_stream.AudioTracks(audio_tracks); - blink::WebVector<blink::WebMediaStreamTrack> video_tracks; - web_stream.VideoTracks(video_tracks); + blink::WebVector<blink::WebMediaStreamTrack> audio_tracks = + web_stream.AudioTracks(); + blink::WebVector<blink::WebMediaStreamTrack> video_tracks = + web_stream.VideoTracks(); EXPECT_EQ(audio_tracks.size(), 0U); EXPECT_EQ(video_tracks.size(), 1U); @@ -515,10 +517,10 @@ class UserMediaClientImplTest : public ::testing::Test { EXPECT_EQ(REQUEST_SUCCEEDED, request_state()); blink::WebMediaStream desc = user_media_processor_->last_generated_stream(); - blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; - desc.AudioTracks(audio_tracks); - blink::WebVector<blink::WebMediaStreamTrack> video_tracks; - desc.VideoTracks(video_tracks); + blink::WebVector<blink::WebMediaStreamTrack> audio_tracks = + desc.AudioTracks(); + blink::WebVector<blink::WebMediaStreamTrack> video_tracks = + desc.VideoTracks(); EXPECT_EQ(audio_tracks.size(), 1u); EXPECT_TRUE(video_tracks.empty()); @@ -617,20 +619,20 @@ TEST_F(UserMediaClientImplTest, GenerateTwoMediaStreamsWithSameSource) { blink::WebMediaStream desc1 = RequestLocalMediaStream(); blink::WebMediaStream desc2 = RequestLocalMediaStream(); - blink::WebVector<blink::WebMediaStreamTrack> desc1_video_tracks; - desc1.VideoTracks(desc1_video_tracks); - blink::WebVector<blink::WebMediaStreamTrack> desc2_video_tracks; - desc2.VideoTracks(desc2_video_tracks); + blink::WebVector<blink::WebMediaStreamTrack> desc1_video_tracks = + desc1.VideoTracks(); + blink::WebVector<blink::WebMediaStreamTrack> desc2_video_tracks = + desc2.VideoTracks(); EXPECT_EQ(desc1_video_tracks[0].Source().Id(), desc2_video_tracks[0].Source().Id()); EXPECT_EQ(desc1_video_tracks[0].Source().GetExtraData(), desc2_video_tracks[0].Source().GetExtraData()); - blink::WebVector<blink::WebMediaStreamTrack> desc1_audio_tracks; - desc1.AudioTracks(desc1_audio_tracks); - blink::WebVector<blink::WebMediaStreamTrack> desc2_audio_tracks; - desc2.AudioTracks(desc2_audio_tracks); + blink::WebVector<blink::WebMediaStreamTrack> desc1_audio_tracks = + desc1.AudioTracks(); + blink::WebVector<blink::WebMediaStreamTrack> desc2_audio_tracks = + desc2.AudioTracks(); EXPECT_EQ(desc1_audio_tracks[0].Source().Id(), desc2_audio_tracks[0].Source().Id()); @@ -647,20 +649,20 @@ TEST_F(UserMediaClientImplTest, GenerateTwoMediaStreamsWithDifferentSources) { mock_dispatcher_host_.IncrementSessionId(); blink::WebMediaStream desc2 = RequestLocalMediaStream(); - blink::WebVector<blink::WebMediaStreamTrack> desc1_video_tracks; - desc1.VideoTracks(desc1_video_tracks); - blink::WebVector<blink::WebMediaStreamTrack> desc2_video_tracks; - desc2.VideoTracks(desc2_video_tracks); + blink::WebVector<blink::WebMediaStreamTrack> desc1_video_tracks = + desc1.VideoTracks(); + blink::WebVector<blink::WebMediaStreamTrack> desc2_video_tracks = + desc2.VideoTracks(); EXPECT_NE(desc1_video_tracks[0].Source().Id(), desc2_video_tracks[0].Source().Id()); EXPECT_NE(desc1_video_tracks[0].Source().GetExtraData(), desc2_video_tracks[0].Source().GetExtraData()); - blink::WebVector<blink::WebMediaStreamTrack> desc1_audio_tracks; - desc1.AudioTracks(desc1_audio_tracks); - blink::WebVector<blink::WebMediaStreamTrack> desc2_audio_tracks; - desc2.AudioTracks(desc2_audio_tracks); + blink::WebVector<blink::WebMediaStreamTrack> desc1_audio_tracks = + desc1.AudioTracks(); + blink::WebVector<blink::WebMediaStreamTrack> desc2_audio_tracks = + desc2.AudioTracks(); EXPECT_NE(desc1_audio_tracks[0].Source().Id(), desc2_audio_tracks[0].Source().Id()); @@ -672,15 +674,15 @@ TEST_F(UserMediaClientImplTest, StopLocalTracks) { // Generate a stream with both audio and video. blink::WebMediaStream mixed_desc = RequestLocalMediaStream(); - blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; - mixed_desc.AudioTracks(audio_tracks); + blink::WebVector<blink::WebMediaStreamTrack> audio_tracks = + mixed_desc.AudioTracks(); MediaStreamTrack* audio_track = MediaStreamTrack::GetTrack(audio_tracks[0]); audio_track->Stop(); base::RunLoop().RunUntilIdle(); EXPECT_EQ(1, mock_dispatcher_host_.stop_audio_device_counter()); - blink::WebVector<blink::WebMediaStreamTrack> video_tracks; - mixed_desc.VideoTracks(video_tracks); + blink::WebVector<blink::WebMediaStreamTrack> video_tracks = + mixed_desc.VideoTracks(); MediaStreamTrack* video_track = MediaStreamTrack::GetTrack(video_tracks[0]); video_track->Stop(); base::RunLoop().RunUntilIdle(); @@ -696,29 +698,29 @@ TEST_F(UserMediaClientImplTest, StopLocalTracksWhenTwoStreamUseSameDevices) { blink::WebMediaStream desc1 = RequestLocalMediaStream(); blink::WebMediaStream desc2 = RequestLocalMediaStream(); - blink::WebVector<blink::WebMediaStreamTrack> audio_tracks1; - desc1.AudioTracks(audio_tracks1); + blink::WebVector<blink::WebMediaStreamTrack> audio_tracks1 = + desc1.AudioTracks(); MediaStreamTrack* audio_track1 = MediaStreamTrack::GetTrack(audio_tracks1[0]); audio_track1->Stop(); base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, mock_dispatcher_host_.stop_audio_device_counter()); - blink::WebVector<blink::WebMediaStreamTrack> audio_tracks2; - desc2.AudioTracks(audio_tracks2); + blink::WebVector<blink::WebMediaStreamTrack> audio_tracks2 = + desc2.AudioTracks(); MediaStreamTrack* audio_track2 = MediaStreamTrack::GetTrack(audio_tracks2[0]); audio_track2->Stop(); base::RunLoop().RunUntilIdle(); EXPECT_EQ(1, mock_dispatcher_host_.stop_audio_device_counter()); - blink::WebVector<blink::WebMediaStreamTrack> video_tracks1; - desc1.VideoTracks(video_tracks1); + blink::WebVector<blink::WebMediaStreamTrack> video_tracks1 = + desc1.VideoTracks(); MediaStreamTrack* video_track1 = MediaStreamTrack::GetTrack(video_tracks1[0]); video_track1->Stop(); base::RunLoop().RunUntilIdle(); EXPECT_EQ(0, mock_dispatcher_host_.stop_video_device_counter()); - blink::WebVector<blink::WebMediaStreamTrack> video_tracks2; - desc2.VideoTracks(video_tracks2); + blink::WebVector<blink::WebMediaStreamTrack> video_tracks2 = + desc2.VideoTracks(); MediaStreamTrack* video_track2 = MediaStreamTrack::GetTrack(video_tracks2[0]); video_track2->Stop(); base::RunLoop().RunUntilIdle(); @@ -823,15 +825,15 @@ TEST_F(UserMediaClientImplTest, StopTrackAfterReload) { EXPECT_EQ(1, mock_dispatcher_host_.stop_audio_device_counter()); EXPECT_EQ(1, mock_dispatcher_host_.stop_video_device_counter()); - blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; - mixed_desc.AudioTracks(audio_tracks); + blink::WebVector<blink::WebMediaStreamTrack> audio_tracks = + mixed_desc.AudioTracks(); MediaStreamTrack* audio_track = MediaStreamTrack::GetTrack(audio_tracks[0]); audio_track->Stop(); base::RunLoop().RunUntilIdle(); EXPECT_EQ(1, mock_dispatcher_host_.stop_audio_device_counter()); - blink::WebVector<blink::WebMediaStreamTrack> video_tracks; - mixed_desc.VideoTracks(video_tracks); + blink::WebVector<blink::WebMediaStreamTrack> video_tracks = + mixed_desc.VideoTracks(); MediaStreamTrack* video_track = MediaStreamTrack::GetTrack(video_tracks[0]); video_track->Stop(); base::RunLoop().RunUntilIdle(); @@ -859,8 +861,8 @@ TEST_F(UserMediaClientImplTest, DefaultConstraintsPropagate) { const AudioProcessingProperties& properties = audio_capture_settings.audio_processing_properties(); - EXPECT_TRUE(properties.enable_sw_echo_cancellation); - EXPECT_TRUE(properties.disable_hw_echo_cancellation); + EXPECT_EQ(EchoCancellationType::kEchoCancellationAec2, + properties.echo_cancellation_type); EXPECT_FALSE(properties.goog_audio_mirroring); EXPECT_TRUE(properties.goog_auto_gain_control); // The default value for goog_experimental_echo_cancellation is platform @@ -870,10 +872,8 @@ TEST_F(UserMediaClientImplTest, DefaultConstraintsPropagate) { EXPECT_TRUE(properties.goog_typing_noise_detection); EXPECT_TRUE(properties.goog_noise_suppression); EXPECT_TRUE(properties.goog_experimental_noise_suppression); - EXPECT_TRUE(properties.goog_beamforming); EXPECT_TRUE(properties.goog_highpass_filter); EXPECT_TRUE(properties.goog_experimental_auto_gain_control); - EXPECT_TRUE(properties.goog_array_geometry.empty()); EXPECT_TRUE(video_capture_settings.HasValue()); EXPECT_EQ(video_capture_settings.Width(), @@ -928,18 +928,16 @@ TEST_F(UserMediaClientImplTest, DefaultTabCapturePropagate) { const AudioProcessingProperties& properties = audio_capture_settings.audio_processing_properties(); - EXPECT_FALSE(properties.enable_sw_echo_cancellation); - EXPECT_TRUE(properties.disable_hw_echo_cancellation); + EXPECT_EQ(EchoCancellationType::kEchoCancellationDisabled, + properties.echo_cancellation_type); EXPECT_FALSE(properties.goog_audio_mirroring); EXPECT_FALSE(properties.goog_auto_gain_control); EXPECT_FALSE(properties.goog_experimental_echo_cancellation); EXPECT_FALSE(properties.goog_typing_noise_detection); EXPECT_FALSE(properties.goog_noise_suppression); EXPECT_FALSE(properties.goog_experimental_noise_suppression); - EXPECT_FALSE(properties.goog_beamforming); EXPECT_FALSE(properties.goog_highpass_filter); EXPECT_FALSE(properties.goog_experimental_auto_gain_control); - EXPECT_TRUE(properties.goog_array_geometry.empty()); EXPECT_TRUE(video_capture_settings.HasValue()); EXPECT_EQ(video_capture_settings.Width(), kDefaultScreenCastWidth); @@ -991,18 +989,16 @@ TEST_F(UserMediaClientImplTest, DefaultDesktopCapturePropagate) { const AudioProcessingProperties& properties = audio_capture_settings.audio_processing_properties(); - EXPECT_FALSE(properties.enable_sw_echo_cancellation); - EXPECT_TRUE(properties.disable_hw_echo_cancellation); + EXPECT_EQ(EchoCancellationType::kEchoCancellationDisabled, + properties.echo_cancellation_type); EXPECT_FALSE(properties.goog_audio_mirroring); EXPECT_FALSE(properties.goog_auto_gain_control); EXPECT_FALSE(properties.goog_experimental_echo_cancellation); EXPECT_FALSE(properties.goog_typing_noise_detection); EXPECT_FALSE(properties.goog_noise_suppression); EXPECT_FALSE(properties.goog_experimental_noise_suppression); - EXPECT_FALSE(properties.goog_beamforming); EXPECT_FALSE(properties.goog_highpass_filter); EXPECT_FALSE(properties.goog_experimental_auto_gain_control); - EXPECT_TRUE(properties.goog_array_geometry.empty()); EXPECT_TRUE(video_capture_settings.HasValue()); EXPECT_EQ(video_capture_settings.Width(), kDefaultScreenCastWidth); @@ -1038,8 +1034,6 @@ TEST_F(UserMediaClientImplTest, NonDefaultAudioConstraintsPropagate) { factory.basic().echo_cancellation.SetExact(false); factory.basic().goog_audio_mirroring.SetExact(true); factory.basic().goog_typing_noise_detection.SetExact(true); - factory.basic().goog_array_geometry.SetExact( - blink::WebString::FromASCII("1 1 1")); blink::WebMediaConstraints audio_constraints = factory.CreateWebMediaConstraints(); // Request contains only audio @@ -1063,19 +1057,16 @@ TEST_F(UserMediaClientImplTest, NonDefaultAudioConstraintsPropagate) { const AudioProcessingProperties& properties = audio_capture_settings.audio_processing_properties(); - EXPECT_FALSE(properties.enable_sw_echo_cancellation); - EXPECT_TRUE(properties.disable_hw_echo_cancellation); + EXPECT_EQ(EchoCancellationType::kEchoCancellationDisabled, + properties.echo_cancellation_type); EXPECT_TRUE(properties.goog_audio_mirroring); EXPECT_FALSE(properties.goog_auto_gain_control); EXPECT_FALSE(properties.goog_experimental_echo_cancellation); EXPECT_TRUE(properties.goog_typing_noise_detection); EXPECT_FALSE(properties.goog_noise_suppression); EXPECT_FALSE(properties.goog_experimental_noise_suppression); - EXPECT_FALSE(properties.goog_beamforming); EXPECT_FALSE(properties.goog_highpass_filter); EXPECT_FALSE(properties.goog_experimental_auto_gain_control); - const std::vector<media::Point> kGeometry = {{1.0, 1.0, 1.0}}; - EXPECT_EQ(kGeometry, properties.goog_array_geometry); } TEST_F(UserMediaClientImplTest, CreateWithMandatoryInvalidAudioDeviceId) { diff --git a/chromium/content/renderer/media/stream/user_media_processor.cc b/chromium/content/renderer/media/stream/user_media_processor.cc index cba8d68a14e..bd5929a359b 100644 --- a/chromium/content/renderer/media/stream/user_media_processor.cc +++ b/chromium/content/renderer/media/stream/user_media_processor.cc @@ -47,6 +47,10 @@ #include "url/origin.h" namespace content { + +using blink::WebMediaStreamSource; +using EchoCancellationType = AudioProcessingProperties::EchoCancellationType; + namespace { void CopyFirstString(const blink::StringConstraint& constraint, @@ -101,37 +105,48 @@ bool IsValidVideoContentSource(const std::string& source) { void SurfaceAudioProcessingSettings(blink::WebMediaStreamSource* source) { MediaStreamAudioSource* source_impl = static_cast<MediaStreamAudioSource*>(source->GetExtraData()); - bool sw_echo_cancellation = false, auto_gain_control = false, - noise_supression = false, hw_echo_cancellation = false; + + // If the source is a processed source, get the properties from it. if (ProcessedLocalAudioSource* processed_source = ProcessedLocalAudioSource::From(source_impl)) { AudioProcessingProperties properties = processed_source->audio_processing_properties(); - sw_echo_cancellation = properties.enable_sw_echo_cancellation; - auto_gain_control = properties.goog_auto_gain_control; - noise_supression = properties.goog_noise_suppression; - // The ECHO_CANCELLER flag will be set if either: - // - The device advertises the ECHO_CANCELLER flag and - // disable_hw_echo_cancellation is false; or if - // - The device advertises the EXPERIMENTAL_ECHO_CANCELLER flag and - // enable_experimental_hw_echo_cancellation is true. - // See: ProcessedLocalAudioSource::EnsureSourceIsStarted(). - const media::AudioParameters& params = processed_source->device().input; - hw_echo_cancellation = - params.IsValid() && - (params.effects() & media::AudioParameters::ECHO_CANCELLER); - } + WebMediaStreamSource::EchoCancellationMode echo_cancellation_mode; - using blink::WebMediaStreamSource; - const WebMediaStreamSource::EchoCancellationMode echo_cancellation_mode = - hw_echo_cancellation - ? WebMediaStreamSource::EchoCancellationMode::kHardware - : sw_echo_cancellation - ? WebMediaStreamSource::EchoCancellationMode::kSoftware - : WebMediaStreamSource::EchoCancellationMode::kDisabled; + switch (properties.echo_cancellation_type) { + case EchoCancellationType::kEchoCancellationDisabled: + echo_cancellation_mode = + WebMediaStreamSource::EchoCancellationMode::kDisabled; + break; + case EchoCancellationType::kEchoCancellationAec2: + echo_cancellation_mode = + WebMediaStreamSource::EchoCancellationMode::kBrowser; + break; + case EchoCancellationType::kEchoCancellationAec3: + echo_cancellation_mode = + WebMediaStreamSource::EchoCancellationMode::kAec3; + break; + case EchoCancellationType::kEchoCancellationSystem: + echo_cancellation_mode = + WebMediaStreamSource::EchoCancellationMode::kSystem; + break; + } + + source->SetAudioProcessingProperties(echo_cancellation_mode, + properties.goog_auto_gain_control, + properties.goog_noise_suppression); + } else { + // If the source is not a processed source, it could still support system + // echo cancellation. Surface that if it does. + media::AudioParameters params = source_impl->GetAudioParameters(); + const WebMediaStreamSource::EchoCancellationMode echo_cancellation_mode = + params.IsValid() && + (params.effects() & media::AudioParameters::ECHO_CANCELLER) + ? WebMediaStreamSource::EchoCancellationMode::kSystem + : WebMediaStreamSource::EchoCancellationMode::kDisabled; - source->SetAudioProcessingProperties(echo_cancellation_mode, - auto_gain_control, noise_supression); + source->SetAudioProcessingProperties(echo_cancellation_mode, false, false); + } } } // namespace @@ -458,10 +473,12 @@ void UserMediaProcessor::SelectAudioDeviceSettings( if (source->device().type == MEDIA_DEVICE_AUDIO_CAPTURE) audio_source = static_cast<MediaStreamAudioSource*>(source); } - if (audio_source) + if (audio_source) { capabilities.emplace_back(audio_source); - else - capabilities.emplace_back(device->device_id, device->parameters); + } else { + capabilities.emplace_back(device->device_id, device->group_id, + device->parameters); + } } SelectAudioSettings(web_request, capabilities); @@ -864,9 +881,11 @@ blink::WebMediaStreamSource UserMediaProcessor::InitializeAudioSourceObject( blink::WebMediaStreamSource::Capabilities capabilities; capabilities.echo_cancellation = {true, false}; - capabilities.echo_cancellation_type.reserve(2); + capabilities.echo_cancellation_type.reserve(3); capabilities.echo_cancellation_type.emplace_back( blink::WebString::FromASCII(blink::kEchoCancellationTypeBrowser)); + capabilities.echo_cancellation_type.emplace_back( + blink::WebString::FromASCII(blink::kEchoCancellationTypeAec3)); if (device.input.effects() & (media::AudioParameters::ECHO_CANCELLER | media::AudioParameters::EXPERIMENTAL_ECHO_CANCELLER)) { @@ -1010,15 +1029,13 @@ void UserMediaProcessor::OnCreateNativeTracksCompleted( } else { GetUserMediaRequestFailed(result, constraint_name); - blink::WebVector<blink::WebMediaStreamTrack> tracks; - request_info->web_stream()->AudioTracks(tracks); - for (auto& web_track : tracks) { + for (auto& web_track : request_info->web_stream()->AudioTracks()) { MediaStreamTrack* track = MediaStreamTrack::GetTrack(web_track); if (track) track->Stop(); } - request_info->web_stream()->VideoTracks(tracks); - for (auto& web_track : tracks) { + + for (auto& web_track : request_info->web_stream()->VideoTracks()) { MediaStreamTrack* track = MediaStreamTrack::GetTrack(web_track); if (track) track->Stop(); diff --git a/chromium/content/renderer/media/stream/webmediaplayer_ms.cc b/chromium/content/renderer/media/stream/webmediaplayer_ms.cc index d8483027e0a..2d13eb7cb58 100644 --- a/chromium/content/renderer/media/stream/webmediaplayer_ms.cc +++ b/chromium/content/renderer/media/stream/webmediaplayer_ms.cc @@ -323,9 +323,10 @@ WebMediaPlayerMS::~WebMediaPlayerMS() { delegate_->RemoveObserver(delegate_id_); } -void WebMediaPlayerMS::Load(LoadType load_type, - const blink::WebMediaPlayerSource& source, - CORSMode /*cors_mode*/) { +blink::WebMediaPlayer::LoadTiming WebMediaPlayerMS::Load( + LoadType load_type, + const blink::WebMediaPlayerSource& source, + CORSMode /*cors_mode*/) { DVLOG(1) << __func__; DCHECK(thread_checker_.CalledOnValidThread()); @@ -376,7 +377,7 @@ void WebMediaPlayerMS::Load(LoadType load_type, if (!video_frame_provider_ && !audio_renderer_) { SetNetworkState(WebMediaPlayer::kNetworkStateNetworkError); - return; + return blink::WebMediaPlayer::LoadTiming::kImmediate; } if (audio_renderer_) { @@ -384,9 +385,9 @@ void WebMediaPlayerMS::Load(LoadType load_type, audio_renderer_->Start(); // Store the ID of audio track being played in |current_video_track_id_| - blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; if (!web_stream_.IsNull()) { - web_stream_.AudioTracks(audio_tracks); + blink::WebVector<blink::WebMediaStreamTrack> audio_tracks = + web_stream_.AudioTracks(); DCHECK_GT(audio_tracks.size(), 0U); current_audio_track_id_ = audio_tracks[0].Id(); } @@ -397,8 +398,8 @@ void WebMediaPlayerMS::Load(LoadType load_type, // Store the ID of video track being played in |current_video_track_id_| if (!web_stream_.IsNull()) { - blink::WebVector<blink::WebMediaStreamTrack> video_tracks; - web_stream_.VideoTracks(video_tracks); + blink::WebVector<blink::WebMediaStreamTrack> video_tracks = + web_stream_.VideoTracks(); DCHECK_GT(video_tracks.size(), 0U); current_video_track_id_ = video_tracks[0].Id(); } @@ -413,6 +414,8 @@ void WebMediaPlayerMS::Load(LoadType load_type, SetReadyState(WebMediaPlayer::kReadyStateHaveMetadata); SetReadyState(WebMediaPlayer::kReadyStateHaveEnoughData); } + + return blink::WebMediaPlayer::LoadTiming::kImmediate; } void WebMediaPlayerMS::TrackAdded(const blink::WebMediaStreamTrack& track) { @@ -455,9 +458,8 @@ void WebMediaPlayerMS::Reload() { void WebMediaPlayerMS::ReloadVideo() { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(!web_stream_.IsNull()); - blink::WebVector<blink::WebMediaStreamTrack> video_tracks; - // VideoTracks() is a getter. - web_stream_.VideoTracks(video_tracks); + blink::WebVector<blink::WebMediaStreamTrack> video_tracks = + web_stream_.VideoTracks(); RendererReloadAction renderer_action = RendererReloadAction::KEEP_RENDERER; if (video_tracks.IsEmpty()) { @@ -506,9 +508,8 @@ void WebMediaPlayerMS::ReloadAudio() { if (!frame) return; - blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; - // AudioTracks() is a getter. - web_stream_.AudioTracks(audio_tracks); + blink::WebVector<blink::WebMediaStreamTrack> audio_tracks = + web_stream_.AudioTracks(); RendererReloadAction renderer_action = RendererReloadAction::KEEP_RENDERER; if (audio_tracks.IsEmpty()) { @@ -763,7 +764,7 @@ bool WebMediaPlayerMS::DidLoadingProgress() { return true; } -void WebMediaPlayerMS::Paint(blink::WebCanvas* canvas, +void WebMediaPlayerMS::Paint(cc::PaintCanvas* canvas, const blink::WebRect& rect, cc::PaintFlags& flags, int already_uploaded_id, @@ -921,6 +922,11 @@ void WebMediaPlayerMS::OnPictureInPictureModeEnded() { NOTIMPLEMENTED(); } +void WebMediaPlayerMS::OnPictureInPictureControlClicked( + const std::string& control_id) { + NOTIMPLEMENTED(); +} + bool WebMediaPlayerMS::CopyVideoTextureToPlatformTexture( gpu::gles2::GLES2Interface* gl, unsigned target, diff --git a/chromium/content/renderer/media/stream/webmediaplayer_ms.h b/chromium/content/renderer/media/stream/webmediaplayer_ms.h index fe0de43a473..4af79567b43 100644 --- a/chromium/content/renderer/media/stream/webmediaplayer_ms.h +++ b/chromium/content/renderer/media/stream/webmediaplayer_ms.h @@ -86,9 +86,10 @@ class CONTENT_EXPORT WebMediaPlayerMS ~WebMediaPlayerMS() override; - void Load(LoadType load_type, - const blink::WebMediaPlayerSource& source, - CORSMode cors_mode) override; + blink::WebMediaPlayer::LoadTiming Load( + LoadType load_type, + const blink::WebMediaPlayerSource& source, + CORSMode cors_mode) override; // Playback controls. void Play() override; @@ -109,7 +110,7 @@ class CONTENT_EXPORT WebMediaPlayerMS blink::WebTimeRanges Seekable() const override; // Methods for painting. - void Paint(blink::WebCanvas* canvas, + void Paint(cc::PaintCanvas* canvas, const blink::WebRect& rect, cc::PaintFlags& flags, int already_uploaded_id, @@ -165,6 +166,7 @@ class CONTENT_EXPORT WebMediaPlayerMS void OnVolumeMultiplierUpdate(double multiplier) override; void OnBecamePersistentVideo(bool value) override; void OnPictureInPictureModeEnded() override; + void OnPictureInPictureControlClicked(const std::string& control_id) override; bool CopyVideoTextureToPlatformTexture( gpu::gles2::GLES2Interface* gl, diff --git a/chromium/content/renderer/media/stream/webmediaplayer_ms_compositor.cc b/chromium/content/renderer/media/stream/webmediaplayer_ms_compositor.cc index 207339b835a..c123ce1f0ec 100644 --- a/chromium/content/renderer/media/stream/webmediaplayer_ms_compositor.cc +++ b/chromium/content/renderer/media/stream/webmediaplayer_ms_compositor.cc @@ -73,20 +73,21 @@ scoped_refptr<media::VideoFrame> CopyFrame( const bool result = bitmap.peekPixels(&pixmap); DCHECK(result) << "Error trying to access SkBitmap's pixels"; - const uint32 source_pixel_format = + const uint32_t source_pixel_format = (kN32_SkColorType == kRGBA_8888_SkColorType) ? libyuv::FOURCC_ABGR : libyuv::FOURCC_ARGB; - libyuv::ConvertToI420( - static_cast<const uint8*>(pixmap.addr(0, 0)), pixmap.computeByteSize(), - new_frame->visible_data(media::VideoFrame::kYPlane), - new_frame->stride(media::VideoFrame::kYPlane), - new_frame->visible_data(media::VideoFrame::kUPlane), - new_frame->stride(media::VideoFrame::kUPlane), - new_frame->visible_data(media::VideoFrame::kVPlane), - new_frame->stride(media::VideoFrame::kVPlane), 0 /* crop_x */, - 0 /* crop_y */, pixmap.width(), pixmap.height(), - new_frame->visible_rect().width(), new_frame->visible_rect().height(), - libyuv::kRotate0, source_pixel_format); + libyuv::ConvertToI420(static_cast<const uint8_t*>(pixmap.addr(0, 0)), + pixmap.computeByteSize(), + new_frame->visible_data(media::VideoFrame::kYPlane), + new_frame->stride(media::VideoFrame::kYPlane), + new_frame->visible_data(media::VideoFrame::kUPlane), + new_frame->stride(media::VideoFrame::kUPlane), + new_frame->visible_data(media::VideoFrame::kVPlane), + new_frame->stride(media::VideoFrame::kVPlane), + 0 /* crop_x */, 0 /* crop_y */, pixmap.width(), + pixmap.height(), new_frame->visible_rect().width(), + new_frame->visible_rect().height(), libyuv::kRotate0, + source_pixel_format); } else { DCHECK(frame->IsMappable()); DCHECK(frame->format() == media::PIXEL_FORMAT_I420A || @@ -145,7 +146,7 @@ WebMediaPlayerMSCompositor::WebMediaPlayerMSCompositor( blink::WebVector<blink::WebMediaStreamTrack> video_tracks; if (!web_stream.IsNull()) - web_stream.VideoTracks(video_tracks); + video_tracks = web_stream.VideoTracks(); const bool remote_video = video_tracks.size() && video_tracks[0].Source().Remote(); diff --git a/chromium/content/renderer/media/stream/webmediaplayer_ms_unittest.cc b/chromium/content/renderer/media/stream/webmediaplayer_ms_unittest.cc index 00933375538..5f7235954c0 100644 --- a/chromium/content/renderer/media/stream/webmediaplayer_ms_unittest.cc +++ b/chromium/content/renderer/media/stream/webmediaplayer_ms_unittest.cc @@ -514,7 +514,6 @@ class WebMediaPlayerMSTest void Repaint() override {} void DurationChanged() override {} void SizeChanged() override; - void PlaybackStateChanged() override {} void SetCcLayer(cc::Layer* layer) override; blink::WebMediaPlayer::TrackId AddAudioTrack(const blink::WebString& id, AudioTrackKind, @@ -545,7 +544,7 @@ class WebMediaPlayerMSTest void RemotePlaybackCompatibilityChanged(const blink::WebURL& url, bool is_compatible) override {} void OnBecamePersistentVideo(bool) override {} - bool IsAutoplayingMuted() override { return false; } + bool WasAlwaysMuted() override { return false; } bool HasSelectedVideoTrack() override { return false; } blink::WebMediaPlayer::TrackId GetSelectedVideoTrackId() override { return blink::WebMediaPlayer::TrackId(); @@ -562,12 +561,17 @@ class WebMediaPlayerMSTest void MediaRemotingStopped( blink::WebLocalizedString::Name error_msg) override {} void PictureInPictureStopped() override {} + void PictureInPictureControlClicked( + const blink::WebString& control_id) override {} + void RequestPlay() override {} + void RequestPause() override {} // Implementation of cc::VideoFrameProvider::Client void StopUsingProvider() override; void StartRendering() override; void StopRendering() override; void DidReceiveFrame() override; + bool IsDrivingFrameUpdates() const override { return true; } // For test use void SetBackgroundRendering(bool background_rendering) { diff --git a/chromium/content/renderer/media/video_capture_impl.cc b/chromium/content/renderer/media/video_capture_impl.cc index d5c5d8358c0..edf50675310 100644 --- a/chromium/content/renderer/media/video_capture_impl.cc +++ b/chromium/content/renderer/media/video_capture_impl.cc @@ -41,6 +41,9 @@ struct VideoCaptureImpl::BufferContext InitializeFromSharedMemory( std::move(buffer_handle->get_shared_buffer_handle())); break; + case VideoFrameBufferHandleType::SHARED_MEMORY_VIA_RAW_FILE_DESCRIPTOR: + NOTREACHED(); + break; case VideoFrameBufferHandleType::MAILBOX_HANDLES: InitializeFromMailbox(std::move(buffer_handle->get_mailbox_handles())); break; @@ -346,6 +349,9 @@ void VideoCaptureImpl::OnBufferReady(int32_t buffer_id, buffer_context->shared_memory()->handle(), 0 /* shared_memory_offset */, info->timestamp); break; + case VideoFrameBufferHandleType::SHARED_MEMORY_VIA_RAW_FILE_DESCRIPTOR: + NOTREACHED(); + break; case VideoFrameBufferHandleType::MAILBOX_HANDLES: gpu::MailboxHolder mailbox_holder_array[media::VideoFrame::kMaxPlanes]; CHECK_EQ(media::VideoFrame::kMaxPlanes, diff --git a/chromium/content/renderer/media/webrtc/audio_codec_factory.cc b/chromium/content/renderer/media/webrtc/audio_codec_factory.cc index be2d15aa1c5..73abab19515 100644 --- a/chromium/content/renderer/media/webrtc/audio_codec_factory.cc +++ b/chromium/content/renderer/media/webrtc/audio_codec_factory.cc @@ -28,7 +28,7 @@ namespace { template <typename T> struct NotAdvertisedEncoder { using Config = typename T::Config; - static rtc::Optional<Config> SdpToConfig( + static absl::optional<Config> SdpToConfig( const webrtc::SdpAudioFormat& audio_format) { return T::SdpToConfig(audio_format); } @@ -42,7 +42,7 @@ struct NotAdvertisedEncoder { static std::unique_ptr<webrtc::AudioEncoder> MakeAudioEncoder( const Config& config, int payload_type, - rtc::Optional<webrtc::AudioCodecPairId> codec_pair_id) { + absl::optional<webrtc::AudioCodecPairId> codec_pair_id) { return T::MakeAudioEncoder(config, payload_type, codec_pair_id); } }; @@ -51,7 +51,7 @@ struct NotAdvertisedEncoder { template <typename T> struct NotAdvertisedDecoder { using Config = typename T::Config; - static rtc::Optional<Config> SdpToConfig( + static absl::optional<Config> SdpToConfig( const webrtc::SdpAudioFormat& audio_format) { return T::SdpToConfig(audio_format); } @@ -61,7 +61,7 @@ struct NotAdvertisedDecoder { } static std::unique_ptr<webrtc::AudioDecoder> MakeAudioDecoder( const Config& config, - rtc::Optional<webrtc::AudioCodecPairId> codec_pair_id) { + absl::optional<webrtc::AudioCodecPairId> codec_pair_id) { return T::MakeAudioDecoder(config, codec_pair_id); } }; diff --git a/chromium/content/renderer/media/webrtc/fake_rtc_rtp_transceiver.cc b/chromium/content/renderer/media/webrtc/fake_rtc_rtp_transceiver.cc new file mode 100644 index 00000000000..acb9937d405 --- /dev/null +++ b/chromium/content/renderer/media/webrtc/fake_rtc_rtp_transceiver.cc @@ -0,0 +1,193 @@ +// 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/fake_rtc_rtp_transceiver.h" + +namespace content { + +blink::WebMediaStreamTrack CreateWebMediaStreamTrack(const std::string& id) { + blink::WebMediaStreamSource web_source; + web_source.Initialize(blink::WebString::FromUTF8(id), + blink::WebMediaStreamSource::kTypeAudio, + blink::WebString::FromUTF8("audio_track"), false); + MediaStreamAudioSource* audio_source = new MediaStreamAudioSource(true); + // Takes ownership of |audio_source|. + web_source.SetExtraData(audio_source); + + blink::WebMediaStreamTrack web_track; + web_track.Initialize(web_source.Id(), web_source); + audio_source->ConnectToTrack(web_track); + return web_track; +} + +FakeRTCRtpSender::FakeRTCRtpSender(base::Optional<std::string> track_id, + std::vector<std::string> stream_ids) + : track_id_(std::move(track_id)), stream_ids_(std::move(stream_ids)) {} + +FakeRTCRtpSender::FakeRTCRtpSender(const FakeRTCRtpSender&) = default; + +FakeRTCRtpSender::~FakeRTCRtpSender() {} + +FakeRTCRtpSender& FakeRTCRtpSender::operator=(const FakeRTCRtpSender&) = + default; + +std::unique_ptr<blink::WebRTCRtpSender> FakeRTCRtpSender::ShallowCopy() const { + return std::make_unique<FakeRTCRtpSender>(*this); +} + +uintptr_t FakeRTCRtpSender::Id() const { + NOTIMPLEMENTED(); + return 0; +} + +blink::WebMediaStreamTrack FakeRTCRtpSender::Track() const { + return track_id_ ? CreateWebMediaStreamTrack(*track_id_) + : blink::WebMediaStreamTrack(); // null +} + +blink::WebVector<blink::WebString> FakeRTCRtpSender::StreamIds() const { + blink::WebVector<blink::WebString> web_stream_ids(stream_ids_.size()); + for (size_t i = 0; i < stream_ids_.size(); ++i) { + web_stream_ids[i] = blink::WebString::FromUTF8(stream_ids_[i]); + } + return web_stream_ids; +} + +void FakeRTCRtpSender::ReplaceTrack(blink::WebMediaStreamTrack with_track, + blink::WebRTCVoidRequest request) { + NOTIMPLEMENTED(); +} + +std::unique_ptr<blink::WebRTCDTMFSenderHandler> +FakeRTCRtpSender::GetDtmfSender() const { + NOTIMPLEMENTED(); + return nullptr; +} + +std::unique_ptr<webrtc::RtpParameters> FakeRTCRtpSender::GetParameters() const { + NOTIMPLEMENTED(); + return nullptr; +} + +void FakeRTCRtpSender::SetParameters( + blink::WebVector<webrtc::RtpEncodingParameters>, + webrtc::DegradationPreference, + blink::WebRTCVoidRequest) { + NOTIMPLEMENTED(); +} + +void FakeRTCRtpSender::GetStats( + std::unique_ptr<blink::WebRTCStatsReportCallback>) { + NOTIMPLEMENTED(); +} + +FakeRTCRtpReceiver::FakeRTCRtpReceiver(const std::string& track_id, + std::vector<std::string> stream_ids) + : track_(CreateWebMediaStreamTrack(track_id)), + stream_ids_(std::move(stream_ids)) {} + +FakeRTCRtpReceiver::FakeRTCRtpReceiver(const FakeRTCRtpReceiver&) = default; + +FakeRTCRtpReceiver::~FakeRTCRtpReceiver() {} + +FakeRTCRtpReceiver& FakeRTCRtpReceiver::operator=(const FakeRTCRtpReceiver&) = + default; + +std::unique_ptr<blink::WebRTCRtpReceiver> FakeRTCRtpReceiver::ShallowCopy() + const { + return std::make_unique<FakeRTCRtpReceiver>(*this); +} + +uintptr_t FakeRTCRtpReceiver::Id() const { + NOTIMPLEMENTED(); + return 0; +} + +const blink::WebMediaStreamTrack& FakeRTCRtpReceiver::Track() const { + return track_; +} + +blink::WebVector<blink::WebString> FakeRTCRtpReceiver::StreamIds() const { + blink::WebVector<blink::WebString> web_stream_ids(stream_ids_.size()); + for (size_t i = 0; i < stream_ids_.size(); ++i) { + web_stream_ids[i] = blink::WebString::FromUTF8(stream_ids_[i]); + } + return web_stream_ids; +} + +blink::WebVector<std::unique_ptr<blink::WebRTCRtpContributingSource>> +FakeRTCRtpReceiver::GetSources() { + NOTIMPLEMENTED(); + return {}; +} + +void FakeRTCRtpReceiver::GetStats( + std::unique_ptr<blink::WebRTCStatsReportCallback>) { + NOTIMPLEMENTED(); +} + +FakeRTCRtpTransceiver::FakeRTCRtpTransceiver( + base::Optional<std::string> mid, + FakeRTCRtpSender sender, + FakeRTCRtpReceiver receiver, + bool stopped, + webrtc::RtpTransceiverDirection direction, + base::Optional<webrtc::RtpTransceiverDirection> current_direction) + : mid_(std::move(mid)), + sender_(std::move(sender)), + receiver_(std::move(receiver)), + stopped_(stopped), + direction_(std::move(direction)), + current_direction_(std::move(current_direction)) {} + +FakeRTCRtpTransceiver::~FakeRTCRtpTransceiver() {} + +blink::WebRTCRtpTransceiverImplementationType +FakeRTCRtpTransceiver::ImplementationType() const { + return blink::WebRTCRtpTransceiverImplementationType::kFullTransceiver; +} + +uintptr_t FakeRTCRtpTransceiver::Id() const { + NOTIMPLEMENTED(); + return 0u; +} + +blink::WebString FakeRTCRtpTransceiver::Mid() const { + return mid_ ? blink::WebString::FromUTF8(*mid_) : blink::WebString(); +} + +std::unique_ptr<blink::WebRTCRtpSender> FakeRTCRtpTransceiver::Sender() const { + return sender_.ShallowCopy(); +} + +std::unique_ptr<blink::WebRTCRtpReceiver> FakeRTCRtpTransceiver::Receiver() + const { + return receiver_.ShallowCopy(); +} + +bool FakeRTCRtpTransceiver::Stopped() const { + return stopped_; +} + +webrtc::RtpTransceiverDirection FakeRTCRtpTransceiver::Direction() const { + return direction_; +} + +void FakeRTCRtpTransceiver::SetDirection( + webrtc::RtpTransceiverDirection direction) { + NOTIMPLEMENTED(); +} + +base::Optional<webrtc::RtpTransceiverDirection> +FakeRTCRtpTransceiver::CurrentDirection() const { + return current_direction_; +} + +base::Optional<webrtc::RtpTransceiverDirection> +FakeRTCRtpTransceiver::FiredDirection() const { + NOTIMPLEMENTED(); + return base::nullopt; +} + +} // namespace content diff --git a/chromium/content/renderer/media/webrtc/fake_rtc_rtp_transceiver.h b/chromium/content/renderer/media/webrtc/fake_rtc_rtp_transceiver.h new file mode 100644 index 00000000000..7f8dbfed61a --- /dev/null +++ b/chromium/content/renderer/media/webrtc/fake_rtc_rtp_transceiver.h @@ -0,0 +1,111 @@ +// 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_FAKE_RTC_RTP_TRANSCEIVER_H_ +#define CONTENT_RENDERER_MEDIA_WEBRTC_FAKE_RTC_RTP_TRANSCEIVER_H_ + +#include <memory> + +#include "content/renderer/media/stream/media_stream_audio_source.h" +#include "third_party/blink/public/platform/web_media_constraints.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_dtmf_sender_handler.h" +#include "third_party/blink/public/platform/web_rtc_rtp_contributing_source.h" +#include "third_party/blink/public/platform/web_rtc_rtp_receiver.h" +#include "third_party/blink/public/platform/web_rtc_rtp_sender.h" +#include "third_party/blink/public/platform/web_rtc_rtp_transceiver.h" + +namespace content { + +// TODO(https://crbug.com/868868): Similar methods to this exist in many content +// unittests. Move to a separate file and reuse it in all of them. +blink::WebMediaStreamTrack CreateWebMediaStreamTrack(const std::string& id); + +class CONTENT_EXPORT FakeRTCRtpSender : public blink::WebRTCRtpSender { + public: + FakeRTCRtpSender(base::Optional<std::string> track_id, + std::vector<std::string> stream_ids); + FakeRTCRtpSender(const FakeRTCRtpSender&); + ~FakeRTCRtpSender() override; + FakeRTCRtpSender& operator=(const FakeRTCRtpSender&); + + std::unique_ptr<blink::WebRTCRtpSender> ShallowCopy() const override; + uintptr_t Id() const override; + blink::WebMediaStreamTrack Track() const override; + blink::WebVector<blink::WebString> StreamIds() const override; + void ReplaceTrack(blink::WebMediaStreamTrack with_track, + blink::WebRTCVoidRequest request) override; + std::unique_ptr<blink::WebRTCDTMFSenderHandler> GetDtmfSender() + const override; + std::unique_ptr<webrtc::RtpParameters> GetParameters() const override; + void SetParameters(blink::WebVector<webrtc::RtpEncodingParameters>, + webrtc::DegradationPreference, + blink::WebRTCVoidRequest) override; + void GetStats(std::unique_ptr<blink::WebRTCStatsReportCallback>) override; + + private: + base::Optional<std::string> track_id_; + std::vector<std::string> stream_ids_; +}; + +class CONTENT_EXPORT FakeRTCRtpReceiver : public blink::WebRTCRtpReceiver { + public: + FakeRTCRtpReceiver(const std::string& track_id, + std::vector<std::string> stream_ids); + FakeRTCRtpReceiver(const FakeRTCRtpReceiver&); + ~FakeRTCRtpReceiver() override; + FakeRTCRtpReceiver& operator=(const FakeRTCRtpReceiver&); + + std::unique_ptr<blink::WebRTCRtpReceiver> ShallowCopy() const override; + uintptr_t Id() const override; + const blink::WebMediaStreamTrack& Track() const override; + blink::WebVector<blink::WebString> StreamIds() const override; + blink::WebVector<std::unique_ptr<blink::WebRTCRtpContributingSource>> + GetSources() override; + void GetStats(std::unique_ptr<blink::WebRTCStatsReportCallback>) override; + + private: + blink::WebMediaStreamTrack track_; + std::vector<std::string> stream_ids_; +}; + +class CONTENT_EXPORT FakeRTCRtpTransceiver + : public blink::WebRTCRtpTransceiver { + public: + FakeRTCRtpTransceiver( + base::Optional<std::string> mid, + FakeRTCRtpSender sender, + FakeRTCRtpReceiver receiver, + bool stopped, + webrtc::RtpTransceiverDirection direction, + base::Optional<webrtc::RtpTransceiverDirection> current_direction); + ~FakeRTCRtpTransceiver() override; + + blink::WebRTCRtpTransceiverImplementationType ImplementationType() + const override; + uintptr_t Id() const override; + blink::WebString Mid() const override; + std::unique_ptr<blink::WebRTCRtpSender> Sender() const override; + std::unique_ptr<blink::WebRTCRtpReceiver> Receiver() const override; + bool Stopped() const override; + webrtc::RtpTransceiverDirection Direction() const override; + void SetDirection(webrtc::RtpTransceiverDirection direction) override; + base::Optional<webrtc::RtpTransceiverDirection> CurrentDirection() + const override; + base::Optional<webrtc::RtpTransceiverDirection> FiredDirection() + const override; + + private: + base::Optional<std::string> mid_; + FakeRTCRtpSender sender_; + FakeRTCRtpReceiver receiver_; + bool stopped_; + webrtc::RtpTransceiverDirection direction_; + base::Optional<webrtc::RtpTransceiverDirection> current_direction_; +}; + +} // namespace content + +#endif // CONTENT_RENDERER_MEDIA_WEBRTC_FAKE_RTC_RTP_TRANSCEIVER_H_ 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 eb85960b29c..0e810df0728 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 @@ -71,6 +71,7 @@ class MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate // Timestamp of the first received frame. base::TimeDelta start_timestamp_; + // WebRTC Chromium timestamp diff const base::TimeDelta time_diff_; }; @@ -117,16 +118,16 @@ void MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate::OnFrame( scoped_refptr<media::VideoFrame> video_frame; scoped_refptr<webrtc::VideoFrameBuffer> buffer( incoming_frame.video_frame_buffer()); + const gfx::Size size(buffer->width(), buffer->height()); - if (buffer->type() == webrtc::VideoFrameBuffer::Type::kNative) { - video_frame = static_cast<WebRtcVideoFrameAdapter*>(buffer.get()) - ->getMediaVideoFrame(); - video_frame->set_timestamp(elapsed_timestamp); - } else { - const gfx::Size size(buffer->width(), buffer->height()); - const bool has_alpha = - buffer->type() == webrtc::VideoFrameBuffer::Type::kI420A; - if (has_alpha) { + switch (buffer->type()) { + case webrtc::VideoFrameBuffer::Type::kNative: { + video_frame = static_cast<WebRtcVideoFrameAdapter*>(buffer.get()) + ->getMediaVideoFrame(); + video_frame->set_timestamp(elapsed_timestamp); + break; + } + case webrtc::VideoFrameBuffer::Type::kI420A: { const webrtc::I420ABufferInterface* yuva_buffer = buffer->GetI420A(); video_frame = media::VideoFrame::WrapExternalYuvaData( media::PIXEL_FORMAT_I420A, size, gfx::Rect(size), size, @@ -136,36 +137,64 @@ void MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate::OnFrame( const_cast<uint8_t*>(yuva_buffer->DataU()), const_cast<uint8_t*>(yuva_buffer->DataV()), const_cast<uint8_t*>(yuva_buffer->DataA()), elapsed_timestamp); - } else { - scoped_refptr<webrtc::PlanarYuvBuffer> yuv_buffer; - media::VideoPixelFormat pixel_format; - if (buffer->type() == webrtc::VideoFrameBuffer::Type::kI444) { - yuv_buffer = buffer->GetI444(); - pixel_format = media::PIXEL_FORMAT_I444; - } else { - yuv_buffer = buffer->ToI420(); - pixel_format = media::PIXEL_FORMAT_I420; - } - // Make a shallow copy. Both |frame| and |video_frame| will share a single - // reference counted frame buffer. Const cast and hope no one will - // overwrite the data. + break; + } + case webrtc::VideoFrameBuffer::Type::kI420: { + rtc::scoped_refptr<webrtc::I420BufferInterface> yuv_buffer = + buffer->ToI420(); video_frame = media::VideoFrame::WrapExternalYuvData( - pixel_format, size, gfx::Rect(size), size, yuv_buffer->StrideY(), - yuv_buffer->StrideU(), yuv_buffer->StrideV(), + media::PIXEL_FORMAT_I420, size, gfx::Rect(size), size, + yuv_buffer->StrideY(), yuv_buffer->StrideU(), yuv_buffer->StrideV(), const_cast<uint8_t*>(yuv_buffer->DataY()), const_cast<uint8_t*>(yuv_buffer->DataU()), const_cast<uint8_t*>(yuv_buffer->DataV()), elapsed_timestamp); + break; } - if (!video_frame) - return; - // The bind ensures that we keep a reference to the underlying buffer. - video_frame->AddDestructionObserver(base::BindOnce(&DoNothing, buffer)); + case webrtc::VideoFrameBuffer::Type::kI444: { + webrtc::I444BufferInterface* yuv_buffer = buffer->GetI444(); + video_frame = media::VideoFrame::WrapExternalYuvData( + media::PIXEL_FORMAT_I444, size, gfx::Rect(size), size, + yuv_buffer->StrideY(), yuv_buffer->StrideU(), yuv_buffer->StrideV(), + const_cast<uint8_t*>(yuv_buffer->DataY()), + const_cast<uint8_t*>(yuv_buffer->DataU()), + const_cast<uint8_t*>(yuv_buffer->DataV()), elapsed_timestamp); + break; + } + case webrtc::VideoFrameBuffer::Type::kI010: { + webrtc::I010BufferInterface* yuv_buffer = buffer->GetI010(); + // WebRTC defines I010 data as uint16 whereas Chromium uses uint8 for all + // video formats, so conversion and cast is needed. + video_frame = media::VideoFrame::WrapExternalYuvData( + media::PIXEL_FORMAT_YUV420P10, size, gfx::Rect(size), size, + yuv_buffer->StrideY() * 2, yuv_buffer->StrideU() * 2, + yuv_buffer->StrideV() * 2, + const_cast<uint8_t*>( + reinterpret_cast<const uint8_t*>(yuv_buffer->DataY())), + const_cast<uint8_t*>( + reinterpret_cast<const uint8_t*>(yuv_buffer->DataU())), + const_cast<uint8_t*>( + reinterpret_cast<const uint8_t*>(yuv_buffer->DataV())), + elapsed_timestamp); + break; + } + default: + NOTREACHED(); } + + if (!video_frame) + return; + + // The bind ensures that we keep a reference to the underlying buffer. + if (buffer->type() != webrtc::VideoFrameBuffer::Type::kNative) + video_frame->AddDestructionObserver(base::BindOnce(&DoNothing, buffer)); + + // Rotation may be explicitly set sometimes. if (incoming_frame.rotation() != webrtc::kVideoRotation_0) { video_frame->metadata()->SetRotation( media::VideoFrameMetadata::ROTATION, WebRTCToMediaVideoRotation(incoming_frame.rotation())); } + // Run render smoothness algorithm only when we don't have to render // immediately. if (!render_immediately) { @@ -235,7 +264,7 @@ void MediaStreamRemoteVideoSource::StopSourceImpl() { } rtc::VideoSinkInterface<webrtc::VideoFrame>* -MediaStreamRemoteVideoSource::SinkInterfaceForTest() { +MediaStreamRemoteVideoSource::SinkInterfaceForTesting() { return delegate_.get(); } diff --git a/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.h b/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.h index 494b11b8f45..f07b411c77c 100644 --- a/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.h +++ b/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.h @@ -24,7 +24,7 @@ class TrackObserver; // to make sure there is no difference between a video track where the source is // a local source and a video track where the source is a remote video track. class CONTENT_EXPORT MediaStreamRemoteVideoSource - : public MediaStreamVideoSource { + : public MediaStreamVideoSource { public: explicit MediaStreamRemoteVideoSource( std::unique_ptr<TrackObserver> observer); @@ -44,7 +44,7 @@ class CONTENT_EXPORT MediaStreamRemoteVideoSource // Used by tests to test that a frame can be received and that the // MediaStreamRemoteVideoSource behaves as expected. - rtc::VideoSinkInterface<webrtc::VideoFrame>* SinkInterfaceForTest(); + rtc::VideoSinkInterface<webrtc::VideoFrame>* SinkInterfaceForTesting(); private: void OnChanged(webrtc::MediaStreamTrackInterface::TrackState state); 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 34db57bbd4b..e721651a012 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 @@ -36,7 +36,7 @@ class MediaStreamRemoteVideoSourceUnderTest explicit MediaStreamRemoteVideoSourceUnderTest( std::unique_ptr<TrackObserver> observer) : MediaStreamRemoteVideoSource(std::move(observer)) {} - using MediaStreamRemoteVideoSource::SinkInterfaceForTest; + using MediaStreamRemoteVideoSource::SinkInterfaceForTesting; }; class MediaStreamRemoteVideoSourceTest @@ -171,7 +171,7 @@ TEST_F(MediaStreamRemoteVideoSourceTest, StartTrack) { webrtc::I420Buffer::SetBlack(buffer); - source()->SinkInterfaceForTest()->OnFrame( + source()->SinkInterfaceForTesting()->OnFrame( webrtc::VideoFrame(buffer, webrtc::kVideoRotation_0, 1000)); run_loop.Run(); diff --git a/chromium/content/renderer/media/webrtc/media_stream_track_metrics.cc b/chromium/content/renderer/media/webrtc/media_stream_track_metrics.cc index e84c5e83b71..30ea304614b 100644 --- a/chromium/content/renderer/media/webrtc/media_stream_track_metrics.cc +++ b/chromium/content/renderer/media/webrtc/media_stream_track_metrics.cc @@ -5,7 +5,6 @@ #include "content/renderer/media/webrtc/media_stream_track_metrics.h" #include <inttypes.h> -#include <set> #include <string> #include "base/md5.h" @@ -14,133 +13,44 @@ #include "content/public/common/service_names.mojom.h" #include "content/renderer/render_thread_impl.h" #include "services/service_manager/public/cpp/connector.h" -#include "third_party/webrtc/api/mediastreaminterface.h" - -using webrtc::AudioTrackVector; -using webrtc::MediaStreamInterface; -using webrtc::MediaStreamTrackInterface; -using webrtc::PeerConnectionInterface; -using webrtc::VideoTrackVector; namespace content { -namespace { -typedef std::set<std::string> IdSet; - -template <class T> -IdSet GetTrackIds(const std::vector<rtc::scoped_refptr<T>>& tracks) { - IdSet track_ids; - for (const auto& track : tracks) - track_ids.insert(track->id()); - return track_ids; -} - -// TODO(tommi): Consolidate this and TrackObserver since these implementations -// are fundamentally achieving the same thing (aside from specific logic inside -// the OnChanged callbacks). -class MediaStreamObserver - : public base::RefCountedThreadSafe<MediaStreamObserver>, - public webrtc::ObserverInterface { - public: - typedef base::Callback< - void(const IdSet& audio_track_ids, const IdSet& video_track_ids)> - OnChangedCallback; - - MediaStreamObserver( - const OnChangedCallback& callback, - const scoped_refptr<base::SingleThreadTaskRunner>& main_thread, - webrtc::MediaStreamInterface* stream) - : main_thread_(main_thread), stream_(stream), callback_(callback) { - signaling_thread_.DetachFromThread(); - stream_->RegisterObserver(this); - } - - const scoped_refptr<webrtc::MediaStreamInterface>& stream() const { - DCHECK(main_thread_->BelongsToCurrentThread()); - return stream_; - } - - void Unregister() { - DCHECK(main_thread_->BelongsToCurrentThread()); - callback_.Reset(); - stream_->UnregisterObserver(this); - stream_ = nullptr; - } - - private: - friend class base::RefCountedThreadSafe<MediaStreamObserver>; - ~MediaStreamObserver() override { - DCHECK(!stream_.get()) << "must have been unregistered before deleting"; - } - - // webrtc::ObserverInterface implementation. - void OnChanged() override { - DCHECK(signaling_thread_.CalledOnValidThread()); - main_thread_->PostTask( - FROM_HERE, base::BindOnce(&MediaStreamObserver::OnChangedOnMainThread, - this, GetTrackIds(stream_->GetAudioTracks()), - GetTrackIds(stream_->GetVideoTracks()))); - } - - void OnChangedOnMainThread(const IdSet& audio_track_ids, - const IdSet& video_track_ids) { - DCHECK(main_thread_->BelongsToCurrentThread()); - if (!callback_.is_null()) - callback_.Run(audio_track_ids, video_track_ids); - } - - const scoped_refptr<base::SingleThreadTaskRunner> main_thread_; - scoped_refptr<webrtc::MediaStreamInterface> stream_; - OnChangedCallback callback_; // Only touched on the main thread. - base::ThreadChecker signaling_thread_; -}; - -} // namespace class MediaStreamTrackMetricsObserver { public: - MediaStreamTrackMetricsObserver( - MediaStreamTrackMetrics::StreamType stream_type, - MediaStreamInterface* stream, - MediaStreamTrackMetrics* owner); + MediaStreamTrackMetricsObserver(MediaStreamTrackMetrics::Direction direction, + MediaStreamTrackMetrics::Kind kind, + std::string track_id, + MediaStreamTrackMetrics* owner); ~MediaStreamTrackMetricsObserver(); - // Sends begin/end messages for all tracks currently tracked. - void SendLifetimeMessages(MediaStreamTrackMetrics::LifetimeEvent event); + // Sends begin/end messages for the track if not already reported. + void SendLifetimeMessageForTrack( + MediaStreamTrackMetrics::LifetimeEvent event); - MediaStreamInterface* stream() { + MediaStreamTrackMetrics::Direction direction() { DCHECK(thread_checker_.CalledOnValidThread()); - return observer_->stream().get(); + return direction_; } - MediaStreamTrackMetrics::StreamType stream_type() { + MediaStreamTrackMetrics::Kind kind() { DCHECK(thread_checker_.CalledOnValidThread()); - return stream_type_; + return kind_; } - private: - void OnChanged(const IdSet& audio_track_ids, const IdSet& video_track_ids); - - void ReportAddedAndRemovedTracks( - const IdSet& new_ids, - const IdSet& old_ids, - MediaStreamTrackMetrics::TrackType track_type); - - // Sends a lifetime message for the given tracks. OK to call with an - // empty |ids|, in which case the method has no side effects. - void ReportTracks(const IdSet& ids, - MediaStreamTrackMetrics::TrackType track_type, - MediaStreamTrackMetrics::LifetimeEvent event); + std::string track_id() const { + DCHECK(thread_checker_.CalledOnValidThread()); + return track_id_; + } + private: // False until start/end of lifetime messages have been sent. bool has_reported_start_; bool has_reported_end_; - // IDs of audio and video tracks in the stream being observed. - IdSet audio_track_ids_; - IdSet video_track_ids_; - - MediaStreamTrackMetrics::StreamType stream_type_; - scoped_refptr<MediaStreamObserver> observer_; + MediaStreamTrackMetrics::Direction direction_; + MediaStreamTrackMetrics::Kind kind_; + std::string track_id_; // Non-owning. MediaStreamTrackMetrics* owner_; @@ -151,47 +61,46 @@ namespace { // Used with std::find_if. struct ObserverFinder { - ObserverFinder(MediaStreamTrackMetrics::StreamType stream_type, - MediaStreamInterface* stream) - : stream_type(stream_type), stream_(stream) {} + ObserverFinder(MediaStreamTrackMetrics::Direction direction, + MediaStreamTrackMetrics::Kind kind, + const std::string& track_id) + : direction_(direction), kind_(kind), track_id_(track_id) {} bool operator()( const std::unique_ptr<MediaStreamTrackMetricsObserver>& observer) { - return stream_ == observer->stream() && - stream_type == observer->stream_type(); + return direction_ == observer->direction() && kind_ == observer->kind() && + track_id_ == observer->track_id(); } - MediaStreamTrackMetrics::StreamType stream_type; - MediaStreamInterface* stream_; + MediaStreamTrackMetrics::Direction direction_; + MediaStreamTrackMetrics::Kind kind_; + std::string track_id_; }; } // namespace MediaStreamTrackMetricsObserver::MediaStreamTrackMetricsObserver( - MediaStreamTrackMetrics::StreamType stream_type, - MediaStreamInterface* stream, + MediaStreamTrackMetrics::Direction direction, + MediaStreamTrackMetrics::Kind kind, + std::string track_id, MediaStreamTrackMetrics* owner) : has_reported_start_(false), has_reported_end_(false), - audio_track_ids_(GetTrackIds(stream->GetAudioTracks())), - video_track_ids_(GetTrackIds(stream->GetVideoTracks())), - stream_type_(stream_type), - observer_(new MediaStreamObserver( - base::Bind(&MediaStreamTrackMetricsObserver::OnChanged, - base::Unretained(this)), - base::ThreadTaskRunnerHandle::Get(), - stream)), + direction_(direction), + kind_(kind), + track_id_(std::move(track_id)), owner_(owner) { + DCHECK(owner); } MediaStreamTrackMetricsObserver::~MediaStreamTrackMetricsObserver() { DCHECK(thread_checker_.CalledOnValidThread()); - observer_->Unregister(); - SendLifetimeMessages(MediaStreamTrackMetrics::DISCONNECTED); + SendLifetimeMessageForTrack( + MediaStreamTrackMetrics::LifetimeEvent::kDisconnected); } -void MediaStreamTrackMetricsObserver::SendLifetimeMessages( +void MediaStreamTrackMetricsObserver::SendLifetimeMessageForTrack( MediaStreamTrackMetrics::LifetimeEvent event) { DCHECK(thread_checker_.CalledOnValidThread()); - if (event == MediaStreamTrackMetrics::CONNECTED) { + if (event == MediaStreamTrackMetrics::LifetimeEvent::kConnected) { // Both ICE CONNECTED and COMPLETED can trigger the first // start-of-life event, so we only report the first. if (has_reported_start_) @@ -199,7 +108,7 @@ void MediaStreamTrackMetricsObserver::SendLifetimeMessages( DCHECK(!has_reported_start_ && !has_reported_end_); has_reported_start_ = true; } else { - DCHECK(event == MediaStreamTrackMetrics::DISCONNECTED); + DCHECK(event == MediaStreamTrackMetrics::LifetimeEvent::kDisconnected); // We only report the first end-of-life event, since there are // several cases where end-of-life can be reached. We also don't @@ -209,10 +118,9 @@ void MediaStreamTrackMetricsObserver::SendLifetimeMessages( has_reported_end_ = true; } - ReportTracks(audio_track_ids_, MediaStreamTrackMetrics::AUDIO_TRACK, event); - ReportTracks(video_track_ids_, MediaStreamTrackMetrics::VIDEO_TRACK, event); + owner_->SendLifetimeMessage(track_id_, kind_, event, direction_); - if (event == MediaStreamTrackMetrics::DISCONNECTED) { + if (event == MediaStreamTrackMetrics::LifetimeEvent::kDisconnected) { // After disconnection, we can get reconnected, so we need to // forget that we've sent lifetime events, while retaining all // other state. @@ -222,76 +130,33 @@ void MediaStreamTrackMetricsObserver::SendLifetimeMessages( } } -void MediaStreamTrackMetricsObserver::OnChanged( - const IdSet& audio_track_ids, const IdSet& video_track_ids) { - DCHECK(thread_checker_.CalledOnValidThread()); - - // We only report changes after our initial report, and never after - // our last report. - if (has_reported_start_ && !has_reported_end_) { - ReportAddedAndRemovedTracks(audio_track_ids, - audio_track_ids_, - MediaStreamTrackMetrics::AUDIO_TRACK); - ReportAddedAndRemovedTracks(video_track_ids, - video_track_ids_, - MediaStreamTrackMetrics::VIDEO_TRACK); - } - - // We always update our sets of tracks. - audio_track_ids_ = audio_track_ids; - video_track_ids_ = video_track_ids; -} - -void MediaStreamTrackMetricsObserver::ReportAddedAndRemovedTracks( - const IdSet& new_ids, - const IdSet& old_ids, - MediaStreamTrackMetrics::TrackType track_type) { - DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(has_reported_start_ && !has_reported_end_); - - IdSet added_tracks = base::STLSetDifference<IdSet>(new_ids, old_ids); - IdSet removed_tracks = base::STLSetDifference<IdSet>(old_ids, new_ids); - - ReportTracks(added_tracks, track_type, MediaStreamTrackMetrics::CONNECTED); - ReportTracks( - removed_tracks, track_type, MediaStreamTrackMetrics::DISCONNECTED); -} - -void MediaStreamTrackMetricsObserver::ReportTracks( - const IdSet& ids, - MediaStreamTrackMetrics::TrackType track_type, - MediaStreamTrackMetrics::LifetimeEvent event) { - DCHECK(thread_checker_.CalledOnValidThread()); - for (IdSet::const_iterator it = ids.begin(); it != ids.end(); ++it) { - owner_->SendLifetimeMessage(*it, track_type, event, stream_type_); - } -} - MediaStreamTrackMetrics::MediaStreamTrackMetrics() : ice_state_(webrtc::PeerConnectionInterface::kIceConnectionNew) {} MediaStreamTrackMetrics::~MediaStreamTrackMetrics() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); for (const auto& observer : observers_) { - observer->SendLifetimeMessages(DISCONNECTED); + observer->SendLifetimeMessageForTrack(LifetimeEvent::kDisconnected); } } -void MediaStreamTrackMetrics::AddStream(StreamType type, - MediaStreamInterface* stream) { +void MediaStreamTrackMetrics::AddTrack(Direction direction, + Kind kind, + const std::string& track_id) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - observers_.push_back( - std::make_unique<MediaStreamTrackMetricsObserver>(type, stream, this)); + observers_.push_back(std::make_unique<MediaStreamTrackMetricsObserver>( + direction, kind, std::move(track_id), this)); SendLifeTimeMessageDependingOnIceState(observers_.back().get()); } -void MediaStreamTrackMetrics::RemoveStream(StreamType type, - MediaStreamInterface* stream) { +void MediaStreamTrackMetrics::RemoveTrack(Direction direction, + Kind kind, + const std::string& track_id) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); auto it = std::find_if(observers_.begin(), observers_.end(), - ObserverFinder(type, stream)); + ObserverFinder(direction, kind, track_id)); if (it == observers_.end()) { - // Since external apps could call removeStream with a stream they + // Since external apps could call removeTrack() with a stream they // never added, this can happen without it being an error. return; } @@ -300,40 +165,41 @@ void MediaStreamTrackMetrics::RemoveStream(StreamType type, } void MediaStreamTrackMetrics::IceConnectionChange( - PeerConnectionInterface::IceConnectionState new_state) { + webrtc::PeerConnectionInterface::IceConnectionState new_state) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); ice_state_ = new_state; for (const auto& observer : observers_) { SendLifeTimeMessageDependingOnIceState(observer.get()); } } + void MediaStreamTrackMetrics::SendLifeTimeMessageDependingOnIceState( MediaStreamTrackMetricsObserver* observer) { // There is a state transition diagram for these states at // http://dev.w3.org/2011/webrtc/editor/webrtc.html#idl-def-RTCIceConnectionState switch (ice_state_) { - case PeerConnectionInterface::kIceConnectionConnected: - case PeerConnectionInterface::kIceConnectionCompleted: - observer->SendLifetimeMessages(CONNECTED); + case webrtc::PeerConnectionInterface::kIceConnectionConnected: + case webrtc::PeerConnectionInterface::kIceConnectionCompleted: + observer->SendLifetimeMessageForTrack(LifetimeEvent::kConnected); break; - case PeerConnectionInterface::kIceConnectionFailed: - // We don't really need to handle FAILED (it is only supposed - // to be preceded by CHECKING so we wouldn't yet have sent a - // lifetime message) but we might as well use belt and - // suspenders and handle it the same as the other "end call" - // states. It will be ignored anyway if the call is not - // already connected. - case PeerConnectionInterface::kIceConnectionNew: - // It's a bit weird to count NEW as an end-lifetime event, but - // it's possible to transition directly from a connected state - // (CONNECTED or COMPLETED) to NEW, which can then be followed - // by a new connection. The observer will ignore the end - // lifetime event if it was not preceded by a begin-lifetime - // event. - case PeerConnectionInterface::kIceConnectionDisconnected: - case PeerConnectionInterface::kIceConnectionClosed: - observer->SendLifetimeMessages(DISCONNECTED); + case webrtc::PeerConnectionInterface::kIceConnectionFailed: + // We don't really need to handle FAILED (it is only supposed + // to be preceded by CHECKING so we wouldn't yet have sent a + // lifetime message) but we might as well use belt and + // suspenders and handle it the same as the other "end call" + // states. It will be ignored anyway if the call is not + // already connected. + case webrtc::PeerConnectionInterface::kIceConnectionNew: + // It's a bit weird to count NEW as an end-lifetime event, but + // it's possible to transition directly from a connected state + // (CONNECTED or COMPLETED) to NEW, which can then be followed + // by a new connection. The observer will ignore the end + // lifetime event if it was not preceded by a begin-lifetime + // event. + case webrtc::PeerConnectionInterface::kIceConnectionDisconnected: + case webrtc::PeerConnectionInterface::kIceConnectionClosed: + observer->SendLifetimeMessageForTrack(LifetimeEvent::kDisconnected); break; default: @@ -345,28 +211,28 @@ void MediaStreamTrackMetrics::SendLifeTimeMessageDependingOnIceState( } void MediaStreamTrackMetrics::SendLifetimeMessage(const std::string& track_id, - TrackType track_type, + Kind kind, LifetimeEvent event, - StreamType stream_type) { + Direction direction) { RenderThreadImpl* render_thread = RenderThreadImpl::current(); // |render_thread| can be NULL in certain cases when running as part // |of a unit test. if (render_thread) { - if (event == CONNECTED) { + if (event == LifetimeEvent::kConnected) { GetMediaStreamTrackMetricsHost()->AddTrack( - MakeUniqueId(track_id, stream_type), track_type == AUDIO_TRACK, - stream_type == RECEIVED_STREAM); + MakeUniqueId(track_id, direction), kind == Kind::kAudio, + direction == Direction::kReceive); } else { - DCHECK_EQ(DISCONNECTED, event); + DCHECK_EQ(LifetimeEvent::kDisconnected, event); GetMediaStreamTrackMetricsHost()->RemoveTrack( - MakeUniqueId(track_id, stream_type)); + MakeUniqueId(track_id, direction)); } } } uint64_t MediaStreamTrackMetrics::MakeUniqueIdImpl(uint64_t pc_id, const std::string& track_id, - StreamType stream_type) { + Direction direction) { // We use a hash over the |track| pointer and the PeerConnection ID, // plus a boolean flag indicating whether the track is remote (since // you might conceivably have a remote track added back as a sent @@ -376,10 +242,8 @@ uint64_t MediaStreamTrackMetrics::MakeUniqueIdImpl(uint64_t pc_id, // no longer be considered), just one with virtually zero chance of // collisions when faced with non-malicious data. std::string unique_id_string = - base::StringPrintf("%" PRIu64 " %s %d", - pc_id, - track_id.c_str(), - stream_type == RECEIVED_STREAM ? 1 : 0); + base::StringPrintf("%" PRIu64 " %s %d", pc_id, track_id.c_str(), + direction == Direction::kReceive ? 1 : 0); base::MD5Context ctx; base::MD5Init(&ctx); @@ -392,10 +256,10 @@ uint64_t MediaStreamTrackMetrics::MakeUniqueIdImpl(uint64_t pc_id, } uint64_t MediaStreamTrackMetrics::MakeUniqueId(const std::string& track_id, - StreamType stream_type) { + Direction direction) { return MakeUniqueIdImpl( reinterpret_cast<uint64_t>(reinterpret_cast<void*>(this)), track_id, - stream_type); + direction); } mojom::MediaStreamTrackMetricsHostPtr& diff --git a/chromium/content/renderer/media/webrtc/media_stream_track_metrics.h b/chromium/content/renderer/media/webrtc/media_stream_track_metrics.h index 779318660ab..addd76a632b 100644 --- a/chromium/content/renderer/media/webrtc/media_stream_track_metrics.h +++ b/chromium/content/renderer/media/webrtc/media_stream_track_metrics.h @@ -15,10 +15,6 @@ #include "content/common/media/media_stream.mojom.h" #include "third_party/webrtc/api/peerconnectioninterface.h" -namespace webrtc { -class MediaStreamInterface; -} - namespace content { class MediaStreamTrackMetricsObserver; @@ -36,19 +32,16 @@ class CONTENT_EXPORT MediaStreamTrackMetrics { explicit MediaStreamTrackMetrics(); ~MediaStreamTrackMetrics(); - enum StreamType { SENT_STREAM, RECEIVED_STREAM }; - - enum TrackType { AUDIO_TRACK, VIDEO_TRACK }; - - enum LifetimeEvent { CONNECTED, DISCONNECTED }; + enum class Direction { kSend, kReceive }; + enum class Kind { kAudio, kVideo }; + enum class LifetimeEvent { kConnected, kDisconnected }; - // Starts tracking lifetimes of all the tracks in |stream| and any - // tracks added or removed to/from the stream until |RemoveStream| - // is called or this object's lifetime ends. - void AddStream(StreamType type, webrtc::MediaStreamInterface* stream); + // Starts tracking the lifetime of the track until |RemoveTrack| is called + // or this object's lifetime ends. + void AddTrack(Direction direction, Kind kind, const std::string& track_id); - // Stops tracking lifetimes of tracks in |stream|. - void RemoveStream(StreamType type, webrtc::MediaStreamInterface* stream); + // Stops tracking the lifetime of the track. + void RemoveTrack(Direction direction, Kind kind, const std::string& track_id); // Called to indicate changes in the ICE connection state for the // PeerConnection this object is associated with. Used to generate @@ -71,9 +64,9 @@ class CONTENT_EXPORT MediaStreamTrackMetrics { // PeerConnection), false for local streams (sent over a // PeerConnection). virtual void SendLifetimeMessage(const std::string& track_id, - TrackType track_type, + Kind kind, LifetimeEvent lifetime_event, - StreamType stream_type); + Direction direction); protected: // Calls SendLifetimeMessage for |observer| depending on |ice_state_|. @@ -86,12 +79,12 @@ class CONTENT_EXPORT MediaStreamTrackMetrics { // is a one-to-one relationship). uint64_t MakeUniqueIdImpl(uint64_t pc_id, const std::string& track, - StreamType stream_type); + Direction direction); private: // Make a unique ID for the given track, that is valid while the // track object and the PeerConnection it is attached to both exist. - uint64_t MakeUniqueId(const std::string& track, StreamType stream_type); + uint64_t MakeUniqueId(const std::string& track_id, Direction direction); mojom::MediaStreamTrackMetricsHostPtr& GetMediaStreamTrackMetricsHost(); diff --git a/chromium/content/renderer/media/webrtc/media_stream_track_metrics_unittest.cc b/chromium/content/renderer/media/webrtc/media_stream_track_metrics_unittest.cc index d8819aa62a5..4fb4ff31bc0 100644 --- a/chromium/content/renderer/media/webrtc/media_stream_track_metrics_unittest.cc +++ b/chromium/content/renderer/media/webrtc/media_stream_track_metrics_unittest.cc @@ -78,8 +78,7 @@ class MockMediaStreamTrackMetrics : public MediaStreamTrackMetrics { virtual ~MockMediaStreamTrackMetrics() {} MOCK_METHOD4(SendLifetimeMessage, - void(const std::string&, TrackType, LifetimeEvent, StreamType)); - + void(const std::string&, Kind, LifetimeEvent, Direction)); using MediaStreamTrackMetrics::MakeUniqueIdImpl; }; @@ -170,88 +169,82 @@ TEST_F(MediaStreamTrackMetricsTest, MakeUniqueId) { // Lower 32 bits the same, upper 32 differ. EXPECT_NE( - metrics_->MakeUniqueIdImpl( - 0x1000000000000001, "x", MediaStreamTrackMetrics::RECEIVED_STREAM), - metrics_->MakeUniqueIdImpl( - 0x2000000000000001, "x", MediaStreamTrackMetrics::RECEIVED_STREAM)); + metrics_->MakeUniqueIdImpl(0x1000000000000001, "x", + MediaStreamTrackMetrics::Direction::kReceive), + metrics_->MakeUniqueIdImpl(0x2000000000000001, "x", + MediaStreamTrackMetrics::Direction::kReceive)); // Track ID differs. EXPECT_NE(metrics_->MakeUniqueIdImpl( - 42, "x", MediaStreamTrackMetrics::RECEIVED_STREAM), + 42, "x", MediaStreamTrackMetrics::Direction::kReceive), metrics_->MakeUniqueIdImpl( - 42, "y", MediaStreamTrackMetrics::RECEIVED_STREAM)); + 42, "y", MediaStreamTrackMetrics::Direction::kReceive)); // Remove vs. local track differs. EXPECT_NE(metrics_->MakeUniqueIdImpl( - 42, "x", MediaStreamTrackMetrics::RECEIVED_STREAM), + 42, "x", MediaStreamTrackMetrics::Direction::kReceive), metrics_->MakeUniqueIdImpl( - 42, "x", MediaStreamTrackMetrics::SENT_STREAM)); + 42, "x", MediaStreamTrackMetrics::Direction::kSend)); } TEST_F(MediaStreamTrackMetricsTest, BasicRemoteStreams) { - scoped_refptr<MockAudioTrackInterface> audio(MakeAudioTrack("audio")); - scoped_refptr<MockVideoTrackInterface> video(MakeVideoTrack("video")); - stream_->AddTrack(audio.get()); - stream_->AddTrack(video.get()); - metrics_->AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM, stream_.get()); - - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::RECEIVED_STREAM)); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("video", - MediaStreamTrackMetrics::VIDEO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::RECEIVED_STREAM)); + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kReceive, + MediaStreamTrackMetrics::Kind::kAudio, "audio"); + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kReceive, + MediaStreamTrackMetrics::Kind::kVideo, "video"); + + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kReceive)); + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "video", MediaStreamTrackMetrics::Kind::kVideo, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kReceive)); metrics_->IceConnectionChange( PeerConnectionInterface::kIceConnectionConnected); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::RECEIVED_STREAM)); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("video", - MediaStreamTrackMetrics::VIDEO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::RECEIVED_STREAM)); + EXPECT_CALL( + *metrics_, + SendLifetimeMessage("audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kDisconnected, + MediaStreamTrackMetrics::Direction::kReceive)); + EXPECT_CALL( + *metrics_, + SendLifetimeMessage("video", MediaStreamTrackMetrics::Kind::kVideo, + MediaStreamTrackMetrics::LifetimeEvent::kDisconnected, + MediaStreamTrackMetrics::Direction::kReceive)); metrics_->IceConnectionChange( PeerConnectionInterface::kIceConnectionDisconnected); } TEST_F(MediaStreamTrackMetricsTest, BasicLocalStreams) { - scoped_refptr<MockAudioTrackInterface> audio(MakeAudioTrack("audio")); - scoped_refptr<MockVideoTrackInterface> video(MakeVideoTrack("video")); - stream_->AddTrack(audio.get()); - stream_->AddTrack(video.get()); - metrics_->AddStream(MediaStreamTrackMetrics::SENT_STREAM, stream_.get()); - - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("video", - MediaStreamTrackMetrics::VIDEO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kAudio, "audio"); + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kVideo, "video"); + + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kSend)); + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "video", MediaStreamTrackMetrics::Kind::kVideo, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kSend)); metrics_->IceConnectionChange( PeerConnectionInterface::kIceConnectionConnected); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("video", - MediaStreamTrackMetrics::VIDEO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); + EXPECT_CALL( + *metrics_, + SendLifetimeMessage("audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kDisconnected, + MediaStreamTrackMetrics::Direction::kSend)); + EXPECT_CALL( + *metrics_, + SendLifetimeMessage("video", MediaStreamTrackMetrics::Kind::kVideo, + MediaStreamTrackMetrics::LifetimeEvent::kDisconnected, + MediaStreamTrackMetrics::Direction::kSend)); metrics_->IceConnectionChange(PeerConnectionInterface::kIceConnectionFailed); } @@ -259,341 +252,226 @@ TEST_F(MediaStreamTrackMetricsTest, LocalStreamAddedAferIceConnect) { metrics_->IceConnectionChange( PeerConnectionInterface::kIceConnectionConnected); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("video", - MediaStreamTrackMetrics::VIDEO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - - scoped_refptr<MockAudioTrackInterface> audio(MakeAudioTrack("audio")); - scoped_refptr<MockVideoTrackInterface> video(MakeVideoTrack("video")); - stream_->AddTrack(audio.get()); - stream_->AddTrack(video.get()); - metrics_->AddStream(MediaStreamTrackMetrics::SENT_STREAM, stream_.get()); + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kSend)); + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "video", MediaStreamTrackMetrics::Kind::kVideo, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kSend)); + + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kAudio, "audio"); + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kVideo, "video"); } TEST_F(MediaStreamTrackMetricsTest, RemoteStreamAddedAferIceConnect) { metrics_->IceConnectionChange( PeerConnectionInterface::kIceConnectionConnected); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::RECEIVED_STREAM)); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("video", - MediaStreamTrackMetrics::VIDEO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::RECEIVED_STREAM)); - - scoped_refptr<MockAudioTrackInterface> audio(MakeAudioTrack("audio")); - scoped_refptr<MockVideoTrackInterface> video(MakeVideoTrack("video")); - stream_->AddTrack(audio.get()); - stream_->AddTrack(video.get()); - metrics_->AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM, stream_.get()); -} - -TEST_F(MediaStreamTrackMetricsTest, RemoteStreamTrackAdded) { - scoped_refptr<MockAudioTrackInterface> initial(MakeAudioTrack("initial")); - scoped_refptr<MockAudioTrackInterface> added(MakeAudioTrack("added")); - stream_->AddTrack(initial.get()); - metrics_->AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM, stream_.get()); - - EXPECT_CALL(*metrics_, - SendLifetimeMessage("initial", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::RECEIVED_STREAM)); - metrics_->IceConnectionChange( - PeerConnectionInterface::kIceConnectionConnected); - - EXPECT_CALL(*metrics_, - SendLifetimeMessage("added", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::RECEIVED_STREAM)); - AddAudioTrack(added.get()); - - EXPECT_CALL(*metrics_, - SendLifetimeMessage("initial", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::RECEIVED_STREAM)); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("added", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::RECEIVED_STREAM)); - metrics_->IceConnectionChange(PeerConnectionInterface::kIceConnectionFailed); + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kReceive)); + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "video", MediaStreamTrackMetrics::Kind::kVideo, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kReceive)); + + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kReceive, + MediaStreamTrackMetrics::Kind::kAudio, "audio"); + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kReceive, + MediaStreamTrackMetrics::Kind::kVideo, "video"); } TEST_F(MediaStreamTrackMetricsTest, LocalStreamTrackRemoved) { - scoped_refptr<MockAudioTrackInterface> first(MakeAudioTrack("first")); - scoped_refptr<MockAudioTrackInterface> second(MakeAudioTrack("second")); - stream_->AddTrack(first.get()); - stream_->AddTrack(second.get()); - metrics_->AddStream(MediaStreamTrackMetrics::SENT_STREAM, stream_.get()); - - EXPECT_CALL(*metrics_, - SendLifetimeMessage("first", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("second", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kAudio, "first"); + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kAudio, "second"); + + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "first", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kSend)); + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "second", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kSend)); metrics_->IceConnectionChange( PeerConnectionInterface::kIceConnectionConnected); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("first", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - stream_->RemoveTrack(first.get()); - - EXPECT_CALL(*metrics_, - SendLifetimeMessage("second", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); + EXPECT_CALL( + *metrics_, + SendLifetimeMessage("first", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kDisconnected, + MediaStreamTrackMetrics::Direction::kSend)); + metrics_->RemoveTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kAudio, "first"); + + EXPECT_CALL( + *metrics_, + SendLifetimeMessage("second", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kDisconnected, + MediaStreamTrackMetrics::Direction::kSend)); metrics_->IceConnectionChange(PeerConnectionInterface::kIceConnectionFailed); } -TEST_F(MediaStreamTrackMetricsTest, LocalStreamModificationsBeforeAndAfter) { - scoped_refptr<MockAudioTrackInterface> first(MakeAudioTrack("first")); - scoped_refptr<MockAudioTrackInterface> second(MakeAudioTrack("second")); - stream_->AddTrack(first.get()); - metrics_->AddStream(MediaStreamTrackMetrics::SENT_STREAM, stream_.get()); - - // This gets added after we start observing, but no lifetime message - // should be sent at this point since the call is not connected. It - // should get sent only once it gets connected. - AddAudioTrack(second.get()); - - EXPECT_CALL(*metrics_, - SendLifetimeMessage("first", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("second", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); +TEST_F(MediaStreamTrackMetricsTest, RemoveAfterDisconnect) { + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kAudio, "audio"); + + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kSend)); metrics_->IceConnectionChange( PeerConnectionInterface::kIceConnectionConnected); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("first", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("second", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); + EXPECT_CALL( + *metrics_, + SendLifetimeMessage("audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kDisconnected, + MediaStreamTrackMetrics::Direction::kSend)); metrics_->IceConnectionChange(PeerConnectionInterface::kIceConnectionFailed); // This happens after the call is disconnected so no lifetime // message should be sent. - RemoveAudioTrack(first.get()); + metrics_->RemoveTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kAudio, "audio"); } TEST_F(MediaStreamTrackMetricsTest, RemoteStreamMultipleDisconnects) { - scoped_refptr<MockAudioTrackInterface> audio(MakeAudioTrack("audio")); - stream_->AddTrack(audio.get()); - metrics_->AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM, stream_.get()); - - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::RECEIVED_STREAM)); + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kReceive, + MediaStreamTrackMetrics::Kind::kAudio, "audio"); + + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kReceive)); metrics_->IceConnectionChange( PeerConnectionInterface::kIceConnectionConnected); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::RECEIVED_STREAM)); + EXPECT_CALL( + *metrics_, + SendLifetimeMessage("audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kDisconnected, + MediaStreamTrackMetrics::Direction::kReceive)); metrics_->IceConnectionChange( PeerConnectionInterface::kIceConnectionDisconnected); metrics_->IceConnectionChange(PeerConnectionInterface::kIceConnectionFailed); - RemoveAudioTrack(audio.get()); + metrics_->RemoveTrack(MediaStreamTrackMetrics::Direction::kReceive, + MediaStreamTrackMetrics::Kind::kAudio, "audio"); } TEST_F(MediaStreamTrackMetricsTest, RemoteStreamConnectDisconnectTwice) { - scoped_refptr<MockAudioTrackInterface> audio(MakeAudioTrack("audio")); - stream_->AddTrack(audio.get()); - metrics_->AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM, stream_.get()); + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kReceive, + MediaStreamTrackMetrics::Kind::kAudio, "audio"); for (size_t i = 0; i < 2; ++i) { - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::RECEIVED_STREAM)); + EXPECT_CALL( + *metrics_, + SendLifetimeMessage("audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kReceive)); metrics_->IceConnectionChange( PeerConnectionInterface::kIceConnectionConnected); EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::RECEIVED_STREAM)); + SendLifetimeMessage( + "audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kDisconnected, + MediaStreamTrackMetrics::Direction::kReceive)); metrics_->IceConnectionChange( PeerConnectionInterface::kIceConnectionDisconnected); } - RemoveAudioTrack(audio.get()); + metrics_->RemoveTrack(MediaStreamTrackMetrics::Direction::kReceive, + MediaStreamTrackMetrics::Kind::kAudio, "audio"); } TEST_F(MediaStreamTrackMetricsTest, LocalStreamRemovedNoDisconnect) { - scoped_refptr<MockAudioTrackInterface> audio(MakeAudioTrack("audio")); - scoped_refptr<MockVideoTrackInterface> video(MakeVideoTrack("video")); - stream_->AddTrack(audio.get()); - stream_->AddTrack(video.get()); - metrics_->AddStream(MediaStreamTrackMetrics::SENT_STREAM, stream_.get()); - - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("video", - MediaStreamTrackMetrics::VIDEO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kAudio, "audio"); + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kVideo, "video"); + + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kSend)); + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "video", MediaStreamTrackMetrics::Kind::kVideo, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kSend)); metrics_->IceConnectionChange( PeerConnectionInterface::kIceConnectionConnected); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("video", - MediaStreamTrackMetrics::VIDEO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - metrics_->RemoveStream(MediaStreamTrackMetrics::SENT_STREAM, stream_.get()); + EXPECT_CALL( + *metrics_, + SendLifetimeMessage("audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kDisconnected, + MediaStreamTrackMetrics::Direction::kSend)); + EXPECT_CALL( + *metrics_, + SendLifetimeMessage("video", MediaStreamTrackMetrics::Kind::kVideo, + MediaStreamTrackMetrics::LifetimeEvent::kDisconnected, + MediaStreamTrackMetrics::Direction::kSend)); + metrics_->RemoveTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kAudio, "audio"); + metrics_->RemoveTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kVideo, "video"); } TEST_F(MediaStreamTrackMetricsTest, LocalStreamLargerTest) { - scoped_refptr<MockAudioTrackInterface> audio1(MakeAudioTrack("audio1")); - scoped_refptr<MockAudioTrackInterface> audio2(MakeAudioTrack("audio2")); - scoped_refptr<MockAudioTrackInterface> audio3(MakeAudioTrack("audio3")); - scoped_refptr<MockVideoTrackInterface> video1(MakeVideoTrack("video1")); - scoped_refptr<MockVideoTrackInterface> video2(MakeVideoTrack("video2")); - scoped_refptr<MockVideoTrackInterface> video3(MakeVideoTrack("video3")); - stream_->AddTrack(audio1.get()); - stream_->AddTrack(video1.get()); - metrics_->AddStream(MediaStreamTrackMetrics::SENT_STREAM, stream_.get()); - - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio1", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("video1", - MediaStreamTrackMetrics::VIDEO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kAudio, "audio"); + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kVideo, "video"); + + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kSend)); + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "video", MediaStreamTrackMetrics::Kind::kVideo, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kSend)); metrics_->IceConnectionChange( PeerConnectionInterface::kIceConnectionConnected); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio2", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - AddAudioTrack(audio2.get()); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("video2", - MediaStreamTrackMetrics::VIDEO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - AddVideoTrack(video2.get()); - - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio1", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - RemoveAudioTrack(audio1.get()); - - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio3", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - AddAudioTrack(audio3.get()); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("video3", - MediaStreamTrackMetrics::VIDEO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - AddVideoTrack(video3.get()); - - // Add back audio1 - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio1", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::CONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - AddAudioTrack(audio1.get()); - - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio2", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - RemoveAudioTrack(audio2.get()); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("video2", - MediaStreamTrackMetrics::VIDEO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - RemoveVideoTrack(video2.get()); - - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio1", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - RemoveAudioTrack(audio1.get()); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("video1", - MediaStreamTrackMetrics::VIDEO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - RemoveVideoTrack(video1.get()); - - EXPECT_CALL(*metrics_, - SendLifetimeMessage("audio3", - MediaStreamTrackMetrics::AUDIO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - EXPECT_CALL(*metrics_, - SendLifetimeMessage("video3", - MediaStreamTrackMetrics::VIDEO_TRACK, - MediaStreamTrackMetrics::DISCONNECTED, - MediaStreamTrackMetrics::SENT_STREAM)); - metrics_->RemoveStream(MediaStreamTrackMetrics::SENT_STREAM, stream_.get()); + EXPECT_CALL( + *metrics_, + SendLifetimeMessage("audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kDisconnected, + MediaStreamTrackMetrics::Direction::kSend)); + metrics_->RemoveTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kAudio, "audio"); + + // Add back audio + EXPECT_CALL(*metrics_, SendLifetimeMessage( + "audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kConnected, + MediaStreamTrackMetrics::Direction::kSend)); + metrics_->AddTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kAudio, "audio"); + + EXPECT_CALL( + *metrics_, + SendLifetimeMessage("audio", MediaStreamTrackMetrics::Kind::kAudio, + MediaStreamTrackMetrics::LifetimeEvent::kDisconnected, + MediaStreamTrackMetrics::Direction::kSend)); + metrics_->RemoveTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kAudio, "audio"); + EXPECT_CALL( + *metrics_, + SendLifetimeMessage("video", MediaStreamTrackMetrics::Kind::kVideo, + MediaStreamTrackMetrics::LifetimeEvent::kDisconnected, + MediaStreamTrackMetrics::Direction::kSend)); + metrics_->RemoveTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetrics::Kind::kVideo, "video"); } } // namespace content diff --git a/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.cc b/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.cc index be896490fc6..837f67cfe22 100644 --- a/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.cc +++ b/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.cc @@ -28,8 +28,8 @@ namespace content { namespace { -rtc::Optional<bool> ToRtcOptionalBool(const base::Optional<bool>& value) { - return value ? rtc::Optional<bool>(*value) : rtc::Optional<bool>(); +absl::optional<bool> ToAbslOptionalBool(const base::Optional<bool>& value) { + return value ? absl::optional<bool>(*value) : absl::nullopt; } } // namespace @@ -39,8 +39,8 @@ class MediaStreamVideoWebRtcSink::WebRtcVideoSource public: WebRtcVideoSource(WebRtcVideoCapturerAdapter* capture_adapter, bool is_screencast, - rtc::Optional<bool> needs_denoising) - : VideoTrackSource(capture_adapter, false), + absl::optional<bool> needs_denoising) + : VideoTrackSource(false), capture_adapter_(capture_adapter), is_screencast_(is_screencast), needs_denoising_(needs_denoising) {} @@ -50,14 +50,19 @@ class MediaStreamVideoWebRtcSink::WebRtcVideoSource } bool is_screencast() const override { return is_screencast_; } - rtc::Optional<bool> needs_denoising() const override { + absl::optional<bool> needs_denoising() const override { return needs_denoising_; } + protected: + rtc::VideoSourceInterface<webrtc::VideoFrame>* source() override { + return capture_adapter_.get(); + } + private: std::unique_ptr<WebRtcVideoCapturerAdapter> const capture_adapter_; const bool is_screencast_; - const rtc::Optional<bool> needs_denoising_; + const absl::optional<bool> needs_denoising_; }; namespace { @@ -84,6 +89,8 @@ webrtc::VideoTrackInterface::ContentHint ContentHintTypeToWebRtcContentHint( return webrtc::VideoTrackInterface::ContentHint::kFluid; case blink::WebMediaStreamTrack::ContentHintType::kVideoDetail: return webrtc::VideoTrackInterface::ContentHint::kDetailed; + case blink::WebMediaStreamTrack::ContentHintType::kVideoText: + return webrtc::VideoTrackInterface::ContentHint::kText; } NOTREACHED(); return webrtc::VideoTrackInterface::ContentHint::kNone; @@ -269,8 +276,8 @@ MediaStreamVideoWebRtcSink::MediaStreamVideoWebRtcSink( MediaStreamVideoTrack::GetVideoTrack(track); DCHECK(video_track); - rtc::Optional<bool> needs_denoising = - ToRtcOptionalBool(video_track->noise_reduction()); + absl::optional<bool> needs_denoising = + ToAbslOptionalBool(video_track->noise_reduction()); bool is_screencast = video_track->is_screencast(); base::Optional<double> min_frame_rate = video_track->min_frame_rate(); @@ -364,8 +371,8 @@ void MediaStreamVideoWebRtcSink::RequestRefreshFrame() { content::RequestRefreshFrameFromVideoTrack(connected_track()); } -rtc::Optional<bool> MediaStreamVideoWebRtcSink::SourceNeedsDenoisingForTesting() - const { +absl::optional<bool> +MediaStreamVideoWebRtcSink::SourceNeedsDenoisingForTesting() const { return video_source_->needs_denoising(); } diff --git a/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.h b/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.h index 8ff0331d038..d8039286fa8 100644 --- a/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.h +++ b/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.h @@ -43,7 +43,7 @@ class CONTENT_EXPORT MediaStreamVideoWebRtcSink : public MediaStreamVideoSink { return video_track_.get(); } - rtc::Optional<bool> SourceNeedsDenoisingForTesting() const; + absl::optional<bool> SourceNeedsDenoisingForTesting() const; protected: // Implementation of MediaStreamSink. diff --git a/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink_unittest.cc b/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink_unittest.cc index 5265f9477fb..d33db26d3c6 100644 --- a/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink_unittest.cc +++ b/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink_unittest.cc @@ -25,8 +25,8 @@ class MediaStreamVideoWebRtcSinkTest : public ::testing::Test { void SetVideoTrack() { registry_.Init("stream URL"); registry_.AddVideoTrack("test video track"); - blink::WebVector<blink::WebMediaStreamTrack> video_tracks; - registry_.test_stream().VideoTracks(video_tracks); + blink::WebVector<blink::WebMediaStreamTrack> video_tracks = + registry_.test_stream().VideoTracks(); track_ = video_tracks[0]; // TODO(hta): Verify that track_ is valid. When constraints produce // no valid format, using the track will cause a crash. @@ -36,8 +36,8 @@ class MediaStreamVideoWebRtcSinkTest : public ::testing::Test { registry_.Init("stream URL"); registry_.AddVideoTrack("test video track", VideoTrackAdapterSettings(), noise_reduction, false, 0.0); - blink::WebVector<blink::WebMediaStreamTrack> video_tracks; - registry_.test_stream().VideoTracks(video_tracks); + blink::WebVector<blink::WebMediaStreamTrack> video_tracks = + registry_.test_stream().VideoTracks(); track_ = video_tracks[0]; // TODO(hta): Verify that track_ is valid. When constraints produce // no valid format, using the track will cause a crash. diff --git a/chromium/content/renderer/media/webrtc/mock_peer_connection_impl.cc b/chromium/content/renderer/media/webrtc/mock_peer_connection_impl.cc index ebc81901bd4..ee019112cb9 100644 --- a/chromium/content/renderer/media/webrtc/mock_peer_connection_impl.cc +++ b/chromium/content/renderer/media/webrtc/mock_peer_connection_impl.cc @@ -9,8 +9,10 @@ #include <vector> #include "base/logging.h" +#include "base/stl_util.h" #include "content/renderer/media/webrtc/mock_data_channel_impl.h" #include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h" +#include "content/renderer/media/webrtc/webrtc_util.h" #include "third_party/webrtc/api/rtpreceiverinterface.h" #include "third_party/webrtc/rtc_base/refcountedobject.h" @@ -58,19 +60,6 @@ class MockStreamCollection : public webrtc::StreamCollectionInterface { } return nullptr; } - std::vector<webrtc::MediaStreamInterface*> FindStreamsOfTrack( - webrtc::MediaStreamTrackInterface* track) { - std::vector<webrtc::MediaStreamInterface*> streams_of_track; - if (!track) - return streams_of_track; - for (size_t i = 0; i < streams_.size(); ++i) { - if (streams_.at(i)->FindAudioTrack(track->id()) || - streams_.at(i)->FindVideoTrack(track->id())) { - streams_of_track.push_back(streams_.at(i)); - } - } - return streams_of_track; - } void AddStream(MediaStreamInterface* stream) { streams_.push_back(stream); } @@ -95,8 +84,6 @@ class MockStreamCollection : public webrtc::StreamCollectionInterface { class MockDtmfSender : public DtmfSenderInterface { public: - explicit MockDtmfSender(AudioTrackInterface* track) - : track_(track), observer_(nullptr), duration_(0), inter_tone_gap_(0) {} void RegisterObserver(DtmfSenderObserverInterface* observer) override { observer_ = observer; } @@ -110,25 +97,21 @@ class MockDtmfSender : public DtmfSenderInterface { inter_tone_gap_ = inter_tone_gap; return true; } - const AudioTrackInterface* track() const override { return track_.get(); } std::string tones() const override { return tones_; } int duration() const override { return duration_; } int inter_tone_gap() const override { return inter_tone_gap_; } - protected: - ~MockDtmfSender() override {} - private: - rtc::scoped_refptr<AudioTrackInterface> track_; - DtmfSenderObserverInterface* observer_; + DtmfSenderObserverInterface* observer_ = nullptr; std::string tones_; - int duration_; - int inter_tone_gap_; + int duration_ = 0; + int inter_tone_gap_ = 0; }; FakeRtpSender::FakeRtpSender( - rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track) - : track_(std::move(track)) {} + rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track, + std::vector<std::string> stream_ids) + : track_(std::move(track)), stream_ids_(std::move(stream_ids)) {} FakeRtpSender::~FakeRtpSender() {} @@ -158,11 +141,10 @@ std::string FakeRtpSender::id() const { } std::vector<std::string> FakeRtpSender::stream_ids() const { - NOTIMPLEMENTED(); - return {}; + return stream_ids_; } -webrtc::RtpParameters FakeRtpSender::GetParameters() const { +webrtc::RtpParameters FakeRtpSender::GetParameters() { NOTIMPLEMENTED(); return webrtc::RtpParameters(); } @@ -175,8 +157,7 @@ webrtc::RTCError FakeRtpSender::SetParameters( rtc::scoped_refptr<webrtc::DtmfSenderInterface> FakeRtpSender::GetDtmfSender() const { - NOTIMPLEMENTED(); - return nullptr; + return new rtc::RefCountedObject<MockDtmfSender>(); } FakeRtpReceiver::FakeRtpReceiver( @@ -226,6 +207,69 @@ std::vector<webrtc::RtpSource> FakeRtpReceiver::GetSources() const { return std::vector<webrtc::RtpSource>(); } +FakeRtpTransceiver::FakeRtpTransceiver( + cricket::MediaType media_type, + rtc::scoped_refptr<webrtc::RtpSenderInterface> sender, + rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver, + base::Optional<std::string> mid, + bool stopped, + webrtc::RtpTransceiverDirection direction, + base::Optional<webrtc::RtpTransceiverDirection> current_direction) + : media_type_(media_type), + sender_(std::move(sender)), + receiver_(std::move(receiver)), + mid_(ToAbslOptional(mid)), + stopped_(stopped), + direction_(direction), + current_direction_(ToAbslOptional(current_direction)) {} + +FakeRtpTransceiver::~FakeRtpTransceiver() {} + +cricket::MediaType FakeRtpTransceiver::media_type() const { + return media_type_; +} + +absl::optional<std::string> FakeRtpTransceiver::mid() const { + return mid_; +} + +rtc::scoped_refptr<webrtc::RtpSenderInterface> FakeRtpTransceiver::sender() + const { + return sender_; +} + +rtc::scoped_refptr<webrtc::RtpReceiverInterface> FakeRtpTransceiver::receiver() + const { + return receiver_; +} + +bool FakeRtpTransceiver::stopped() const { + return stopped_; +} + +webrtc::RtpTransceiverDirection FakeRtpTransceiver::direction() const { + return direction_; +} + +void FakeRtpTransceiver::SetDirection( + webrtc::RtpTransceiverDirection new_direction) { + NOTIMPLEMENTED(); +} + +absl::optional<webrtc::RtpTransceiverDirection> +FakeRtpTransceiver::current_direction() const { + return current_direction_; +} + +void FakeRtpTransceiver::Stop() { + NOTIMPLEMENTED(); +} + +void FakeRtpTransceiver::SetCodecPreferences( + rtc::ArrayView<webrtc::RtpCodecCapability> codecs) { + NOTIMPLEMENTED(); +} + const char MockPeerConnectionImpl::kDummyOffer[] = "dummy offer"; const char MockPeerConnectionImpl::kDummyAnswer[] = "dummy answer"; @@ -233,7 +277,6 @@ MockPeerConnectionImpl::MockPeerConnectionImpl( MockPeerConnectionDependencyFactory* factory, webrtc::PeerConnectionObserver* observer) : dependency_factory_(factory), - local_streams_(new rtc::RefCountedObject<MockStreamCollection>), remote_streams_(new rtc::RefCountedObject<MockStreamCollection>), hint_audio_(false), hint_video_(false), @@ -257,73 +300,42 @@ MockPeerConnectionImpl::MockPeerConnectionImpl( MockPeerConnectionImpl::~MockPeerConnectionImpl() {} -rtc::scoped_refptr<webrtc::StreamCollectionInterface> -MockPeerConnectionImpl::local_streams() { - return local_streams_; -} - -rtc::scoped_refptr<webrtc::StreamCollectionInterface> -MockPeerConnectionImpl::remote_streams() { - return remote_streams_; -} - -rtc::scoped_refptr<webrtc::RtpSenderInterface> MockPeerConnectionImpl::AddTrack( - webrtc::MediaStreamTrackInterface* track, - std::vector<webrtc::MediaStreamInterface*> streams) { +webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpSenderInterface>> +MockPeerConnectionImpl::AddTrack( + rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track, + const std::vector<std::string>& stream_ids) { DCHECK(track); - DCHECK_EQ(1u, streams.size()); + DCHECK_EQ(1u, stream_ids.size()); for (const auto& sender : senders_) { if (sender->track() == track) - return nullptr; + return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER); } - for (auto* stream : streams) { - if (!local_streams_->find(stream->id())) { - stream_label_ = stream->id(); - local_streams_->AddStream(stream); + for (const auto& stream_id : stream_ids) { + if (!base::ContainsValue(local_stream_ids_, stream_id)) { + stream_label_ = stream_id; + local_stream_ids_.push_back(stream_id); } } - auto* sender = new rtc::RefCountedObject<FakeRtpSender>(track); + auto* sender = new rtc::RefCountedObject<FakeRtpSender>(track, stream_ids); senders_.push_back(sender); - return sender; + return rtc::scoped_refptr<webrtc::RtpSenderInterface>(sender); } -bool MockPeerConnectionImpl::RemoveTrack(webrtc::RtpSenderInterface* sender) { - auto it = std::find(senders_.begin(), senders_.end(), - static_cast<FakeRtpSender*>(sender)); +bool MockPeerConnectionImpl::RemoveTrack(webrtc::RtpSenderInterface* s) { + rtc::scoped_refptr<FakeRtpSender> sender = static_cast<FakeRtpSender*>(s); + auto it = std::find(senders_.begin(), senders_.end(), sender); if (it == senders_.end()) return false; senders_.erase(it); auto track = sender->track(); - for (auto* stream : local_streams_->FindStreamsOfTrack(track)) { - bool stream_has_senders = false; - for (const auto& track : stream->GetAudioTracks()) { - for (const auto& sender : senders_) { - if (sender->track() == track) { - stream_has_senders = true; - break; - } - } - } - for (const auto& track : stream->GetVideoTracks()) { - for (const auto& sender : senders_) { - if (sender->track() == track) { - stream_has_senders = true; - break; - } - } - } - if (!stream_has_senders) - local_streams_->RemoveStream(stream); - } - return true; -} -rtc::scoped_refptr<DtmfSenderInterface> -MockPeerConnectionImpl::CreateDtmfSender(AudioTrackInterface* track) { - if (!track) { - return nullptr; + for (const auto& stream_id : sender->stream_ids()) { + auto local_stream_it = std::find(local_stream_ids_.begin(), + local_stream_ids_.end(), stream_id); + if (local_stream_it != local_stream_ids_.end()) + local_stream_ids_.erase(local_stream_it); } - return new rtc::RefCountedObject<MockDtmfSender>(track); + return true; } std::vector<rtc::scoped_refptr<webrtc::RtpSenderInterface>> @@ -477,11 +489,6 @@ bool MockPeerConnectionImpl::AddIceCandidate( return candidate->ToString(&ice_sdp_); } -void MockPeerConnectionImpl::RegisterUMAObserver( - webrtc::UMAObserver* observer) { - NOTIMPLEMENTED(); -} - webrtc::RTCError MockPeerConnectionImpl::SetBitrate( const webrtc::BitrateSettings& bitrate) { NOTIMPLEMENTED(); diff --git a/chromium/content/renderer/media/webrtc/mock_peer_connection_impl.h b/chromium/content/renderer/media/webrtc/mock_peer_connection_impl.h index da06e71438e..5d348e74b72 100644 --- a/chromium/content/renderer/media/webrtc/mock_peer_connection_impl.h +++ b/chromium/content/renderer/media/webrtc/mock_peer_connection_impl.h @@ -11,6 +11,7 @@ #include "base/compiler_specific.h" #include "base/logging.h" #include "base/macros.h" +#include "base/optional.h" #include "testing/gmock/include/gmock/gmock.h" #include "third_party/webrtc/api/peerconnectioninterface.h" #include "third_party/webrtc/api/stats/rtcstatsreport.h" @@ -22,7 +23,8 @@ class MockStreamCollection; class FakeRtpSender : public webrtc::RtpSenderInterface { public: - FakeRtpSender(rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track); + FakeRtpSender(rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track, + std::vector<std::string> stream_ids); ~FakeRtpSender() override; bool SetTrack(webrtc::MediaStreamTrackInterface* track) override; @@ -31,7 +33,7 @@ class FakeRtpSender : public webrtc::RtpSenderInterface { cricket::MediaType media_type() const override; std::string id() const override; std::vector<std::string> stream_ids() const override; - webrtc::RtpParameters GetParameters() const override; + webrtc::RtpParameters GetParameters() override; webrtc::RTCError SetParameters( const webrtc::RtpParameters& parameters) override; rtc::scoped_refptr<webrtc::DtmfSenderInterface> GetDtmfSender() @@ -39,6 +41,7 @@ class FakeRtpSender : public webrtc::RtpSenderInterface { private: rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track_; + std::vector<std::string> stream_ids_; }; class FakeRtpReceiver : public webrtc::RtpReceiverInterface { @@ -63,6 +66,43 @@ class FakeRtpReceiver : public webrtc::RtpReceiverInterface { std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>> streams_; }; +class FakeRtpTransceiver : public webrtc::RtpTransceiverInterface { + public: + FakeRtpTransceiver( + cricket::MediaType media_type, + rtc::scoped_refptr<webrtc::RtpSenderInterface> sender, + rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver, + base::Optional<std::string> mid, + bool stopped, + webrtc::RtpTransceiverDirection direction, + base::Optional<webrtc::RtpTransceiverDirection> current_direction); + ~FakeRtpTransceiver() override; + + FakeRtpTransceiver& operator=(const FakeRtpTransceiver& other) = default; + + cricket::MediaType media_type() const override; + absl::optional<std::string> mid() const override; + rtc::scoped_refptr<webrtc::RtpSenderInterface> sender() const override; + rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver() const override; + bool stopped() const override; + webrtc::RtpTransceiverDirection direction() const override; + void SetDirection(webrtc::RtpTransceiverDirection new_direction) override; + absl::optional<webrtc::RtpTransceiverDirection> current_direction() + const override; + void Stop() override; + void SetCodecPreferences( + rtc::ArrayView<webrtc::RtpCodecCapability> codecs) override; + + private: + cricket::MediaType media_type_; + rtc::scoped_refptr<webrtc::RtpSenderInterface> sender_; + rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver_; + absl::optional<std::string> mid_; + bool stopped_; + webrtc::RtpTransceiverDirection direction_; + absl::optional<webrtc::RtpTransceiverDirection> current_direction_; +}; + // TODO(hbos): The use of fakes and mocks is the wrong approach for testing of // this. It introduces complexity, is error prone (not testing the right thing // and bugs in the mocks). This class is a maintenance burden and should be @@ -73,10 +113,16 @@ class MockPeerConnectionImpl : public webrtc::PeerConnectionInterface { webrtc::PeerConnectionObserver* observer); // PeerConnectionInterface implementation. - rtc::scoped_refptr<webrtc::StreamCollectionInterface> - local_streams() override; - rtc::scoped_refptr<webrtc::StreamCollectionInterface> - remote_streams() override; + rtc::scoped_refptr<webrtc::StreamCollectionInterface> local_streams() + override { + NOTIMPLEMENTED(); + return nullptr; + } + rtc::scoped_refptr<webrtc::StreamCollectionInterface> remote_streams() + override { + NOTIMPLEMENTED(); + return nullptr; + } bool AddStream(webrtc::MediaStreamInterface* local_stream) override { NOTIMPLEMENTED(); return false; @@ -84,14 +130,10 @@ class MockPeerConnectionImpl : public webrtc::PeerConnectionInterface { void RemoveStream(webrtc::MediaStreamInterface* local_stream) override { NOTIMPLEMENTED(); } - // TODO(hbos): Use AddTrack() taking stream labels instead of stream pointers. - // https://crbug.com/810708 - rtc::scoped_refptr<webrtc::RtpSenderInterface> AddTrack( - webrtc::MediaStreamTrackInterface* track, - std::vector<webrtc::MediaStreamInterface*> streams) override; + webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpSenderInterface>> AddTrack( + rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track, + const std::vector<std::string>& stream_ids) override; bool RemoveTrack(webrtc::RtpSenderInterface* sender) override; - rtc::scoped_refptr<webrtc::DtmfSenderInterface> - CreateDtmfSender(webrtc::AudioTrackInterface* track) override; std::vector<rtc::scoped_refptr<webrtc::RtpSenderInterface>> GetSenders() const override; std::vector<rtc::scoped_refptr<webrtc::RtpReceiverInterface>> GetReceivers() @@ -174,7 +216,6 @@ class MockPeerConnectionImpl : public webrtc::PeerConnectionInterface { bool SetConfiguration(const RTCConfiguration& configuration, webrtc::RTCError* error) override; bool AddIceCandidate(const webrtc::IceCandidateInterface* candidate) override; - void RegisterUMAObserver(webrtc::UMAObserver* observer) override; webrtc::RTCError SetBitrate(const webrtc::BitrateSettings& bitrate) override; @@ -207,7 +248,7 @@ class MockPeerConnectionImpl : public webrtc::PeerConnectionInterface { MockPeerConnectionDependencyFactory* dependency_factory_; std::string stream_label_; - rtc::scoped_refptr<MockStreamCollection> local_streams_; + std::vector<std::string> local_stream_ids_; rtc::scoped_refptr<MockStreamCollection> remote_streams_; std::vector<rtc::scoped_refptr<FakeRtpSender>> senders_; std::unique_ptr<webrtc::SessionDescriptionInterface> local_desc_; diff --git a/chromium/content/renderer/media/webrtc/mock_web_rtc_peer_connection_handler_client.cc b/chromium/content/renderer/media/webrtc/mock_web_rtc_peer_connection_handler_client.cc index 6d8afca21d7..a1ec79ef9f7 100644 --- a/chromium/content/renderer/media/webrtc/mock_web_rtc_peer_connection_handler_client.cc +++ b/chromium/content/renderer/media/webrtc/mock_web_rtc_peer_connection_handler_client.cc @@ -20,14 +20,13 @@ MockWebRTCPeerConnectionHandlerClient() .WillByDefault( testing::Invoke(this, &MockWebRTCPeerConnectionHandlerClient:: didGenerateICECandidateWorker)); - ON_CALL(*this, DidAddRemoteTrackForMock(_)) + ON_CALL(*this, DidAddReceiverPlanBForMock(_)) .WillByDefault(testing::Invoke( - this, - &MockWebRTCPeerConnectionHandlerClient::didAddRemoteTrackWorker)); - ON_CALL(*this, DidRemoveRemoteTrackForMock(_)) + this, &MockWebRTCPeerConnectionHandlerClient::didAddReceiverWorker)); + ON_CALL(*this, DidRemoveReceiverPlanBForMock(_)) .WillByDefault(testing::Invoke( this, - &MockWebRTCPeerConnectionHandlerClient::didRemoveRemoteTrackWorker)); + &MockWebRTCPeerConnectionHandlerClient::didRemoveReceiverWorker)); } MockWebRTCPeerConnectionHandlerClient:: @@ -40,17 +39,17 @@ void MockWebRTCPeerConnectionHandlerClient::didGenerateICECandidateWorker( candidate_mid_ = candidate->SdpMid().Utf8(); } -void MockWebRTCPeerConnectionHandlerClient::didAddRemoteTrackWorker( +void MockWebRTCPeerConnectionHandlerClient::didAddReceiverWorker( std::unique_ptr<blink::WebRTCRtpReceiver>* web_rtp_receiver) { - blink::WebVector<blink::WebMediaStream> web_streams = - (*web_rtp_receiver)->Streams(); - DCHECK_EQ(1u, web_streams.size()); - remote_stream_ = web_streams[0]; + blink::WebVector<blink::WebString> stream_ids = + (*web_rtp_receiver)->StreamIds(); + DCHECK_EQ(1u, stream_ids.size()); + remote_stream_id_ = stream_ids[0]; } -void MockWebRTCPeerConnectionHandlerClient::didRemoveRemoteTrackWorker( +void MockWebRTCPeerConnectionHandlerClient::didRemoveReceiverWorker( std::unique_ptr<blink::WebRTCRtpReceiver>* web_rtp_receiver) { - remote_stream_.Reset(); + remote_stream_id_ = blink::WebString(); } } // 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 6958818c8c2..32ec4d023d4 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 @@ -14,6 +14,7 @@ #include "third_party/blink/public/platform/web_rtc_ice_candidate.h" #include "third_party/blink/public/platform/web_rtc_peer_connection_handler_client.h" #include "third_party/blink/public/platform/web_rtc_rtp_receiver.h" +#include "third_party/blink/public/platform/web_rtc_rtp_transceiver.h" namespace content { @@ -27,33 +28,42 @@ class MockWebRTCPeerConnectionHandlerClient MOCK_METHOD0(NegotiationNeeded, void()); MOCK_METHOD1(DidGenerateICECandidate, void(scoped_refptr<blink::WebRTCICECandidate> candidate)); - MOCK_METHOD1(DidChangeSignalingState, void(SignalingState state)); + MOCK_METHOD1(DidChangeSignalingState, + void(webrtc::PeerConnectionInterface::SignalingState state)); MOCK_METHOD1(DidChangeICEGatheringState, void(ICEGatheringState state)); MOCK_METHOD1(DidChangeICEConnectionState, void(ICEConnectionState state)); - void DidAddRemoteTrack( + void DidAddReceiverPlanB( std::unique_ptr<blink::WebRTCRtpReceiver> web_rtp_receiver) override { - DidAddRemoteTrackForMock(&web_rtp_receiver); + DidAddReceiverPlanBForMock(&web_rtp_receiver); } - void DidRemoveRemoteTrack( + void DidRemoveReceiverPlanB( std::unique_ptr<blink::WebRTCRtpReceiver> web_rtp_receiver) override { - DidRemoveRemoteTrackForMock(&web_rtp_receiver); + DidRemoveReceiverPlanBForMock(&web_rtp_receiver); + } + void DidModifyTransceivers( + std::vector<std::unique_ptr<blink::WebRTCRtpTransceiver>> + web_transceivers, + bool is_remote_description) override { + DidModifyTransceiversForMock(&web_transceivers, is_remote_description); } MOCK_METHOD1(DidAddRemoteDataChannel, void(blink::WebRTCDataChannelHandler*)); MOCK_METHOD0(ReleasePeerConnectionHandler, void()); - MOCK_METHOD0(GetOriginTrials, WebRTCOriginTrials()); // Move-only arguments do not play nicely with MOCK, the workaround is to // EXPECT_CALL with these instead. - MOCK_METHOD1(DidAddRemoteTrackForMock, + MOCK_METHOD1(DidAddReceiverPlanBForMock, void(std::unique_ptr<blink::WebRTCRtpReceiver>*)); - MOCK_METHOD1(DidRemoveRemoteTrackForMock, + MOCK_METHOD1(DidRemoveReceiverPlanBForMock, void(std::unique_ptr<blink::WebRTCRtpReceiver>*)); + MOCK_METHOD2(DidModifyTransceiversForMock, + void(std::vector<std::unique_ptr<blink::WebRTCRtpTransceiver>>*, + bool)); void didGenerateICECandidateWorker( scoped_refptr<blink::WebRTCICECandidate> candidate); - void didAddRemoteTrackWorker( + void didAddReceiverWorker( std::unique_ptr<blink::WebRTCRtpReceiver>* stream_web_rtp_receivers); - void didRemoveRemoteTrackWorker( + void didRemoveReceiverWorker( std::unique_ptr<blink::WebRTCRtpReceiver>* stream_web_rtp_receivers); const std::string& candidate_sdp() const { return candidate_sdp_; } @@ -61,10 +71,10 @@ class MockWebRTCPeerConnectionHandlerClient return candidate_mline_index_; } const std::string& candidate_mid() const { return candidate_mid_ ; } - const blink::WebMediaStream& remote_stream() const { return remote_stream_; } + const blink::WebString& remote_stream_id() const { return remote_stream_id_; } private: - blink::WebMediaStream remote_stream_; + blink::WebString remote_stream_id_; std::string candidate_sdp_; int candidate_mline_index_; std::string candidate_mid_; 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 d57e983c03b..d0c4b1b96f9 100644 --- a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc +++ b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc @@ -620,4 +620,30 @@ void PeerConnectionDependencyFactory::EnsureWebRtcAudioDeviceImpl() { audio_device_ = new rtc::RefCountedObject<WebRtcAudioDeviceImpl>(); } +std::unique_ptr<webrtc::RtpCapabilities> +PeerConnectionDependencyFactory::GetSenderCapabilities( + const std::string& kind) { + if (kind == "audio") { + return std::make_unique<webrtc::RtpCapabilities>( + GetPcFactory()->GetRtpSenderCapabilities(cricket::MEDIA_TYPE_AUDIO)); + } else if (kind == "video") { + return std::make_unique<webrtc::RtpCapabilities>( + GetPcFactory()->GetRtpSenderCapabilities(cricket::MEDIA_TYPE_VIDEO)); + } + return nullptr; +} + +std::unique_ptr<webrtc::RtpCapabilities> +PeerConnectionDependencyFactory::GetReceiverCapabilities( + const std::string& kind) { + if (kind == "audio") { + return std::make_unique<webrtc::RtpCapabilities>( + GetPcFactory()->GetRtpReceiverCapabilities(cricket::MEDIA_TYPE_AUDIO)); + } else if (kind == "video") { + return std::make_unique<webrtc::RtpCapabilities>( + GetPcFactory()->GetRtpReceiverCapabilities(cricket::MEDIA_TYPE_VIDEO)); + } + return nullptr; +} + } // namespace content 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 8f1cbd22a8c..db7919fe1e5 100644 --- a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h +++ b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h @@ -94,6 +94,13 @@ class CONTENT_EXPORT PeerConnectionDependencyFactory int sdp_mline_index, const std::string& sdp); + // Returns the most optimistic view of the capabilities of the system for + // sending or receiving media of the given kind ("audio" or "video"). + virtual std::unique_ptr<webrtc::RtpCapabilities> GetSenderCapabilities( + const std::string& kind); + virtual std::unique_ptr<webrtc::RtpCapabilities> GetReceiverCapabilities( + const std::string& kind); + WebRtcAudioDeviceImpl* GetWebRtcAudioDevice(); void EnsureInitialized(); diff --git a/chromium/content/renderer/media/webrtc/peer_connection_tracker.cc b/chromium/content/renderer/media/webrtc/peer_connection_tracker.cc index 85ce26f5918..4566c247f7b 100644 --- a/chromium/content/renderer/media/webrtc/peer_connection_tracker.cc +++ b/chromium/content/renderer/media/webrtc/peer_connection_tracker.cc @@ -87,39 +87,111 @@ static std::string SerializeAnswerOptions( return result.str(); } -static std::string SerializeMediaStreamComponent( - const blink::WebMediaStreamTrack& component) { - return component.Source().Id().Utf8(); -} - -static std::string SerializeMediaDescriptor( - const blink::WebMediaStream& stream) { - std::string id = stream.Id().Utf8(); - std::string result = "id: " + id; - blink::WebVector<blink::WebMediaStreamTrack> tracks; - stream.AudioTracks(tracks); - if (!tracks.IsEmpty()) { - result += ", audio: ["; - for (size_t i = 0; i < tracks.size(); ++i) { - result += SerializeMediaStreamComponent(tracks[i]); - if (i != tracks.size() - 1) - result += ", "; - } - result += "]"; +static std::string SerializeMediaStreamIds( + const blink::WebVector<blink::WebString>& stream_ids) { + if (!stream_ids.size()) + return "[]"; + std::string result = "["; + for (const auto& stream_id : stream_ids) { + if (result.size() > 2u) + result += ","; + result += "'" + stream_id.Utf8() + "'"; } - stream.VideoTracks(tracks); - if (!tracks.IsEmpty()) { - result += ", video: ["; - for (size_t i = 0; i < tracks.size(); ++i) { - result += SerializeMediaStreamComponent(tracks[i]); - if (i != tracks.size() - 1) - result += ", "; - } - result += "]"; + result += "]"; + return result; +} + +static const char* SerializeDirection( + webrtc::RtpTransceiverDirection direction) { + switch (direction) { + case webrtc::RtpTransceiverDirection::kSendRecv: + return "'sendrecv'"; + case webrtc::RtpTransceiverDirection::kSendOnly: + return "'sendonly'"; + case webrtc::RtpTransceiverDirection::kRecvOnly: + return "'recvonly'"; + case webrtc::RtpTransceiverDirection::kInactive: + return "'inactive'"; + } +} + +static const char* SerializeOptionalDirection( + const base::Optional<webrtc::RtpTransceiverDirection>& direction) { + return direction ? SerializeDirection(*direction) : "null"; +} + +static std::string SerializeSender(const std::string& indent, + const blink::WebRTCRtpSender& sender) { + std::string result = "{\n"; + // track:'id', + result += indent + " track:"; + if (sender.Track().IsNull()) { + result += "null"; + } else { + result += "'" + sender.Track().Source().Id().Utf8() + "'"; } + result += ",\n"; + // streams:['id,'id'], + result += indent + + " streams:" + SerializeMediaStreamIds(sender.StreamIds()) + ",\n"; + result += indent + "}"; + return result; +} + +static std::string SerializeReceiver(const std::string& indent, + const blink::WebRTCRtpReceiver& receiver) { + std::string result = "{\n"; + // track:'id', + DCHECK(!receiver.Track().IsNull()); + result += + indent + " track:'" + receiver.Track().Source().Id().Utf8() + "',\n"; + // streams:['id,'id'], + result += indent + + " streams:" + SerializeMediaStreamIds(receiver.StreamIds()) + + ",\n"; + result += indent + "}"; return result; } +static std::string SerializeTransceiver( + const blink::WebRTCRtpTransceiver& transceiver) { + if (transceiver.ImplementationType() == + blink::WebRTCRtpTransceiverImplementationType::kFullTransceiver) { + std::string result = "{\n"; + // mid:'foo', + if (transceiver.Mid().IsNull()) + result += " mid:null,\n"; + else + result += " mid:'" + transceiver.Mid().Utf8() + "',\n"; + // sender:{...}, + result += + " sender:" + SerializeSender(" ", *transceiver.Sender()) + ",\n"; + // receiver:{...}, + result += " receiver:" + SerializeReceiver(" ", *transceiver.Receiver()) + + ",\n"; + // stopped:false, + result += " stopped:" + + std::string(SerializeBoolean(transceiver.Stopped())) + ",\n"; + // direction:'sendrecv', + result += " direction:" + + std::string(SerializeDirection(transceiver.Direction())) + ",\n"; + // currentDirection:null, + result += " currentDirection:" + + std::string( + SerializeOptionalDirection(transceiver.CurrentDirection())) + + ",\n"; + result += "}"; + return result; + } + if (transceiver.ImplementationType() == + blink::WebRTCRtpTransceiverImplementationType::kPlanBSenderOnly) { + return SerializeSender("", *transceiver.Sender()); + } + DCHECK(transceiver.ImplementationType() == + blink::WebRTCRtpTransceiverImplementationType::kPlanBReceiverOnly); + return SerializeReceiver("", *transceiver.Receiver()); +} + static const char* SerializeIceTransportType( webrtc::PeerConnectionInterface::IceTransportsType type) { const char* transport_type = ""; @@ -216,15 +288,21 @@ static std::string SerializeConfiguration( // strings on chrome://webrtc-internals. static const char* GetSignalingStateString( - WebRTCPeerConnectionHandlerClient::SignalingState state) { + webrtc::PeerConnectionInterface::SignalingState state) { const char* result = ""; switch (state) { - GET_STRING_OF_STATE(SignalingStateStable) - GET_STRING_OF_STATE(SignalingStateHaveLocalOffer) - GET_STRING_OF_STATE(SignalingStateHaveRemoteOffer) - GET_STRING_OF_STATE(SignalingStateHaveLocalPrAnswer) - GET_STRING_OF_STATE(SignalingStateHaveRemotePrAnswer) - GET_STRING_OF_STATE(SignalingStateClosed) + case webrtc::PeerConnectionInterface::SignalingState::kStable: + return "SignalingStateStable"; + case webrtc::PeerConnectionInterface::SignalingState::kHaveLocalOffer: + return "SignalingStateHaveLocalOffer"; + case webrtc::PeerConnectionInterface::SignalingState::kHaveRemoteOffer: + return "SignalingStateHaveRemoteOffer"; + case webrtc::PeerConnectionInterface::SignalingState::kHaveLocalPrAnswer: + return "SignalingStateHaveLocalPrAnswer"; + case webrtc::PeerConnectionInterface::SignalingState::kHaveRemotePrAnswer: + return "SignalingStateHaveRemotePrAnswer"; + case webrtc::PeerConnectionInterface::SignalingState::kClosed: + return "SignalingStateClosed"; default: NOTREACHED(); break; @@ -264,6 +342,24 @@ static const char* GetIceGatheringStateString( return result; } +static const char* GetTransceiverUpdatedReasonString( + PeerConnectionTracker::TransceiverUpdatedReason reason) { + switch (reason) { + case PeerConnectionTracker::TransceiverUpdatedReason::kAddTransceiver: + return "addTransceiver"; + case PeerConnectionTracker::TransceiverUpdatedReason::kAddTrack: + return "addTrack"; + case PeerConnectionTracker::TransceiverUpdatedReason::kRemoveTrack: + return "removeTrack"; + case PeerConnectionTracker::TransceiverUpdatedReason::kSetLocalDescription: + return "setLocalDescription"; + case PeerConnectionTracker::TransceiverUpdatedReason::kSetRemoteDescription: + return "setRemoteDescription"; + } + NOTREACHED(); + return nullptr; +} + // Builds a DictionaryValue from the StatsReport. // Note: // The format must be consistent with what webrtc_internals.js expects. @@ -613,30 +709,73 @@ void PeerConnectionTracker::TrackAddIceCandidate( SendPeerConnectionUpdate(id, event, value); } -void PeerConnectionTracker::TrackAddStream( +void PeerConnectionTracker::TrackAddTransceiver( RTCPeerConnectionHandler* pc_handler, - const blink::WebMediaStream& stream, - Source source) { - DCHECK(main_thread_.CalledOnValidThread()); - int id = GetLocalIDForHandler(pc_handler); - if (id == -1) - return; - SendPeerConnectionUpdate( - id, source == SOURCE_LOCAL ? "addStream" : "onAddStream", - SerializeMediaDescriptor(stream)); + PeerConnectionTracker::TransceiverUpdatedReason reason, + const blink::WebRTCRtpTransceiver& transceiver, + size_t transceiver_index) { + TrackTransceiver("Added", pc_handler, reason, transceiver, transceiver_index); } -void PeerConnectionTracker::TrackRemoveStream( +void PeerConnectionTracker::TrackModifyTransceiver( RTCPeerConnectionHandler* pc_handler, - const blink::WebMediaStream& stream, - Source source) { + PeerConnectionTracker::TransceiverUpdatedReason reason, + const blink::WebRTCRtpTransceiver& transceiver, + size_t transceiver_index) { + TrackTransceiver("Modified", pc_handler, reason, transceiver, + transceiver_index); +} + +void PeerConnectionTracker::TrackRemoveTransceiver( + RTCPeerConnectionHandler* pc_handler, + PeerConnectionTracker::TransceiverUpdatedReason reason, + const blink::WebRTCRtpTransceiver& transceiver, + size_t transceiver_index) { + TrackTransceiver("Removed", pc_handler, reason, transceiver, + transceiver_index); +} + +void PeerConnectionTracker::TrackTransceiver( + const char* callback_type_ending, + RTCPeerConnectionHandler* pc_handler, + PeerConnectionTracker::TransceiverUpdatedReason reason, + const blink::WebRTCRtpTransceiver& transceiver, + size_t transceiver_index) { DCHECK(main_thread_.CalledOnValidThread()); int id = GetLocalIDForHandler(pc_handler); if (id == -1) return; - SendPeerConnectionUpdate( - id, source == SOURCE_LOCAL ? "removeStream" : "onRemoveStream", - SerializeMediaDescriptor(stream)); + std::string callback_type; + if (transceiver.ImplementationType() == + blink::WebRTCRtpTransceiverImplementationType::kFullTransceiver) { + callback_type = "transceiver"; + } else if (transceiver.ImplementationType() == + blink::WebRTCRtpTransceiverImplementationType::kPlanBSenderOnly) { + callback_type = "sender"; + } else { + callback_type = "receiver"; + } + callback_type += callback_type_ending; + + std::string result; + result += "Caused by: "; + result += GetTransceiverUpdatedReasonString(reason); + result += "\n\n"; + if (transceiver.ImplementationType() == + blink::WebRTCRtpTransceiverImplementationType::kFullTransceiver) { + result += "getTransceivers()"; + } else if (transceiver.ImplementationType() == + blink::WebRTCRtpTransceiverImplementationType::kPlanBSenderOnly) { + result += "getSenders()"; + } else { + DCHECK_EQ( + transceiver.ImplementationType(), + blink::WebRTCRtpTransceiverImplementationType::kPlanBReceiverOnly); + result += "getReceivers()"; + } + result += "[" + base::UintToString(transceiver_index) + "]:"; + result += SerializeTransceiver(transceiver); + SendPeerConnectionUpdate(id, callback_type, result); } void PeerConnectionTracker::TrackCreateDataChannel( @@ -664,8 +803,8 @@ void PeerConnectionTracker::TrackStop(RTCPeerConnectionHandler* pc_handler) { } void PeerConnectionTracker::TrackSignalingStateChange( - RTCPeerConnectionHandler* pc_handler, - WebRTCPeerConnectionHandlerClient::SignalingState state) { + RTCPeerConnectionHandler* pc_handler, + webrtc::PeerConnectionInterface::SignalingState state) { DCHECK(main_thread_.CalledOnValidThread()); int id = GetLocalIDForHandler(pc_handler); if (id == -1) @@ -779,11 +918,11 @@ int PeerConnectionTracker::GetLocalIDForHandler( void PeerConnectionTracker::SendPeerConnectionUpdate( int local_id, - const char* callback_type, + const std::string& callback_type, const std::string& value) { DCHECK(main_thread_.CalledOnValidThread()); GetPeerConnectionTrackerHost().get()->UpdatePeerConnection( - local_id, std::string(callback_type), value); + local_id, callback_type, value); } void PeerConnectionTracker::OverrideSendTargetForTesting(RenderThread* target) { @@ -797,6 +936,6 @@ PeerConnectionTracker::GetPeerConnectionTrackerHost() { &peer_connection_tracker_host_ptr_); } return peer_connection_tracker_host_ptr_; -}; +} } // namespace content diff --git a/chromium/content/renderer/media/webrtc/peer_connection_tracker.h b/chromium/content/renderer/media/webrtc/peer_connection_tracker.h index 0c35de2047e..24e0fd85e1c 100644 --- a/chromium/content/renderer/media/webrtc/peer_connection_tracker.h +++ b/chromium/content/renderer/media/webrtc/peer_connection_tracker.h @@ -16,6 +16,7 @@ #include "ipc/ipc_platform_file.h" #include "third_party/blink/public/platform/web_media_stream.h" #include "third_party/blink/public/platform/web_rtc_peer_connection_handler_client.h" +#include "third_party/blink/public/platform/web_rtc_rtp_transceiver.h" #include "third_party/blink/public/platform/web_rtc_session_description.h" #include "third_party/webrtc/api/peerconnectioninterface.h" @@ -60,6 +61,16 @@ class CONTENT_EXPORT PeerConnectionTracker ACTION_CREATE_ANSWER }; + // In Plan B: "Transceiver" refers to RTCRtpSender or RTCRtpReceiver. + // In Unified Plan: "Transceiver" refers to RTCRtpTransceiver. + enum class TransceiverUpdatedReason { + kAddTransceiver, + kAddTrack, + kRemoveTrack, + kSetLocalDescription, + kSetRemoteDescription, + }; + // RenderThreadObserver implementation. bool OnControlMessageReceived(const IPC::Message& message) override; @@ -116,15 +127,31 @@ class CONTENT_EXPORT PeerConnectionTracker Source source, bool succeeded); - // Sends an update when a media stream is added. - virtual void TrackAddStream( + // Sends an update when a transceiver is added, modified or removed. This can + // happen as a result of any of the methods indicated by |reason|. + // In Plan B: |transceiver| refers to its Sender() or Receiver() depending on + // ImplementationType(). Example events: "senderAdded", "receiverRemoved". + // In Plan B: |transceiver| has a fully implemented ImplementationType(). + // Example events: "transceiverAdded", "transceiverModified". + // See peer_connection_tracker_unittest.cc for expected resulting event + // strings. + virtual void TrackAddTransceiver( RTCPeerConnectionHandler* pc_handler, - const blink::WebMediaStream& stream, Source source); - - // Sends an update when a media stream is removed. - virtual void TrackRemoveStream( + TransceiverUpdatedReason reason, + const blink::WebRTCRtpTransceiver& transceiver, + size_t transceiver_index); + virtual void TrackModifyTransceiver( RTCPeerConnectionHandler* pc_handler, - const blink::WebMediaStream& stream, Source source); + TransceiverUpdatedReason reason, + const blink::WebRTCRtpTransceiver& transceiver, + size_t transceiver_index); + // TODO(hbos): When Plan B is removed this is no longer applicable. + // https://crbug.com/857004 + virtual void TrackRemoveTransceiver( + RTCPeerConnectionHandler* pc_handler, + TransceiverUpdatedReason reason, + const blink::WebRTCRtpTransceiver& transceiver, + size_t transceiver_index); // Sends an update when a DataChannel is created. virtual void TrackCreateDataChannel( @@ -137,7 +164,7 @@ class CONTENT_EXPORT PeerConnectionTracker // Sends an update when the signaling state of a PeerConnection has changed. virtual void TrackSignalingStateChange( RTCPeerConnectionHandler* pc_handler, - blink::WebRTCPeerConnectionHandlerClient::SignalingState state); + webrtc::PeerConnectionInterface::SignalingState state); // Sends an update when the Ice connection state // of a PeerConnection has changed. @@ -180,6 +207,12 @@ class CONTENT_EXPORT PeerConnectionTracker // is not registered, the return value will be -1. int GetLocalIDForHandler(RTCPeerConnectionHandler* handler) const; + void TrackTransceiver(const char* callback_type_ending, + RTCPeerConnectionHandler* pc_handler, + PeerConnectionTracker::TransceiverUpdatedReason reason, + const blink::WebRTCRtpTransceiver& transceiver, + size_t transceiver_index); + // IPC Message handler for getting all stats. void OnGetAllStats(); @@ -211,7 +244,7 @@ class CONTENT_EXPORT PeerConnectionTracker // |value| - A json serialized string containing all the information for the // update event. void SendPeerConnectionUpdate(int local_id, - const char* callback_type, + const std::string& callback_type, const std::string& value); RenderThread* SendTarget(); diff --git a/chromium/content/renderer/media/webrtc/peer_connection_tracker_unittest.cc b/chromium/content/renderer/media/webrtc/peer_connection_tracker_unittest.cc index 647a6462d8c..84865974755 100644 --- a/chromium/content/renderer/media/webrtc/peer_connection_tracker_unittest.cc +++ b/chromium/content/renderer/media/webrtc/peer_connection_tracker_unittest.cc @@ -8,6 +8,7 @@ #include "content/common/media/peer_connection_tracker.mojom.h" #include "content/common/media/peer_connection_tracker_messages.h" #include "content/public/test/mock_render_thread.h" +#include "content/renderer/media/webrtc/fake_rtc_rtp_transceiver.h" #include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h" #include "content/renderer/media/webrtc/mock_web_rtc_peer_connection_handler_client.h" #include "content/renderer/media/webrtc/rtc_peer_connection_handler.h" @@ -18,11 +19,42 @@ #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" #include "third_party/blink/public/platform/web_media_constraints.h" #include "third_party/blink/public/platform/web_rtc_offer_options.h" +#include "third_party/blink/public/platform/web_rtc_rtp_receiver.h" +#include "third_party/blink/public/platform/web_rtc_rtp_sender.h" +#include "third_party/blink/public/platform/web_rtc_rtp_transceiver.h" using ::testing::_; namespace content { +const char* kDefaultTransceiverString = + "getTransceivers()[0]:{\n" + " mid:null,\n" + " sender:{\n" + " track:'senderTrackId',\n" + " streams:['senderStreamId'],\n" + " },\n" + " receiver:{\n" + " track:'receiverTrackId',\n" + " streams:['receiverStreamId'],\n" + " },\n" + " stopped:false,\n" + " direction:'sendonly',\n" + " currentDirection:null,\n" + "}"; + +const char* kDefaultSenderString = + "getSenders()[0]:{\n" + " track:'senderTrackId',\n" + " streams:['senderStreamId'],\n" + "}"; + +const char* kDefaultReceiverString = + "getReceivers()[0]:{\n" + " track:'receiverTrackId',\n" + " streams:['receiverStreamId'],\n" + "}"; + class MockPeerConnectionTrackerHost : public mojom::PeerConnectionTrackerHost { public: MockPeerConnectionTrackerHost() : binding_(this) {} @@ -47,7 +79,41 @@ class MockPeerConnectionTrackerHost : public mojom::PeerConnectionTrackerHost { mojo::AssociatedBinding<mojom::PeerConnectionTrackerHost> binding_; }; +// Creates a transceiver that is expected to be logged as +// |kDefaultTransceiverString|, |kDefaultSenderString| or +// |kDefaultReceiverString| depending on if |implementation_type| refers to a +// fully implemented, sender-only or receiver-only transceiver. +// +// This is used in unittests that don't care about the specific attributes of +// the transceiver. +std::unique_ptr<blink::WebRTCRtpTransceiver> CreateDefaultTransceiver( + blink::WebRTCRtpTransceiverImplementationType implementation_type) { + std::unique_ptr<blink::WebRTCRtpTransceiver> transceiver; + FakeRTCRtpSender sender("senderTrackId", {"senderStreamId"}); + FakeRTCRtpReceiver receiver("receiverTrackId", {"receiverStreamId"}); + if (implementation_type == + blink::WebRTCRtpTransceiverImplementationType::kFullTransceiver) { + transceiver = std::make_unique<FakeRTCRtpTransceiver>( + base::nullopt, std::move(sender), std::move(receiver), + false /* stopped */, + webrtc::RtpTransceiverDirection::kSendOnly /* direction */, + base::nullopt /* current_direction */); + } else if (implementation_type == + blink::WebRTCRtpTransceiverImplementationType::kPlanBSenderOnly) { + transceiver = std::make_unique<RTCRtpSenderOnlyTransceiver>( + std::make_unique<FakeRTCRtpSender>(sender)); + } else { + DCHECK_EQ( + implementation_type, + blink::WebRTCRtpTransceiverImplementationType::kPlanBReceiverOnly); + transceiver = std::make_unique<RTCRtpReceiverOnlyTransceiver>( + std::make_unique<FakeRTCRtpReceiver>(receiver)); + } + return transceiver; +} + namespace { + class MockSendTargetThread : public MockRenderThread { public: MOCK_METHOD1(OnAddPeerConnection, void(PeerConnectionInfo)); @@ -66,6 +132,7 @@ bool MockSendTargetThread::OnMessageReceived(const IPC::Message& msg) { return handled; } +// TODO(https://crbug.com/868868): Move this into a separate file. class MockPeerConnectionHandler : public RTCPeerConnectionHandler { public: MockPeerConnectionHandler() @@ -81,8 +148,30 @@ class MockPeerConnectionHandler : public RTCPeerConnectionHandler { }; class PeerConnectionTrackerTest : public ::testing::Test { - private: + public: + void CreateTrackerWithMocks() { + mock_host_.reset(new MockPeerConnectionTrackerHost()); + tracker_.reset( + new PeerConnectionTracker(mock_host_->CreateInterfacePtrAndBind())); + target_thread_.reset(new MockSendTargetThread()); + tracker_->OverrideSendTargetForTesting(target_thread_.get()); + } + + void CreateAndRegisterPeerConnectionHandler() { + mock_handler_.reset(new MockPeerConnectionHandler()); + EXPECT_CALL(*target_thread_, OnAddPeerConnection(_)); + tracker_->RegisterPeerConnection( + mock_handler_.get(), + webrtc::PeerConnectionInterface::RTCConfiguration(), + blink::WebMediaConstraints(), nullptr); + } + + protected: base::MessageLoop message_loop_; + std::unique_ptr<MockPeerConnectionTrackerHost> mock_host_; + std::unique_ptr<PeerConnectionTracker> tracker_; + std::unique_ptr<MockSendTargetThread> target_thread_; + std::unique_ptr<MockPeerConnectionHandler> mock_handler_; }; } // namespace @@ -92,47 +181,258 @@ TEST_F(PeerConnectionTrackerTest, CreatingObject) { } TEST_F(PeerConnectionTrackerTest, TrackCreateOffer) { - MockPeerConnectionTrackerHost mock_peer_connection_tracker_host; - PeerConnectionTracker tracker( - mock_peer_connection_tracker_host.CreateInterfacePtrAndBind()); - // mojom::PeerConnectionTrackerHostAssociatedPtr - // mock_peer_connection_tracker_host_ptr_ - // = mock_peer_connection_tracker_host.CreateInterfacePtrAndBind(); - // tracker.SetPeerConnectionTrackerHostForTesting(std::move(ptr1)); - // Note: blink::WebRTCOfferOptions is not mockable. So we can't write - // tests for anything but a null options parameter. + CreateTrackerWithMocks(); + CreateAndRegisterPeerConnectionHandler(); + // Note: blink::WebRTCOfferOptions is not mockable. So we can't write tests + // for anything but a null options parameter. blink::WebRTCOfferOptions options(0, 0, false, false); - // Initialization stuff. This can be separated into a test class. - MockPeerConnectionHandler pc_handler; - MockSendTargetThread target_thread; - webrtc::PeerConnectionInterface::RTCConfiguration config; - blink::WebMediaConstraints constraints; - tracker.OverrideSendTargetForTesting(&target_thread); - EXPECT_CALL(target_thread, OnAddPeerConnection(_)); - tracker.RegisterPeerConnection(&pc_handler, config, constraints, nullptr); - // Back to the test. - EXPECT_CALL(mock_peer_connection_tracker_host, + EXPECT_CALL(*mock_host_, UpdatePeerConnection( _, "createOffer", "options: {offerToReceiveVideo: 0, offerToReceiveAudio: 0, " "voiceActivityDetection: false, iceRestart: false}")); - tracker.TrackCreateOffer(&pc_handler, options); + tracker_->TrackCreateOffer(mock_handler_.get(), options); base::RunLoop().RunUntilIdle(); } TEST_F(PeerConnectionTrackerTest, OnSuspend) { - PeerConnectionTracker tracker; - // Initialization stuff. - MockPeerConnectionHandler pc_handler; - MockSendTargetThread target_thread; - webrtc::PeerConnectionInterface::RTCConfiguration config; - blink::WebMediaConstraints constraints; - tracker.OverrideSendTargetForTesting(&target_thread); - EXPECT_CALL(target_thread, OnAddPeerConnection(_)); - tracker.RegisterPeerConnection(&pc_handler, config, constraints, nullptr); - EXPECT_CALL(pc_handler, CloseClientPeerConnection()); + CreateTrackerWithMocks(); + CreateAndRegisterPeerConnectionHandler(); + EXPECT_CALL(*mock_handler_, CloseClientPeerConnection()); std::unique_ptr<IPC::Message> message(new PeerConnectionTracker_OnSuspend()); - tracker.OnControlMessageReceived(*message.get()); + tracker_->OnControlMessageReceived(*message.get()); +} + +TEST_F(PeerConnectionTrackerTest, AddTransceiverWithOptionalValuesPresent) { + CreateTrackerWithMocks(); + CreateAndRegisterPeerConnectionHandler(); + FakeRTCRtpTransceiver transceiver( + "midValue", FakeRTCRtpSender("senderTrackId", {"streamIdA", "streamIdB"}), + FakeRTCRtpReceiver("receiverTrackId", {"streamIdC"}), true /* stopped */, + webrtc::RtpTransceiverDirection::kSendRecv /* direction */, + webrtc::RtpTransceiverDirection::kInactive /* current_direction */); + std::string update_value; + EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, "transceiverAdded", _)) + .WillOnce(testing::SaveArg<2>(&update_value)); + tracker_->TrackAddTransceiver( + mock_handler_.get(), + PeerConnectionTracker::TransceiverUpdatedReason::kAddTrack, transceiver, + 0u); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ( + "Caused by: addTrack\n" + "\n" + "getTransceivers()[0]:{\n" + " mid:'midValue',\n" + " sender:{\n" + " track:'senderTrackId',\n" + " streams:['streamIdA','streamIdB'],\n" + " },\n" + " receiver:{\n" + " track:'receiverTrackId',\n" + " streams:['streamIdC'],\n" + " },\n" + " stopped:true,\n" + " direction:'sendrecv',\n" + " currentDirection:'inactive',\n" + "}", + update_value); +} + +TEST_F(PeerConnectionTrackerTest, AddTransceiverWithOptionalValuesNull) { + CreateTrackerWithMocks(); + CreateAndRegisterPeerConnectionHandler(); + FakeRTCRtpTransceiver transceiver( + base::nullopt, FakeRTCRtpSender(base::nullopt, {}), + FakeRTCRtpReceiver("receiverTrackId", {}), false /* stopped */, + webrtc::RtpTransceiverDirection::kInactive /* direction */, + base::nullopt /* current_direction */); + std::string update_value; + EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, "transceiverAdded", _)) + .WillOnce(testing::SaveArg<2>(&update_value)); + tracker_->TrackAddTransceiver( + mock_handler_.get(), + PeerConnectionTracker::TransceiverUpdatedReason::kAddTransceiver, + transceiver, 1u); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ( + "Caused by: addTransceiver\n" + "\n" + "getTransceivers()[1]:{\n" + " mid:null,\n" + " sender:{\n" + " track:null,\n" + " streams:[],\n" + " },\n" + " receiver:{\n" + " track:'receiverTrackId',\n" + " streams:[],\n" + " },\n" + " stopped:false,\n" + " direction:'inactive',\n" + " currentDirection:null,\n" + "}", + update_value); +} + +TEST_F(PeerConnectionTrackerTest, ModifyTransceiver) { + CreateTrackerWithMocks(); + CreateAndRegisterPeerConnectionHandler(); + auto transceiver = CreateDefaultTransceiver( + blink::WebRTCRtpTransceiverImplementationType::kFullTransceiver); + std::string update_value; + EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, "transceiverModified", _)) + .WillOnce(testing::SaveArg<2>(&update_value)); + tracker_->TrackModifyTransceiver( + mock_handler_.get(), + PeerConnectionTracker::TransceiverUpdatedReason::kSetLocalDescription, + *transceiver, 0u); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ( + "Caused by: setLocalDescription\n" + "\n" + + std::string(kDefaultTransceiverString), + update_value); +} + +TEST_F(PeerConnectionTrackerTest, RemoveTransceiver) { + CreateTrackerWithMocks(); + CreateAndRegisterPeerConnectionHandler(); + auto transceiver = CreateDefaultTransceiver( + blink::WebRTCRtpTransceiverImplementationType::kFullTransceiver); + std::string update_value; + EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, "transceiverRemoved", _)) + .WillOnce(testing::SaveArg<2>(&update_value)); + tracker_->TrackRemoveTransceiver( + mock_handler_.get(), + PeerConnectionTracker::TransceiverUpdatedReason::kRemoveTrack, + *transceiver, 0u); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ( + "Caused by: removeTrack\n" + "\n" + + std::string(kDefaultTransceiverString), + update_value); +} + +TEST_F(PeerConnectionTrackerTest, AddSender) { + CreateTrackerWithMocks(); + CreateAndRegisterPeerConnectionHandler(); + auto sender_only = CreateDefaultTransceiver( + blink::WebRTCRtpTransceiverImplementationType::kPlanBSenderOnly); + std::string update_value; + EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, "senderAdded", _)) + .WillOnce(testing::SaveArg<2>(&update_value)); + tracker_->TrackAddTransceiver( + mock_handler_.get(), + PeerConnectionTracker::TransceiverUpdatedReason::kSetLocalDescription, + *sender_only, 0u); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ( + "Caused by: setLocalDescription\n" + "\n" + + std::string(kDefaultSenderString), + update_value); +} + +TEST_F(PeerConnectionTrackerTest, ModifySender) { + CreateTrackerWithMocks(); + CreateAndRegisterPeerConnectionHandler(); + auto sender_only = CreateDefaultTransceiver( + blink::WebRTCRtpTransceiverImplementationType::kPlanBSenderOnly); + std::string update_value; + EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, "senderModified", _)) + .WillOnce(testing::SaveArg<2>(&update_value)); + tracker_->TrackModifyTransceiver( + mock_handler_.get(), + PeerConnectionTracker::TransceiverUpdatedReason::kSetRemoteDescription, + *sender_only, 0u); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ( + "Caused by: setRemoteDescription\n" + "\n" + + std::string(kDefaultSenderString), + update_value); +} + +TEST_F(PeerConnectionTrackerTest, RemoveSender) { + CreateTrackerWithMocks(); + CreateAndRegisterPeerConnectionHandler(); + auto sender_only = CreateDefaultTransceiver( + blink::WebRTCRtpTransceiverImplementationType::kPlanBSenderOnly); + std::string update_value; + EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, "senderRemoved", _)) + .WillOnce(testing::SaveArg<2>(&update_value)); + tracker_->TrackRemoveTransceiver( + mock_handler_.get(), + PeerConnectionTracker::TransceiverUpdatedReason::kSetRemoteDescription, + *sender_only, 0u); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ( + "Caused by: setRemoteDescription\n" + "\n" + + std::string(kDefaultSenderString), + update_value); +} + +TEST_F(PeerConnectionTrackerTest, AddReceiver) { + CreateTrackerWithMocks(); + CreateAndRegisterPeerConnectionHandler(); + auto receiver_only = CreateDefaultTransceiver( + blink::WebRTCRtpTransceiverImplementationType::kPlanBReceiverOnly); + std::string update_value; + EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, "receiverAdded", _)) + .WillOnce(testing::SaveArg<2>(&update_value)); + tracker_->TrackAddTransceiver( + mock_handler_.get(), + PeerConnectionTracker::TransceiverUpdatedReason::kSetRemoteDescription, + *receiver_only, 0u); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ( + "Caused by: setRemoteDescription\n" + "\n" + + std::string(kDefaultReceiverString), + update_value); +} + +TEST_F(PeerConnectionTrackerTest, ModifyReceiver) { + CreateTrackerWithMocks(); + CreateAndRegisterPeerConnectionHandler(); + auto receiver_only = CreateDefaultTransceiver( + blink::WebRTCRtpTransceiverImplementationType::kPlanBReceiverOnly); + std::string update_value; + EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, "receiverModified", _)) + .WillOnce(testing::SaveArg<2>(&update_value)); + tracker_->TrackModifyTransceiver( + mock_handler_.get(), + PeerConnectionTracker::TransceiverUpdatedReason::kSetRemoteDescription, + *receiver_only, 0u); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ( + "Caused by: setRemoteDescription\n" + "\n" + + std::string(kDefaultReceiverString), + update_value); +} + +TEST_F(PeerConnectionTrackerTest, RemoveReceiver) { + CreateTrackerWithMocks(); + CreateAndRegisterPeerConnectionHandler(); + auto receiver_only = CreateDefaultTransceiver( + blink::WebRTCRtpTransceiverImplementationType::kPlanBReceiverOnly); + std::string update_value; + EXPECT_CALL(*mock_host_, UpdatePeerConnection(_, "receiverRemoved", _)) + .WillOnce(testing::SaveArg<2>(&update_value)); + tracker_->TrackRemoveTransceiver( + mock_handler_.get(), + PeerConnectionTracker::TransceiverUpdatedReason::kSetRemoteDescription, + *receiver_only, 0u); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ( + "Caused by: setRemoteDescription\n" + "\n" + + std::string(kDefaultReceiverString), + update_value); } // TODO(hta): Write tests for the other tracking functions. diff --git a/chromium/content/renderer/media/webrtc/rtc_certificate_generator.cc b/chromium/content/renderer/media/webrtc/rtc_certificate_generator.cc index 8eb3a817560..4f5ff473c80 100644 --- a/chromium/content/renderer/media/webrtc/rtc_certificate_generator.cc +++ b/chromium/content/renderer/media/webrtc/rtc_certificate_generator.cc @@ -39,7 +39,7 @@ rtc::KeyParams WebRTCKeyParamsToKeyParams( } // A certificate generation request spawned by -// |RTCCertificateGenerator::generateCertificateWithOptionalExpiration|. This +// |GenerateCertificateWithOptionalExpiration|. This // is handled by a separate class so that reference counting can keep the // request alive independently of the |RTCCertificateGenerator| that spawned it. class RTCCertificateGeneratorRequest @@ -60,7 +60,7 @@ class RTCCertificateGeneratorRequest void GenerateCertificateAsync( const blink::WebRTCKeyParams& key_params, - const rtc::Optional<uint64_t>& expires_ms, + const absl::optional<uint64_t>& expires_ms, std::unique_ptr<blink::WebRTCCertificateCallback> observer) { DCHECK(main_thread_->BelongsToCurrentThread()); DCHECK(observer); @@ -80,7 +80,7 @@ class RTCCertificateGeneratorRequest void GenerateCertificateOnWorkerThread( const blink::WebRTCKeyParams key_params, - const rtc::Optional<uint64_t> expires_ms, + const absl::optional<uint64_t> expires_ms, CertificateCallbackPtr observer) { DCHECK(worker_thread_->BelongsToCurrentThread()); @@ -114,41 +114,40 @@ class RTCCertificateGeneratorRequest const scoped_refptr<base::SingleThreadTaskRunner> worker_thread_; }; -} // namespace - -void RTCCertificateGenerator::GenerateCertificate( +void GenerateCertificateWithOptionalExpiration( const blink::WebRTCKeyParams& key_params, + const absl::optional<uint64_t>& expires_ms, std::unique_ptr<blink::WebRTCCertificateCallback> observer, scoped_refptr<base::SingleThreadTaskRunner> task_runner) { - generateCertificateWithOptionalExpiration( - key_params, rtc::Optional<uint64_t>(), std::move(observer), task_runner); + DCHECK(WebRTCKeyParamsToKeyParams(key_params).IsValid()); + PeerConnectionDependencyFactory* pc_dependency_factory = + RenderThreadImpl::current()->GetPeerConnectionDependencyFactory(); + pc_dependency_factory->EnsureInitialized(); + + scoped_refptr<RTCCertificateGeneratorRequest> request = + new RTCCertificateGeneratorRequest( + task_runner, pc_dependency_factory->GetWebRtcWorkerThread()); + request->GenerateCertificateAsync(key_params, expires_ms, + std::move(observer)); } -void RTCCertificateGenerator::GenerateCertificateWithExpiration( +} // namespace + +void RTCCertificateGenerator::GenerateCertificate( const blink::WebRTCKeyParams& key_params, - uint64_t expires_ms, std::unique_ptr<blink::WebRTCCertificateCallback> observer, scoped_refptr<base::SingleThreadTaskRunner> task_runner) { - generateCertificateWithOptionalExpiration(key_params, - rtc::Optional<uint64_t>(expires_ms), + GenerateCertificateWithOptionalExpiration(key_params, absl::nullopt, std::move(observer), task_runner); } -void RTCCertificateGenerator::generateCertificateWithOptionalExpiration( +void RTCCertificateGenerator::GenerateCertificateWithExpiration( const blink::WebRTCKeyParams& key_params, - const rtc::Optional<uint64_t>& expires_ms, + uint64_t expires_ms, std::unique_ptr<blink::WebRTCCertificateCallback> observer, scoped_refptr<base::SingleThreadTaskRunner> task_runner) { - DCHECK(IsSupportedKeyParams(key_params)); - PeerConnectionDependencyFactory* pc_dependency_factory = - RenderThreadImpl::current()->GetPeerConnectionDependencyFactory(); - pc_dependency_factory->EnsureInitialized(); - - scoped_refptr<RTCCertificateGeneratorRequest> request = - new RTCCertificateGeneratorRequest( - task_runner, pc_dependency_factory->GetWebRtcWorkerThread()); - request->GenerateCertificateAsync( - key_params, expires_ms, std::move(observer)); + GenerateCertificateWithOptionalExpiration(key_params, expires_ms, + std::move(observer), task_runner); } bool RTCCertificateGenerator::IsSupportedKeyParams( diff --git a/chromium/content/renderer/media/webrtc/rtc_certificate_generator.h b/chromium/content/renderer/media/webrtc/rtc_certificate_generator.h index 248cd21846c..5e29c7f62d4 100644 --- a/chromium/content/renderer/media/webrtc/rtc_certificate_generator.h +++ b/chromium/content/renderer/media/webrtc/rtc_certificate_generator.h @@ -10,7 +10,6 @@ #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/optional.h" namespace content { @@ -38,12 +37,6 @@ class RTCCertificateGenerator : public blink::WebRTCCertificateGenerator { blink::WebString pem_certificate) override; private: - void generateCertificateWithOptionalExpiration( - const blink::WebRTCKeyParams& key_params, - const rtc::Optional<uint64_t>& expires_ms, - std::unique_ptr<blink::WebRTCCertificateCallback> observer, - scoped_refptr<base::SingleThreadTaskRunner> task_runner); - DISALLOW_COPY_AND_ASSIGN(RTCCertificateGenerator); }; 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 e972ef0a8dd..64bf108735c 100644 --- a/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.cc +++ b/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.cc @@ -18,6 +18,7 @@ #include "base/logging.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" +#include "base/stl_util.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_task_runner_handle.h" @@ -36,8 +37,7 @@ #include "content/renderer/media/webrtc/rtc_event_log_output_sink_proxy.h" #include "content/renderer/media/webrtc/rtc_stats.h" #include "content/renderer/media/webrtc/webrtc_audio_device_impl.h" -#include "content/renderer/media/webrtc/webrtc_media_stream_adapter.h" -#include "content/renderer/media/webrtc/webrtc_set_remote_description_observer.h" +#include "content/renderer/media/webrtc/webrtc_set_description_observer.h" #include "content/renderer/media/webrtc/webrtc_uma_histograms.h" #include "content/renderer/render_thread_impl.h" #include "media/base/media_switches.h" @@ -49,6 +49,7 @@ #include "third_party/blink/public/platform/web_rtc_legacy_stats.h" #include "third_party/blink/public/platform/web_rtc_offer_options.h" #include "third_party/blink/public/platform/web_rtc_rtp_sender.h" +#include "third_party/blink/public/platform/web_rtc_rtp_transceiver.h" #include "third_party/blink/public/platform/web_rtc_session_description.h" #include "third_party/blink/public/platform/web_rtc_session_description_request.h" #include "third_party/blink/public/platform/web_rtc_void_request.h" @@ -119,30 +120,6 @@ GetWebKitIceConnectionState( } } -blink::WebRTCPeerConnectionHandlerClient::SignalingState -GetWebKitSignalingState(webrtc::PeerConnectionInterface::SignalingState state) { - using blink::WebRTCPeerConnectionHandlerClient; - switch (state) { - case webrtc::PeerConnectionInterface::kStable: - return WebRTCPeerConnectionHandlerClient::kSignalingStateStable; - case webrtc::PeerConnectionInterface::kHaveLocalOffer: - return WebRTCPeerConnectionHandlerClient::kSignalingStateHaveLocalOffer; - case webrtc::PeerConnectionInterface::kHaveLocalPrAnswer: - return WebRTCPeerConnectionHandlerClient:: - kSignalingStateHaveLocalPrAnswer; - case webrtc::PeerConnectionInterface::kHaveRemoteOffer: - return WebRTCPeerConnectionHandlerClient::kSignalingStateHaveRemoteOffer; - case webrtc::PeerConnectionInterface::kHaveRemotePrAnswer: - return WebRTCPeerConnectionHandlerClient:: - kSignalingStateHaveRemotePrAnswer; - case webrtc::PeerConnectionInterface::kClosed: - return WebRTCPeerConnectionHandlerClient::kSignalingStateClosed; - default: - NOTREACHED(); - return WebRTCPeerConnectionHandlerClient::kSignalingStateClosed; - } -} - blink::WebRTCSessionDescription CreateWebKitSessionDescription( const std::string& sdp, const std::string& type) { blink::WebRTCSessionDescription description; @@ -257,14 +234,13 @@ void GetNativeRtcConfiguration( } switch (blink_config.sdp_semantics) { - case blink::WebRTCSdpSemantics::kDefault: case blink::WebRTCSdpSemantics::kPlanB: webrtc_config->sdp_semantics = webrtc::SdpSemantics::kPlanB; break; case blink::WebRTCSdpSemantics::kUnifiedPlan: webrtc_config->sdp_semantics = webrtc::SdpSemantics::kUnifiedPlan; break; - default: + case blink::WebRTCSdpSemantics::kDefault: NOTREACHED(); } @@ -279,6 +255,16 @@ void GetNativeRtcConfiguration( 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) { + bool value; + if (GetConstraintValueAsBoolean(constraints, picker, &value)) { + return absl::optional<bool>(value); + } + return absl::nullopt; +} + void CopyConstraintsIntoRtcConfiguration( const blink::WebMediaConstraints constraints, webrtc::PeerConnectionInterface::RTCConfiguration* configuration) { @@ -329,7 +315,7 @@ void CopyConstraintsIntoRtcConfiguration( constraints, &blink::WebMediaTrackConstraintSet::goog_screencast_min_bitrate, &rate)) { - configuration->screencast_min_bitrate = rtc::Optional<int>(rate); + configuration->screencast_min_bitrate = rate; } configuration->combined_audio_video_bwe = ConstraintToOptional( constraints, @@ -338,42 +324,6 @@ void CopyConstraintsIntoRtcConfiguration( constraints, &blink::WebMediaTrackConstraintSet::enable_dtls_srtp); } -class SessionDescriptionRequestTracker { - public: - SessionDescriptionRequestTracker( - const base::WeakPtr<RTCPeerConnectionHandler>& handler, - const base::WeakPtr<PeerConnectionTracker>& tracker, - PeerConnectionTracker::Action action) - : handler_(handler), tracker_(tracker), action_(action) {} - - void TrackOnSuccess(const webrtc::SessionDescriptionInterface* desc) { - DCHECK(thread_checker_.CalledOnValidThread()); - if (tracker_ && handler_) { - std::string value; - if (desc) { - desc->ToString(&value); - value = "type: " + desc->type() + ", sdp: " + value; - } - tracker_->TrackSessionDescriptionCallback( - handler_.get(), action_, "OnSuccess", value); - } - } - - void TrackOnFailure(const webrtc::RTCError& error) { - DCHECK(thread_checker_.CalledOnValidThread()); - if (handler_ && tracker_) { - tracker_->TrackSessionDescriptionCallback(handler_.get(), action_, - "OnFailure", error.message()); - } - } - - private: - const base::WeakPtr<RTCPeerConnectionHandler> handler_; - const base::WeakPtr<PeerConnectionTracker> tracker_; - PeerConnectionTracker::Action action_; - base::ThreadChecker thread_checker_; -}; - // Class mapping responses from calls to libjingle CreateOffer/Answer and // the blink::WebRTCSessionDescriptionRequest. class CreateSessionDescriptionRequest @@ -387,8 +337,9 @@ class CreateSessionDescriptionRequest PeerConnectionTracker::Action action) : main_thread_(main_thread), webkit_request_(request), - tracker_(handler, tracker, action) { - } + handler_(handler), + tracker_(tracker), + action_(action) {} void OnSuccess(webrtc::SessionDescriptionInterface* desc) override { if (!main_thread_->BelongsToCurrentThread()) { @@ -398,7 +349,15 @@ class CreateSessionDescriptionRequest return; } - tracker_.TrackOnSuccess(desc); + if (tracker_ && handler_) { + std::string value; + if (desc) { + desc->ToString(&value); + value = "type: " + desc->type() + ", sdp: " + value; + } + tracker_->TrackSessionDescriptionCallback(handler_.get(), action_, + "OnSuccess", value); + } webkit_request_.RequestSucceeded(CreateWebKitSessionDescription(desc)); webkit_request_.Reset(); delete desc; @@ -411,7 +370,10 @@ class CreateSessionDescriptionRequest return; } - tracker_.TrackOnFailure(error); + if (handler_ && tracker_) { + tracker_->TrackSessionDescriptionCallback(handler_.get(), action_, + "OnFailure", error.message()); + } // TODO(hta): Convert CreateSessionDescriptionRequest.OnFailure webkit_request_.RequestFailed(error); webkit_request_.Reset(); @@ -430,62 +392,9 @@ class CreateSessionDescriptionRequest const scoped_refptr<base::SingleThreadTaskRunner> main_thread_; blink::WebRTCSessionDescriptionRequest webkit_request_; - SessionDescriptionRequestTracker tracker_; -}; - -// Class mapping responses from calls to libjingle SetLocalDescription and a -// blink::WebRTCVoidRequest. -class SetLocalDescriptionRequest - : public webrtc::SetSessionDescriptionObserver { - public: - explicit SetLocalDescriptionRequest( - const scoped_refptr<base::SingleThreadTaskRunner>& main_thread, - const blink::WebRTCVoidRequest& request, - const base::WeakPtr<RTCPeerConnectionHandler>& handler, - const base::WeakPtr<PeerConnectionTracker>& tracker, - PeerConnectionTracker::Action action) - : main_thread_(main_thread), - webkit_request_(request), - tracker_(handler, tracker, action) {} - - void OnSuccess() override { - if (!main_thread_->BelongsToCurrentThread()) { - main_thread_->PostTask( - FROM_HERE, - base::BindOnce(&SetLocalDescriptionRequest::OnSuccess, this)); - return; - } - tracker_.TrackOnSuccess(nullptr); - webkit_request_.RequestSucceeded(); - webkit_request_.Reset(); - } - void OnFailure(webrtc::RTCError error) override { - if (!main_thread_->BelongsToCurrentThread()) { - main_thread_->PostTask( - FROM_HERE, base::BindOnce(&SetLocalDescriptionRequest::OnFailure, - this, std::move(error))); - return; - } - tracker_.TrackOnFailure(error); - webkit_request_.RequestFailed(error); - webkit_request_.Reset(); - } - - protected: - ~SetLocalDescriptionRequest() override { - // This object is reference counted and its callback methods |OnSuccess| and - // |OnFailure| will be invoked on libjingle's signaling thread and posted to - // the main thread. Since the main thread may complete before the signaling - // thread has deferenced this object there is no guarantee that this object - // is destructed on the main thread. - DLOG_IF(ERROR, !webkit_request_.IsNull()) - << "SetLocalDescriptionRequest not completed. Shutting down?"; - } - - private: - const scoped_refptr<base::SingleThreadTaskRunner> main_thread_; - blink::WebRTCVoidRequest webkit_request_; - SessionDescriptionRequestTracker tracker_; + const base::WeakPtr<RTCPeerConnectionHandler> handler_; + const base::WeakPtr<PeerConnectionTracker> tracker_; + PeerConnectionTracker::Action action_; }; blink::WebRTCLegacyStatsMemberType @@ -704,139 +613,6 @@ void GetRTCStatsOnSignalingThread( RTCStatsCollectorCallbackImpl::Create(main_thread, std::move(callback))); } -class PeerConnectionUMAObserver : public webrtc::UMAObserver { - public: - PeerConnectionUMAObserver() {} - ~PeerConnectionUMAObserver() override {} - void IncrementEnumCounter(webrtc::PeerConnectionEnumCounterType counter_type, - int counter, - int counter_max) override { - switch (counter_type) { - case webrtc::kEnumCounterAddressFamily: - UMA_HISTOGRAM_EXACT_LINEAR("WebRTC.PeerConnection.IPMetrics", counter, - counter_max); - break; - case webrtc::kEnumCounterIceCandidatePairTypeUdp: - UMA_HISTOGRAM_EXACT_LINEAR( - "WebRTC.PeerConnection.CandidatePairType_UDP", counter, - counter_max); - break; - case webrtc::kEnumCounterIceCandidatePairTypeTcp: - UMA_HISTOGRAM_EXACT_LINEAR( - "WebRTC.PeerConnection.CandidatePairType_TCP", counter, - counter_max); - break; - case webrtc::kEnumCounterDtlsHandshakeError: - UMA_HISTOGRAM_EXACT_LINEAR("WebRTC.PeerConnection.DtlsHandshakeError", - counter, counter_max); - break; - case webrtc::kEnumCounterIceRestart: - UMA_HISTOGRAM_EXACT_LINEAR("WebRTC.PeerConnection.IceRestartState", - counter, counter_max); - break; - case webrtc::kEnumCounterIceRegathering: - UMA_HISTOGRAM_EXACT_LINEAR("WebRTC.PeerConnection.IceRegatheringReason", - counter, counter_max); - break; - case webrtc::kEnumCounterKeyProtocol: - UMA_HISTOGRAM_ENUMERATION( - "WebRTC.PeerConnection.KeyProtocol", - static_cast<webrtc::KeyExchangeProtocolType>(counter), - webrtc::kEnumCounterKeyProtocolMax); - break; - case webrtc::kEnumCounterSdpSemanticNegotiated: - UMA_HISTOGRAM_ENUMERATION( - "WebRTC.PeerConnection.SdpSemanticNegotiated", - static_cast<webrtc::SdpSemanticNegotiated>(counter), - webrtc::kSdpSemanticNegotiatedMax); - break; - case webrtc::kEnumCounterKeyProtocolMediaType: - UMA_HISTOGRAM_ENUMERATION( - "WebRTC.PeerConnection.KeyProtocolByMedia", - static_cast<webrtc::KeyExchangeProtocolMedia>(counter), - webrtc::kEnumCounterKeyProtocolMediaTypeMax); - break; - case webrtc::kEnumCounterSdpFormatReceived: - UMA_HISTOGRAM_ENUMERATION( - "WebRTC.PeerConnection.SdpFormatReceived", - static_cast<webrtc::SdpFormatReceived>(counter), - webrtc::kSdpFormatReceivedMax); - break; - default: - // The default clause is expected to be reached when new enum types are - // added. - break; - } - } - - void IncrementSparseEnumCounter( - webrtc::PeerConnectionEnumCounterType counter_type, - int counter) override { - switch (counter_type) { - case webrtc::kEnumCounterAudioSrtpCipher: - base::UmaHistogramSparse("WebRTC.PeerConnection.SrtpCryptoSuite.Audio", - counter); - break; - case webrtc::kEnumCounterAudioSslCipher: - base::UmaHistogramSparse("WebRTC.PeerConnection.SslCipherSuite.Audio", - counter); - break; - case webrtc::kEnumCounterVideoSrtpCipher: - base::UmaHistogramSparse("WebRTC.PeerConnection.SrtpCryptoSuite.Video", - counter); - break; - case webrtc::kEnumCounterVideoSslCipher: - base::UmaHistogramSparse("WebRTC.PeerConnection.SslCipherSuite.Video", - counter); - break; - case webrtc::kEnumCounterDataSrtpCipher: - base::UmaHistogramSparse("WebRTC.PeerConnection.SrtpCryptoSuite.Data", - counter); - break; - case webrtc::kEnumCounterDataSslCipher: - base::UmaHistogramSparse("WebRTC.PeerConnection.SslCipherSuite.Data", - counter); - break; - case webrtc::kEnumCounterSrtpUnprotectError: - base::UmaHistogramSparse("WebRTC.PeerConnection.SrtpUnprotectError", - counter); - break; - case webrtc::kEnumCounterSrtcpUnprotectError: - base::UmaHistogramSparse("WebRTC.PeerConnection.SrtcpUnprotectError", - counter); - break; - default: - // The default clause is expected to reach when new enum types are - // added. - break; - } - } - - void AddHistogramSample(webrtc::PeerConnectionUMAMetricsName type, - int value) override { - // Runs on libjingle's signaling thread. - switch (type) { - case webrtc::kTimeToConnect: - UMA_HISTOGRAM_MEDIUM_TIMES( - "WebRTC.PeerConnection.TimeToConnect", - base::TimeDelta::FromMilliseconds(value)); - break; - case webrtc::kNetworkInterfaces_IPv4: - UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv4Interfaces", - value); - break; - case webrtc::kNetworkInterfaces_IPv6: - UMA_HISTOGRAM_COUNTS_100("WebRTC.PeerConnection.IPv6Interfaces", - value); - break; - default: - // The default clause is expected to reach when new enum types are - // added. - break; - } - } -}; - void ConvertOfferOptionsToWebrtcOfferOptions( const blink::WebRTCOfferOptions& options, webrtc::PeerConnectionInterface::RTCOfferAnswerOptions* output) { @@ -890,15 +666,14 @@ std::set<RTCPeerConnectionHandler*>* GetPeerConnectionHandlers() { return handlers; } -// Counts the number of senders that have |web_stream| as an associated stream. +// Counts the number of senders that have |stream_id| as an associated stream. size_t GetLocalStreamUsageCount( const std::vector<std::unique_ptr<RTCRtpSender>>& rtp_senders, - const blink::WebMediaStream& web_stream) { + const std::string stream_id) { size_t usage_count = 0; for (const auto& sender : rtp_senders) { - for (const auto& stream_ref : sender->stream_refs()) { - if (stream_ref->adapter().web_stream().UniqueId() == - web_stream.UniqueId()) { + for (const auto& sender_stream_id : sender->state().stream_ids()) { + if (sender_stream_id == stream_id) { ++usage_count; break; } @@ -907,17 +682,16 @@ size_t GetLocalStreamUsageCount( return usage_count; } -// Counts the number of receivers that have |webrtc_stream| as an associated -// stream. -size_t GetRemoteStreamUsageCount( - const std::map<uintptr_t, std::unique_ptr<RTCRtpReceiver>>& rtp_receivers, - const webrtc::MediaStreamInterface* webrtc_stream) { - size_t usage_count = 0; - for (const auto& receiver_entry : rtp_receivers) { - if (receiver_entry.second->HasStream(webrtc_stream)) - ++usage_count; +bool IsRemoteStream( + const std::vector<std::unique_ptr<RTCRtpReceiver>>& rtp_receivers, + const std::string& stream_id) { + for (const auto& receiver : rtp_receivers) { + for (const auto& receiver_stream_id : receiver->state().stream_ids()) { + if (stream_id == receiver_stream_id) + return true; + } } - return usage_count; + return false; } enum SdpSemanticRequested { @@ -941,6 +715,13 @@ SdpSemanticRequested GetSdpSemanticRequested( return kSdpSemanticRequestedDefault; } +MediaStreamTrackMetrics::Kind MediaStreamTrackMetricsKind( + const blink::WebMediaStreamTrack& track) { + return track.Source().GetType() == blink::WebMediaStreamSource::kTypeAudio + ? MediaStreamTrackMetrics::Kind::kAudio + : MediaStreamTrackMetrics::Kind::kVideo; +} + } // namespace // Implementation of LocalRTCStatsRequest. @@ -978,175 +759,146 @@ void LocalRTCStatsResponse::addStats(const blink::WebRTCLegacyStats& stats) { impl_.AddStats(stats); } -// Processes the resulting state changes of a SetRemoteDescription call. -class RTCPeerConnectionHandler::WebRtcSetRemoteDescriptionObserverImpl - : public WebRtcSetRemoteDescriptionObserver { +// Processes the resulting state changes of a SetLocalDescription() or +// SetRemoteDescription() call. +class RTCPeerConnectionHandler::WebRtcSetDescriptionObserverImpl + : public WebRtcSetDescriptionObserver { public: - WebRtcSetRemoteDescriptionObserverImpl( + WebRtcSetDescriptionObserverImpl( base::WeakPtr<RTCPeerConnectionHandler> handler, blink::WebRTCVoidRequest web_request, base::WeakPtr<PeerConnectionTracker> tracker, - scoped_refptr<base::SingleThreadTaskRunner> task_runner) + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + PeerConnectionTracker::Action action, + blink::WebRTCSdpSemantics sdp_semantics) : handler_(handler), main_thread_(task_runner), web_request_(web_request), - tracker_(tracker) {} + tracker_(tracker), + action_(action), + sdp_semantics_(sdp_semantics) { + DCHECK(sdp_semantics_ == blink::WebRTCSdpSemantics::kPlanB || + sdp_semantics_ == blink::WebRTCSdpSemantics::kUnifiedPlan); + } - void OnSetRemoteDescriptionComplete( - webrtc::RTCErrorOr<WebRtcSetRemoteDescriptionObserver::States> - states_or_error) override { - if (!states_or_error.ok()) { - auto& error = states_or_error.error(); + void OnSetDescriptionComplete( + webrtc::RTCError error, + WebRtcSetDescriptionObserver::States states) override { + if (!error.ok()) { if (tracker_ && handler_) { - tracker_->TrackSessionDescriptionCallback( - handler_.get(), - PeerConnectionTracker::ACTION_SET_REMOTE_DESCRIPTION, "OnFailure", - error.message()); + tracker_->TrackSessionDescriptionCallback(handler_.get(), action_, + "OnFailure", error.message()); } web_request_.RequestFailed(error); web_request_.Reset(); return; } - auto& states = states_or_error.value(); if (handler_) { - // Determine which receivers have been removed before processing the - // removal as to not invalidate the iterator. - std::vector<RTCRtpReceiver*> removed_receivers; - for (auto it = handler_->rtp_receivers_.begin(); - it != handler_->rtp_receivers_.end(); ++it) { - if (ReceiverWasRemoved(*it->second, states.receiver_states)) - removed_receivers.push_back(it->second.get()); - } - - // Update stream states (which tracks belong to which streams). - for (auto& stream_state : GetStreamStates(states, removed_receivers)) { - stream_state.stream_ref->adapter().SetTracks( - std::move(stream_state.track_refs)); + handler_->OnSignalingChange(states.signaling_state); + + // Process the rest of the state changes differently depending on SDP + // semantics. + if (sdp_semantics_ == blink::WebRTCSdpSemantics::kPlanB) { + ProcessStateChangesPlanB(std::move(states)); + } else { + DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kUnifiedPlan); + ProcessStateChangesUnifiedPlan(std::move(states)); } - // Process the addition of remote receivers/tracks. - for (auto& receiver_state : states.receiver_states) { - if (ReceiverWasAdded(receiver_state)) { - handler_->OnAddRemoteTrack(receiver_state.receiver, - std::move(receiver_state.track_ref), - std::move(receiver_state.stream_refs)); - } - } - // Process the removal of remote receivers/tracks. - for (auto* removed_receiver : removed_receivers) - handler_->OnRemoveRemoteTrack(removed_receiver->webrtc_receiver()); if (tracker_) { - tracker_->TrackSessionDescriptionCallback( - handler_.get(), - PeerConnectionTracker::ACTION_SET_REMOTE_DESCRIPTION, "OnSuccess", - ""); + tracker_->TrackSessionDescriptionCallback(handler_.get(), action_, + "OnSuccess", ""); } } - // Resolve the promise in a post to ensure any events scheduled for - // dispatching will have fired by the time the promise is resolved. - // TODO(hbos): Don't schedule/post to fire events/resolve the promise. - // Instead, do it all synchronously. This must happen as the last step - // before returning so that all effects of SRD have occurred when the event - // executes. https://crbug.com/788558 - main_thread_->PostTask( - FROM_HERE, - base::BindOnce( - &RTCPeerConnectionHandler::WebRtcSetRemoteDescriptionObserverImpl:: - ResolvePromise, - this)); + if (action_ == PeerConnectionTracker::ACTION_SET_REMOTE_DESCRIPTION) { + // Resolve the promise in a post to ensure any events scheduled for + // dispatching will have fired by the time the promise is resolved. + // TODO(hbos): Don't schedule/post to fire events/resolve the promise. + // Instead, do it all synchronously. This must happen as the last step + // before returning so that all effects of SRD have occurred when the + // event executes. https://crbug.com/788558 + main_thread_->PostTask( + FROM_HERE, + base::BindOnce(&RTCPeerConnectionHandler:: + WebRtcSetDescriptionObserverImpl::ResolvePromise, + this)); + } else { + // Resolve promise immediately if we can. https://crbug.com/788558 still + // needs to be addressed for "setLocalDescription(answer)" rejecting a + // transceiver in Unified Plan, but this is a minor edge-case. + ResolvePromise(); + } } private: - ~WebRtcSetRemoteDescriptionObserverImpl() override {} - - // Describes which tracks belong to a stream in terms of AdapterRefs. - struct StreamState { - StreamState( - std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> stream_ref) - : stream_ref(std::move(stream_ref)) {} - - std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> stream_ref; - std::vector<std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>> - track_refs; - }; + ~WebRtcSetDescriptionObserverImpl() override {} void ResolvePromise() { web_request_.RequestSucceeded(); web_request_.Reset(); } - bool ReceiverWasAdded(const WebRtcReceiverState& receiver_state) { - return handler_->rtp_receivers_.find( - RTCRtpReceiver::getId(receiver_state.receiver.get())) == - handler_->rtp_receivers_.end(); + void ProcessStateChangesPlanB(WebRtcSetDescriptionObserver::States states) { + DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kPlanB); + // Determine which receivers have been removed before processing the + // removal as to not invalidate the iterator. + std::vector<RTCRtpReceiver*> removed_receivers; + for (auto it = handler_->rtp_receivers_.begin(); + it != handler_->rtp_receivers_.end(); ++it) { + if (ReceiverWasRemoved(*(*it), states.transceiver_states)) + removed_receivers.push_back(it->get()); + } + + // Process the addition of remote receivers/tracks. + for (auto& transceiver_state : states.transceiver_states) { + if (ReceiverWasAdded(transceiver_state)) { + handler_->OnAddReceiverPlanB(transceiver_state.MoveReceiverState()); + } + } + // Process the removal of remote receivers/tracks. + for (auto* removed_receiver : removed_receivers) { + handler_->OnRemoveReceiverPlanB(RTCRtpReceiver::getId( + removed_receiver->state().webrtc_receiver().get())); + } } - bool ReceiverWasRemoved( - const RTCRtpReceiver& receiver, - const std::vector<WebRtcReceiverState>& receiver_states) { - for (const auto& receiver_state : receiver_states) { - if (receiver_state.receiver == receiver.webrtc_receiver()) + bool ReceiverWasAdded(const RtpTransceiverState& transceiver_state) { + uintptr_t receiver_id = RTCRtpReceiver::getId( + transceiver_state.receiver_state()->webrtc_receiver().get()); + for (const auto& receiver : handler_->rtp_receivers_) { + if (receiver->Id() == receiver_id) return false; } return true; } - // Determines the stream states from the current state of receivers and the - // receivers that are about to be removed. Produces a stable order of streams. - std::vector<StreamState> GetStreamStates( - const WebRtcSetRemoteDescriptionObserver::States& states, - const std::vector<RTCRtpReceiver*>& removed_receivers) { - states.CheckInvariants(); - std::vector<StreamState> stream_states; - // The receiver's track belongs to all of its streams. A stream may be - // associated with multiple tracks (multiple receivers). - for (auto& receiver_state : states.receiver_states) { - for (auto& stream_ref : receiver_state.stream_refs) { - CHECK(stream_ref); - CHECK(stream_ref->adapter().is_initialized()); - CHECK(!stream_ref->adapter().web_stream().IsNull()); - CHECK(stream_ref->adapter().webrtc_stream()); - auto* stream_state = - GetOrAddStreamStateForStream(*stream_ref, &stream_states); - auto track_ref = receiver_state.track_ref->Copy(); - CHECK(!track_ref->web_track().IsNull()); - CHECK(track_ref->webrtc_track()); - stream_state->track_refs.push_back(std::move(track_ref)); - } - } - // The track of removed receivers do not belong to any stream. Make sure we - // have a stream state for any streams belonging to receivers about to be - // removed in case it was the last receiver referencing that stream. - for (auto* removed_receiver : removed_receivers) { - for (auto& stream_ref : removed_receiver->StreamAdapterRefs()) { - CHECK(!stream_ref->adapter().web_stream().IsNull()); - CHECK(stream_ref->adapter().webrtc_stream()); - GetOrAddStreamStateForStream(*stream_ref, &stream_states); - } - } - states.CheckInvariants(); - return stream_states; - } - - StreamState* GetOrAddStreamStateForStream( - const WebRtcMediaStreamAdapterMap::AdapterRef& stream_ref, - std::vector<StreamState>* stream_states) { - auto* webrtc_stream = stream_ref.adapter().webrtc_stream().get(); - for (auto& stream_state : *stream_states) { - if (stream_state.stream_ref->adapter().webrtc_stream().get() == - webrtc_stream) { - return &stream_state; + bool ReceiverWasRemoved( + const RTCRtpReceiver& receiver, + const std::vector<RtpTransceiverState>& transceiver_states) { + for (const auto& transceiver_state : transceiver_states) { + if (transceiver_state.receiver_state()->webrtc_receiver() == + receiver.state().webrtc_receiver()) { + return false; } } - stream_states->push_back(StreamState(stream_ref.Copy())); - return &stream_states->back(); + return true; + } + + void ProcessStateChangesUnifiedPlan( + WebRtcSetDescriptionObserver::States states) { + DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kUnifiedPlan); + handler_->OnModifyTransceivers( + std::move(states.transceiver_states), + action_ == PeerConnectionTracker::ACTION_SET_REMOTE_DESCRIPTION); } base::WeakPtr<RTCPeerConnectionHandler> handler_; scoped_refptr<base::SequencedTaskRunner> main_thread_; blink::WebRTCVoidRequest web_request_; base::WeakPtr<PeerConnectionTracker> tracker_; + PeerConnectionTracker::Action action_; + blink::WebRTCSdpSemantics sdp_semantics_; }; // Receives notifications from a PeerConnection object about state changes. The @@ -1181,19 +933,8 @@ class RTCPeerConnectionHandler::Observer friend class base::RefCountedThreadSafe<RTCPeerConnectionHandler::Observer>; ~Observer() override = default; - void OnSignalingChange( - PeerConnectionInterface::SignalingState new_state) override { - if (!main_thread_->BelongsToCurrentThread()) { - main_thread_->PostTask( - FROM_HERE, - base::BindOnce(&RTCPeerConnectionHandler::Observer::OnSignalingChange, - this, new_state)); - } else if (handler_) { - handler_->OnSignalingChange(new_state); - } - } - // TODO(hbos): Remove once no longer mandatory to implement. + void OnSignalingChange(PeerConnectionInterface::SignalingState) override {} void OnAddStream(rtc::scoped_refptr<MediaStreamInterface>) override {} void OnRemoveStream(rtc::scoped_refptr<MediaStreamInterface>) override {} @@ -1293,9 +1034,8 @@ RTCPeerConnectionHandler::RTCPeerConnectionHandler( track_adapter_map_( new WebRtcMediaStreamTrackAdapterMap(dependency_factory_, task_runner)), - stream_adapter_map_(new WebRtcMediaStreamAdapterMap(dependency_factory_, - task_runner, - track_adapter_map_)), + // 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_); @@ -1304,7 +1044,7 @@ RTCPeerConnectionHandler::RTCPeerConnectionHandler( } RTCPeerConnectionHandler::~RTCPeerConnectionHandler() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); Stop(); @@ -1317,15 +1057,16 @@ RTCPeerConnectionHandler::~RTCPeerConnectionHandler() { } void RTCPeerConnectionHandler::associateWithFrame(blink::WebLocalFrame* frame) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); DCHECK(frame); frame_ = frame; } bool RTCPeerConnectionHandler::Initialize( const blink::WebRTCConfiguration& server_configuration, - const blink::WebMediaConstraints& options) { - DCHECK(thread_checker_.CalledOnValidThread()); + const blink::WebMediaConstraints& options, + blink::WebRTCSdpSemantics original_sdp_semantics_value) { + DCHECK(task_runner_->RunsTasksInCurrentSequence()); DCHECK(frame_); CHECK(!initialize_called_); @@ -1334,6 +1075,9 @@ 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_); // Choose between RTC smoothness algorithm and prerenderer smoothing. @@ -1363,12 +1107,9 @@ bool RTCPeerConnectionHandler::Initialize( options, frame_); } - uma_observer_ = new rtc::RefCountedObject<PeerConnectionUMAObserver>(); - native_peer_connection_->RegisterUMAObserver(uma_observer_.get()); - UMA_HISTOGRAM_ENUMERATION( "WebRTC.PeerConnection.SdpSemanticRequested", - GetSdpSemanticRequested(server_configuration.sdp_semantics), + GetSdpSemanticRequested(original_sdp_semantics_value), kSdpSemanticRequestedMax); return true; @@ -1378,11 +1119,14 @@ bool RTCPeerConnectionHandler::InitializeForTest( const blink::WebRTCConfiguration& server_configuration, const blink::WebMediaConstraints& options, const base::WeakPtr<PeerConnectionTracker>& peer_connection_tracker) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); 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_); peer_connection_observer_ = @@ -1402,7 +1146,7 @@ bool RTCPeerConnectionHandler::InitializeForTest( void RTCPeerConnectionHandler::CreateOffer( const blink::WebRTCSessionDescriptionRequest& request, const blink::WebMediaConstraints& options) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createOffer"); scoped_refptr<CreateSessionDescriptionRequest> description_request( @@ -1424,7 +1168,7 @@ void RTCPeerConnectionHandler::CreateOffer( void RTCPeerConnectionHandler::CreateOffer( const blink::WebRTCSessionDescriptionRequest& request, const blink::WebRTCOfferOptions& options) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createOffer"); scoped_refptr<CreateSessionDescriptionRequest> description_request( @@ -1446,7 +1190,7 @@ void RTCPeerConnectionHandler::CreateOffer( void RTCPeerConnectionHandler::CreateAnswer( const blink::WebRTCSessionDescriptionRequest& request, const blink::WebMediaConstraints& options) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createAnswer"); scoped_refptr<CreateSessionDescriptionRequest> description_request( new rtc::RefCountedObject<CreateSessionDescriptionRequest>( @@ -1466,7 +1210,7 @@ void RTCPeerConnectionHandler::CreateAnswer( void RTCPeerConnectionHandler::CreateAnswer( const blink::WebRTCSessionDescriptionRequest& request, const blink::WebRTCAnswerOptions& options) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createAnswer"); scoped_refptr<CreateSessionDescriptionRequest> description_request( new rtc::RefCountedObject<CreateSessionDescriptionRequest>( @@ -1491,7 +1235,7 @@ bool IsOfferOrAnswer(const webrtc::SessionDescriptionInterface* native_desc) { void RTCPeerConnectionHandler::SetLocalDescription( const blink::WebRTCVoidRequest& request, const blink::WebRTCSessionDescription& description) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::setLocalDescription"); std::string sdp = description.Sdp().Utf8(); @@ -1532,18 +1276,27 @@ void RTCPeerConnectionHandler::SetLocalDescription( } } - scoped_refptr<SetLocalDescriptionRequest> set_request( - new rtc::RefCountedObject<SetLocalDescriptionRequest>( - task_runner_, request, weak_factory_.GetWeakPtr(), - peer_connection_tracker_, - PeerConnectionTracker::ACTION_SET_LOCAL_DESCRIPTION)); + scoped_refptr<WebRtcSetDescriptionObserverImpl> content_observer( + new WebRtcSetDescriptionObserverImpl( + weak_factory_.GetWeakPtr(), request, peer_connection_tracker_, + task_runner_, PeerConnectionTracker::ACTION_SET_LOCAL_DESCRIPTION, + sdp_semantics_)); + + bool surface_receivers_only = + (sdp_semantics_ == blink::WebRTCSdpSemantics::kPlanB); + scoped_refptr<webrtc::SetSessionDescriptionObserver> webrtc_observer( + WebRtcSetLocalDescriptionObserverHandler::Create( + task_runner_, signaling_thread(), native_peer_connection_, + track_adapter_map_, content_observer, surface_receivers_only) + .get()); signaling_thread()->PostTask( FROM_HERE, base::BindOnce( &RunClosureWithTrace, base::Bind(&webrtc::PeerConnectionInterface::SetLocalDescription, - native_peer_connection_, base::RetainedRef(set_request), + native_peer_connection_, + base::RetainedRef(webrtc_observer), base::Unretained(native_desc)), "SetLocalDescription")); } @@ -1551,7 +1304,7 @@ void RTCPeerConnectionHandler::SetLocalDescription( void RTCPeerConnectionHandler::SetRemoteDescription( const blink::WebRTCVoidRequest& request, const blink::WebRTCSessionDescription& description) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::setRemoteDescription"); std::string sdp = description.Sdp().Utf8(); std::string type = description.GetType().Utf8(); @@ -1592,15 +1345,19 @@ void RTCPeerConnectionHandler::SetRemoteDescription( } } - scoped_refptr<WebRtcSetRemoteDescriptionObserverImpl> content_observer( - new WebRtcSetRemoteDescriptionObserverImpl( + scoped_refptr<WebRtcSetDescriptionObserverImpl> content_observer( + new WebRtcSetDescriptionObserverImpl( weak_factory_.GetWeakPtr(), request, peer_connection_tracker_, - task_runner_)); + task_runner_, PeerConnectionTracker::ACTION_SET_REMOTE_DESCRIPTION, + sdp_semantics_)); + bool surface_receivers_only = + (sdp_semantics_ == blink::WebRTCSdpSemantics::kPlanB); rtc::scoped_refptr<webrtc::SetRemoteDescriptionObserverInterface> webrtc_observer(WebRtcSetRemoteDescriptionObserverHandler::Create( - task_runner_, native_peer_connection_, - stream_adapter_map_, content_observer) + task_runner_, signaling_thread(), + native_peer_connection_, track_adapter_map_, + content_observer, surface_receivers_only) .get()); signaling_thread()->PostTask( @@ -1619,7 +1376,7 @@ void RTCPeerConnectionHandler::SetRemoteDescription( } blink::WebRTCSessionDescription RTCPeerConnectionHandler::LocalDescription() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::localDescription"); // Since local_description returns a pointer to a non-reference-counted object @@ -1640,7 +1397,7 @@ blink::WebRTCSessionDescription RTCPeerConnectionHandler::LocalDescription() { } blink::WebRTCSessionDescription RTCPeerConnectionHandler::RemoteDescription() { - DCHECK(thread_checker_.CalledOnValidThread()); + 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 @@ -1661,7 +1418,7 @@ blink::WebRTCSessionDescription RTCPeerConnectionHandler::RemoteDescription() { webrtc::RTCErrorType RTCPeerConnectionHandler::SetConfiguration( const blink::WebRTCConfiguration& blink_config) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::setConfiguration"); GetNativeRtcConfiguration(blink_config, &configuration_); @@ -1680,7 +1437,7 @@ webrtc::RTCErrorType RTCPeerConnectionHandler::SetConfiguration( bool RTCPeerConnectionHandler::AddICECandidate( const blink::WebRTCVoidRequest& request, scoped_refptr<blink::WebRTCICECandidate> candidate) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addICECandidate"); // Libjingle currently does not accept callbacks for addICECandidate. // For that reason we are going to call callbacks from here. @@ -1698,7 +1455,7 @@ bool RTCPeerConnectionHandler::AddICECandidate( bool RTCPeerConnectionHandler::AddICECandidate( scoped_refptr<blink::WebRTCICECandidate> candidate) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addICECandidate"); std::unique_ptr<webrtc::IceCandidateInterface> native_candidate( dependency_factory_->CreateIceCandidate(candidate->SdpMid().Utf8(), @@ -1724,7 +1481,7 @@ bool RTCPeerConnectionHandler::AddICECandidate( void RTCPeerConnectionHandler::OnaddICECandidateResult( const blink::WebRTCVoidRequest& webkit_request, bool result) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnaddICECandidateResult"); if (!result) { // We don't have the actual error code from the libjingle, so for now @@ -1739,7 +1496,7 @@ void RTCPeerConnectionHandler::OnaddICECandidateResult( void RTCPeerConnectionHandler::GetStats( const blink::WebRTCStatsRequest& request) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); scoped_refptr<LocalRTCStatsRequest> inner_request( new rtc::RefCountedObject<LocalRTCStatsRequest>(request)); getStats(inner_request); @@ -1747,7 +1504,7 @@ void RTCPeerConnectionHandler::GetStats( void RTCPeerConnectionHandler::getStats( const scoped_refptr<LocalRTCStatsRequest>& request) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::getStats"); rtc::scoped_refptr<webrtc::StatsObserver> observer( @@ -1777,7 +1534,7 @@ void RTCPeerConnectionHandler::GetStats( webrtc::StatsObserver* observer, webrtc::PeerConnectionInterface::StatsOutputLevel level, rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> selector) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); signaling_thread()->PostTask( FROM_HERE, base::BindOnce(&GetStatsOnSignalingThread, native_peer_connection_, level, @@ -1786,96 +1543,347 @@ void RTCPeerConnectionHandler::GetStats( void RTCPeerConnectionHandler::GetStats( std::unique_ptr<blink::WebRTCStatsReportCallback> callback) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); signaling_thread()->PostTask( FROM_HERE, base::BindOnce(&GetRTCStatsOnSignalingThread, task_runner_, native_peer_connection_, std::move(callback))); } -std::unique_ptr<blink::WebRTCRtpSender> RTCPeerConnectionHandler::AddTrack( +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(task_runner_->RunsTasksInCurrentSequence()); + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref = + track_adapter_map_->GetOrCreateLocalTrackAdapter(web_track); + TransceiverStateSurfacer transceiver_state_surfacer(task_runner_, + signaling_thread()); + webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> + error_or_transceiver; + RunSynchronousClosureOnSignalingThread( + base::BindRepeating( + &RTCPeerConnectionHandler::AddTransceiverWithTrackOnSignalingThread, + base::Unretained(this), base::RetainedRef(track_ref->webrtc_track()), + base::ConstRef(init), base::Unretained(&transceiver_state_surfacer), + base::Unretained(&error_or_transceiver)), + "AddTransceiverWithTrackOnSignalingThread"); + if (!error_or_transceiver.ok()) { + // Don't leave the surfacer in a pending state. + transceiver_state_surfacer.ObtainStates(); + return error_or_transceiver.MoveError(); + } + + auto transceiver_states = transceiver_state_surfacer.ObtainStates(); + auto transceiver = + CreateOrUpdateTransceiver(std::move(transceiver_states[0])); + std::unique_ptr<blink::WebRTCRtpTransceiver> web_transceiver = + std::move(transceiver); + return std::move(web_transceiver); +} + +void RTCPeerConnectionHandler::AddTransceiverWithTrackOnSignalingThread( + rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track, + webrtc::RtpTransceiverInit init, + TransceiverStateSurfacer* transceiver_state_surfacer, + webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>* + error_or_transceiver) { + *error_or_transceiver = + native_peer_connection_->AddTransceiver(webrtc_track, init); + std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> transceivers; + if (error_or_transceiver->ok()) + transceivers.push_back(error_or_transceiver->value()); + transceiver_state_surfacer->Initialize(track_adapter_map_, transceivers); +} + +webrtc::RTCErrorOr<std::unique_ptr<blink::WebRTCRtpTransceiver>> +RTCPeerConnectionHandler::AddTransceiverWithKind( + std::string kind, + const webrtc::RtpTransceiverInit& init) { + DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kUnifiedPlan); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); + cricket::MediaType media_type; + if (kind == webrtc::MediaStreamTrackInterface::kAudioKind) { + media_type = cricket::MEDIA_TYPE_AUDIO; + } else { + DCHECK_EQ(kind, webrtc::MediaStreamTrackInterface::kVideoKind); + media_type = cricket::MEDIA_TYPE_VIDEO; + } + TransceiverStateSurfacer transceiver_state_surfacer(task_runner_, + signaling_thread()); + webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> + error_or_transceiver; + RunSynchronousClosureOnSignalingThread( + base::BindRepeating(&RTCPeerConnectionHandler:: + AddTransceiverWithMediaTypeOnSignalingThread, + base::Unretained(this), base::ConstRef(media_type), + base::ConstRef(init), + base::Unretained(&transceiver_state_surfacer), + base::Unretained(&error_or_transceiver)), + "AddTransceiverWithMediaTypeOnSignalingThread"); + if (!error_or_transceiver.ok()) { + // Don't leave the surfacer in a pending state. + transceiver_state_surfacer.ObtainStates(); + return error_or_transceiver.MoveError(); + } + + auto transceiver_states = transceiver_state_surfacer.ObtainStates(); + auto transceiver = + CreateOrUpdateTransceiver(std::move(transceiver_states[0])); + std::unique_ptr<blink::WebRTCRtpTransceiver> web_transceiver = + std::move(transceiver); + return std::move(web_transceiver); +} + +void RTCPeerConnectionHandler::AddTransceiverWithMediaTypeOnSignalingThread( + cricket::MediaType media_type, + webrtc::RtpTransceiverInit init, + TransceiverStateSurfacer* transceiver_state_surfacer, + webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>* + error_or_transceiver) { + *error_or_transceiver = + native_peer_connection_->AddTransceiver(media_type, init); + std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> transceivers; + if (error_or_transceiver->ok()) + transceivers.push_back(error_or_transceiver->value()); + transceiver_state_surfacer->Initialize(track_adapter_map_, transceivers); +} + +webrtc::RTCErrorOr<std::unique_ptr<blink::WebRTCRtpTransceiver>> +RTCPeerConnectionHandler::AddTrack( const blink::WebMediaStreamTrack& track, const blink::WebVector<blink::WebMediaStream>& streams) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::AddTrack"); - // Get or create the associated track and stream adapters. - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_adapter = + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref = track_adapter_map_->GetOrCreateLocalTrackAdapter(track); - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_adapters(streams.size()); - std::vector<webrtc::MediaStreamInterface*> webrtc_streams(streams.size()); - for (size_t i = 0; i < streams.size(); ++i) { - stream_adapters[i] = - stream_adapter_map_->GetOrCreateLocalStreamAdapter(streams[i]); - webrtc_streams[i] = stream_adapters[i]->adapter().webrtc_stream().get(); - } - - rtc::scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender = - native_peer_connection_->AddTrack(track_adapter->webrtc_track(), - webrtc_streams); - if (!webrtc_sender) - return nullptr; - DCHECK(FindSender(RTCRtpSender::getId(webrtc_sender)) == rtp_senders_.end()); - rtp_senders_.push_back(std::make_unique<RTCRtpSender>( - native_peer_connection_, task_runner_, signaling_thread(), - stream_adapter_map_, std::move(webrtc_sender), std::move(track_adapter), - std::move(stream_adapters))); - for (const auto& stream_ref : rtp_senders_.back()->stream_refs()) { - if (GetLocalStreamUsageCount(rtp_senders_, - stream_ref->adapter().web_stream()) == 1u) { + std::vector<std::string> stream_ids(streams.size()); + for (size_t i = 0; i < streams.size(); ++i) + stream_ids[i] = streams[i].Id().Utf8(); + + // Invoke native AddTrack() on the signaling thread and surface the resulting + // transceiver (Plan B: sender only). + // TODO(hbos): Implement and surface full transceiver support under Unified + // Plan. https://crbug.com/777617 + TransceiverStateSurfacer transceiver_state_surfacer(task_runner_, + signaling_thread()); + webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpSenderInterface>> + error_or_sender; + RunSynchronousClosureOnSignalingThread( + base::BindRepeating( + &RTCPeerConnectionHandler::AddTrackOnSignalingThread, + base::Unretained(this), base::RetainedRef(track_ref->webrtc_track()), + std::move(stream_ids), base::Unretained(&transceiver_state_surfacer), + base::Unretained(&error_or_sender)), + "AddTrackOnSignalingThread"); + DCHECK(transceiver_state_surfacer.is_initialized()); + if (!error_or_sender.ok()) { + // Don't leave the surfacer in a pending state. + transceiver_state_surfacer.ObtainStates(); + return error_or_sender.MoveError(); + } + track_metrics_.AddTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetricsKind(track), + track.Id().Utf8()); + + auto transceiver_states = transceiver_state_surfacer.ObtainStates(); + DCHECK_EQ(transceiver_states.size(), 1u); + auto transceiver_state = std::move(transceiver_states[0]); + + std::unique_ptr<blink::WebRTCRtpTransceiver> web_transceiver; + if (sdp_semantics_ == blink::WebRTCSdpSemantics::kPlanB) { + // Plan B: Create sender only. + DCHECK(transceiver_state.sender_state()); + auto webrtc_sender = transceiver_state.sender_state()->webrtc_sender(); + DCHECK(FindSender(RTCRtpSender::getId(webrtc_sender.get())) == + rtp_senders_.end()); + RtpSenderState sender_state = transceiver_state.MoveSenderState(); + DCHECK(sender_state.is_initialized()); + rtp_senders_.push_back(std::make_unique<RTCRtpSender>( + native_peer_connection_, track_adapter_map_, std::move(sender_state))); + web_transceiver = std::make_unique<RTCRtpSenderOnlyTransceiver>( + std::make_unique<RTCRtpSender>(*rtp_senders_.back().get())); + } else { + DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kUnifiedPlan); + // Unified Plan: Create or recycle a transceiver. + auto transceiver = CreateOrUpdateTransceiver(std::move(transceiver_state)); + web_transceiver = std::move(transceiver); + } + if (peer_connection_tracker_) { + size_t transceiver_index = GetTransceiverIndex(*web_transceiver.get()); + peer_connection_tracker_->TrackAddTransceiver( + this, PeerConnectionTracker::TransceiverUpdatedReason::kAddTrack, + *web_transceiver.get(), transceiver_index); + } + for (const auto& stream_id : rtp_senders_.back()->state().stream_ids()) { + if (GetLocalStreamUsageCount(rtp_senders_, stream_id) == 1u) { // This is the first occurrence of this stream. - if (peer_connection_tracker_) { - peer_connection_tracker_->TrackAddStream( - this, stream_ref->adapter().web_stream(), - PeerConnectionTracker::SOURCE_LOCAL); - } PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter(); - track_metrics_.AddStream(MediaStreamTrackMetrics::SENT_STREAM, - stream_ref->adapter().webrtc_stream().get()); } } - return rtp_senders_.back()->ShallowCopy(); + return web_transceiver; +} + +void RTCPeerConnectionHandler::AddTrackOnSignalingThread( + rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track, + std::vector<std::string> stream_ids, + TransceiverStateSurfacer* transceiver_state_surfacer, + webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpSenderInterface>>* + error_or_sender) { + *error_or_sender = native_peer_connection_->AddTrack(track, stream_ids); + 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) { + transceivers = {new SurfaceSenderStateOnly(sender)}; + } else { + DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kUnifiedPlan); + rtc::scoped_refptr<webrtc::RtpTransceiverInterface> + transceiver_for_sender = nullptr; + for (const auto& transceiver : + native_peer_connection_->GetTransceivers()) { + if (transceiver->sender() == sender) { + transceiver_for_sender = transceiver; + break; + } + } + DCHECK(transceiver_for_sender); + transceivers = {transceiver_for_sender}; + } + } + transceiver_state_surfacer->Initialize(track_adapter_map_, + std::move(transceivers)); } -bool RTCPeerConnectionHandler::RemoveTrack(blink::WebRTCRtpSender* web_sender) { - DCHECK(thread_checker_.CalledOnValidThread()); +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 (RemoveTrackPlanB(web_sender)) { + // In Plan B, null indicates success. + std::unique_ptr<blink::WebRTCRtpTransceiver> web_transceiver = nullptr; + return std::move(web_transceiver); + } + // TODO(hbos): Surface RTCError from third_party/webrtc when + // peerconnectioninterface.h is updated. https://crbug.com/webrtc/9534 + return webrtc::RTCError(webrtc::RTCErrorType::INVALID_STATE); + } + DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kUnifiedPlan); + return RemoveTrackUnifiedPlan(web_sender); +} + +bool RTCPeerConnectionHandler::RemoveTrackPlanB( + blink::WebRTCRtpSender* web_sender) { + DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kPlanB); + auto web_track = web_sender->Track(); auto it = FindSender(web_sender->Id()); if (it == rtp_senders_.end()) return false; if (!(*it)->RemoveFromPeerConnection(native_peer_connection_.get())) return false; - auto stream_refs = (*it)->stream_refs(); - // TODO(hbos): In Unified Plan, senders are never removed. The lower layer - // needs to tell us what to do with the sender: Update its states and/or - // remove it. https://crbug.com/799030 + track_metrics_.RemoveTrack(MediaStreamTrackMetrics::Direction::kSend, + MediaStreamTrackMetricsKind(web_track), + web_track.Id().Utf8()); + if (peer_connection_tracker_) { + auto sender_only_transceiver = + std::make_unique<RTCRtpSenderOnlyTransceiver>( + std::make_unique<RTCRtpSender>(*it->get())); + size_t sender_index = GetTransceiverIndex(*sender_only_transceiver); + peer_connection_tracker_->TrackRemoveTransceiver( + this, PeerConnectionTracker::TransceiverUpdatedReason::kRemoveTrack, + *sender_only_transceiver.get(), sender_index); + } + std::vector<std::string> stream_ids = (*it)->state().stream_ids(); rtp_senders_.erase(it); - for (const auto& stream_ref : stream_refs) { - if (GetLocalStreamUsageCount(rtp_senders_, - stream_ref->adapter().web_stream()) == 0u) { + for (const auto& stream_id : stream_ids) { + if (GetLocalStreamUsageCount(rtp_senders_, stream_id) == 0u) { // This was the last occurrence of this stream. - if (peer_connection_tracker_) { - peer_connection_tracker_->TrackRemoveStream( - this, stream_ref->adapter().web_stream(), - PeerConnectionTracker::SOURCE_LOCAL); - } PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter(); - track_metrics_.RemoveStream(MediaStreamTrackMetrics::SENT_STREAM, - stream_ref->adapter().webrtc_stream().get()); } } return true; } +webrtc::RTCErrorOr<std::unique_ptr<blink::WebRTCRtpTransceiver>> +RTCPeerConnectionHandler::RemoveTrackUnifiedPlan( + blink::WebRTCRtpSender* web_sender) { + DCHECK(task_runner_->RunsTasksInCurrentSequence()); + DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kUnifiedPlan); + auto it = FindSender(web_sender->Id()); + if (it == rtp_senders_.end()) + return webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER); + const auto& sender = *it; + auto webrtc_sender = sender->state().webrtc_sender(); + + TransceiverStateSurfacer transceiver_state_surfacer(task_runner_, + signaling_thread()); + bool result; + RunSynchronousClosureOnSignalingThread( + base::BindRepeating( + &RTCPeerConnectionHandler::RemoveTrackUnifiedPlanOnSignalingThread, + base::Unretained(this), base::RetainedRef(webrtc_sender), + base::Unretained(&transceiver_state_surfacer), + base::Unretained(&result)), + "RemoveTrackUnifiedPlanOnSignalingThread"); + DCHECK(transceiver_state_surfacer.is_initialized()); + if (!result) { + // Don't leave the surfacer in a pending state. + transceiver_state_surfacer.ObtainStates(); + // TODO(hbos): Surface RTCError from third_party/webrtc when + // peerconnectioninterface.h is updated. https://crbug.com/webrtc/9534 + return webrtc::RTCError(webrtc::RTCErrorType::INTERNAL_ERROR); + } + + auto transceiver_states = transceiver_state_surfacer.ObtainStates(); + DCHECK_EQ(transceiver_states.size(), 1u); + auto transceiver_state = std::move(transceiver_states[0]); + + // Update the transceiver. + auto transceiver = CreateOrUpdateTransceiver(std::move(transceiver_state)); + if (peer_connection_tracker_) { + size_t transceiver_index = GetTransceiverIndex(*transceiver); + peer_connection_tracker_->TrackModifyTransceiver( + this, PeerConnectionTracker::TransceiverUpdatedReason::kRemoveTrack, + *transceiver.get(), transceiver_index); + } + std::unique_ptr<blink::WebRTCRtpTransceiver> web_transceiver = + std::move(transceiver); + return web_transceiver; +} + +void RTCPeerConnectionHandler::RemoveTrackUnifiedPlanOnSignalingThread( + rtc::scoped_refptr<webrtc::RtpSenderInterface> sender, + TransceiverStateSurfacer* transceiver_state_surfacer, + bool* result) { + *result = native_peer_connection_->RemoveTrack(sender); + std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> transceivers; + if (*result) { + rtc::scoped_refptr<webrtc::RtpTransceiverInterface> transceiver_for_sender = + nullptr; + for (const auto& transceiver : native_peer_connection_->GetTransceivers()) { + if (transceiver->sender() == sender) { + transceiver_for_sender = transceiver; + break; + } + } + DCHECK(transceiver_for_sender); + transceivers = {transceiver_for_sender}; + } + transceiver_state_surfacer->Initialize(track_adapter_map_, + std::move(transceivers)); +} + void RTCPeerConnectionHandler::CloseClientPeerConnection() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); if (!is_closed_) client_->ClosePeerConnection(); } void RTCPeerConnectionHandler::StartEventLog(IPC::PlatformFileForTransit file, int64_t max_file_size_bytes) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); DCHECK(file != IPC::InvalidPlatformFileForTransit()); // TODO(eladalon): StartRtcEventLog() return value is not useful; remove it // or find a way to be able to use it. @@ -1885,7 +1893,7 @@ void RTCPeerConnectionHandler::StartEventLog(IPC::PlatformFileForTransit file, } void RTCPeerConnectionHandler::StartEventLog() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); // TODO(eladalon): StartRtcEventLog() return value is not useful; remove it // or find a way to be able to use it. // https://crbug.com/775415 @@ -1896,13 +1904,13 @@ void RTCPeerConnectionHandler::StartEventLog() { } void RTCPeerConnectionHandler::StopEventLog() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); native_peer_connection_->StopRtcEventLog(); } void RTCPeerConnectionHandler::OnWebRtcEventLogWrite( const std::string& output) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); if (peer_connection_tracker_) { peer_connection_tracker_->TrackRtcEventLogWrite(this, output); } @@ -1911,7 +1919,7 @@ void RTCPeerConnectionHandler::OnWebRtcEventLogWrite( blink::WebRTCDataChannelHandler* RTCPeerConnectionHandler::CreateDataChannel( const blink::WebString& label, const blink::WebRTCDataChannelInit& init) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createDataChannel"); DVLOG(1) << "createDataChannel label " << label.Utf8(); @@ -1943,7 +1951,7 @@ blink::WebRTCDataChannelHandler* RTCPeerConnectionHandler::CreateDataChannel( } void RTCPeerConnectionHandler::Stop() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); DVLOG(1) << "RTCPeerConnectionHandler::stop"; if (is_closed_ || !native_peer_connection_.get()) @@ -1964,22 +1972,20 @@ blink::WebString RTCPeerConnectionHandler::Id() const { void RTCPeerConnectionHandler::OnSignalingChange( webrtc::PeerConnectionInterface::SignalingState new_state) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnSignalingChange"); - blink::WebRTCPeerConnectionHandlerClient::SignalingState state = - GetWebKitSignalingState(new_state); if (peer_connection_tracker_) - peer_connection_tracker_->TrackSignalingStateChange(this, state); + peer_connection_tracker_->TrackSignalingStateChange(this, new_state); if (!is_closed_) - client_->DidChangeSignalingState(state); + client_->DidChangeSignalingState(new_state); } // Called any time the IceConnectionState changes void RTCPeerConnectionHandler::OnIceConnectionChange( webrtc::PeerConnectionInterface::IceConnectionState new_state) { TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceConnectionChange"); - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); ReportICEState(new_state); if (new_state == webrtc::PeerConnectionInterface::kIceConnectionChecking) { ice_connection_checking_start_ = base::TimeTicks::Now(); @@ -2014,7 +2020,7 @@ void RTCPeerConnectionHandler::OnIceConnectionChange( // Called any time the IceGatheringState changes void RTCPeerConnectionHandler::OnIceGatheringChange( webrtc::PeerConnectionInterface::IceGatheringState new_state) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceGatheringChange"); if (new_state == webrtc::PeerConnectionInterface::kIceGatheringComplete) { @@ -2039,7 +2045,7 @@ void RTCPeerConnectionHandler::OnIceGatheringChange( } void RTCPeerConnectionHandler::OnRenegotiationNeeded() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnRenegotiationNeeded"); if (peer_connection_tracker_) peer_connection_tracker_->TrackOnRenegotiationNeeded(this); @@ -2047,89 +2053,129 @@ void RTCPeerConnectionHandler::OnRenegotiationNeeded() { client_->NegotiationNeeded(); } -void RTCPeerConnectionHandler::OnAddRemoteTrack( - scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver, - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> - remote_track_adapter_ref, - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - remote_stream_adapter_refs) { - DCHECK(thread_checker_.CalledOnValidThread()); - TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnAddRemoteTrack"); - - for (const auto& remote_stream_adapter_ref : remote_stream_adapter_refs) { +void RTCPeerConnectionHandler::OnAddReceiverPlanB( + RtpReceiverState receiver_state) { + DCHECK(task_runner_->RunsTasksInCurrentSequence()); + DCHECK(receiver_state.is_initialized()); + TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnAddReceiverPlanB"); + auto web_track = receiver_state.track_ref()->web_track(); + // Update metrics. + track_metrics_.AddTrack(MediaStreamTrackMetrics::Direction::kReceive, + MediaStreamTrackMetricsKind(web_track), + web_track.Id().Utf8()); + for (const auto& stream_id : receiver_state.stream_ids()) { // New remote stream? - if (GetRemoteStreamUsageCount( - rtp_receivers_, - remote_stream_adapter_ref->adapter().webrtc_stream().get()) == 0) { - // Update metrics. - // TODO(hbos): Update metrics to correspond to track added/removed events, - // not streams. https://crbug.com/765170 - if (peer_connection_tracker_) { - peer_connection_tracker_->TrackAddStream( - this, remote_stream_adapter_ref->adapter().web_stream(), - PeerConnectionTracker::SOURCE_REMOTE); - } + if (!IsRemoteStream(rtp_receivers_, stream_id)) PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter(); - track_metrics_.AddStream( - MediaStreamTrackMetrics::RECEIVED_STREAM, - remote_stream_adapter_ref->adapter().webrtc_stream().get()); - } } - - uintptr_t receiver_id = RTCRtpReceiver::getId(webrtc_receiver.get()); - DCHECK(rtp_receivers_.find(receiver_id) == rtp_receivers_.end()); - const std::unique_ptr<RTCRtpReceiver>& rtp_receiver = - rtp_receivers_ - .insert(std::make_pair( - receiver_id, - std::make_unique<RTCRtpReceiver>( - native_peer_connection_, task_runner_, signaling_thread(), - webrtc_receiver.get(), std::move(remote_track_adapter_ref), - std::move(remote_stream_adapter_refs)))) - .first->second; + uintptr_t receiver_id = + RTCRtpReceiver::getId(receiver_state.webrtc_receiver().get()); + DCHECK(FindReceiver(receiver_id) == rtp_receivers_.end()); + auto rtp_receiver = std::make_unique<RTCRtpReceiver>( + native_peer_connection_, std::move(receiver_state)); + rtp_receivers_.push_back(std::make_unique<RTCRtpReceiver>(*rtp_receiver)); + if (peer_connection_tracker_) { + auto receiver_only_transceiver = + std::make_unique<RTCRtpReceiverOnlyTransceiver>( + std::make_unique<RTCRtpReceiver>(*rtp_receiver)); + size_t receiver_index = GetTransceiverIndex(*receiver_only_transceiver); + peer_connection_tracker_->TrackAddTransceiver( + this, + PeerConnectionTracker::TransceiverUpdatedReason::kSetRemoteDescription, + *receiver_only_transceiver.get(), receiver_index); + } if (!is_closed_) - client_->DidAddRemoteTrack(rtp_receiver->ShallowCopy()); + client_->DidAddReceiverPlanB(rtp_receiver->ShallowCopy()); } -void RTCPeerConnectionHandler::OnRemoveRemoteTrack( - scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver) { - DCHECK(thread_checker_.CalledOnValidThread()); - TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnRemoveRemoteTrack"); +void RTCPeerConnectionHandler::OnRemoveReceiverPlanB(uintptr_t receiver_id) { + DCHECK(task_runner_->RunsTasksInCurrentSequence()); + TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnRemoveReceiverPlanB"); - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - remote_stream_adapter_refs; - { - uintptr_t receiver_id = RTCRtpReceiver::getId(webrtc_receiver.get()); - auto it = rtp_receivers_.find(receiver_id); - DCHECK(it != rtp_receivers_.end()); - remote_stream_adapter_refs = it->second->StreamAdapterRefs(); - if (!is_closed_) - client_->DidRemoveRemoteTrack(it->second->ShallowCopy()); - rtp_receivers_.erase(it); - } - - for (const auto& remote_stream_adapter_ref : remote_stream_adapter_refs) { - // Was this the last usage of the remote stream? - if (GetRemoteStreamUsageCount( - rtp_receivers_, - remote_stream_adapter_ref->adapter().webrtc_stream().get()) == 0) { - // Update metrics. - track_metrics_.RemoveStream( - MediaStreamTrackMetrics::RECEIVED_STREAM, - remote_stream_adapter_ref->adapter().webrtc_stream().get()); - PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter(); - if (peer_connection_tracker_) { - peer_connection_tracker_->TrackRemoveStream( - this, remote_stream_adapter_ref->adapter().web_stream(), - PeerConnectionTracker::SOURCE_REMOTE); + auto it = FindReceiver(receiver_id); + DCHECK(it != rtp_receivers_.end()); + auto receiver = std::make_unique<RTCRtpReceiver>(*(*it)); + // Update metrics. + track_metrics_.RemoveTrack(MediaStreamTrackMetrics::Direction::kReceive, + MediaStreamTrackMetricsKind(receiver->Track()), + receiver->Track().Id().Utf8()); + if (peer_connection_tracker_) { + auto receiver_only_transceiver = + std::make_unique<RTCRtpReceiverOnlyTransceiver>( + std::make_unique<RTCRtpReceiver>(*receiver)); + size_t receiver_index = GetTransceiverIndex(*receiver_only_transceiver); + peer_connection_tracker_->TrackRemoveTransceiver( + this, + PeerConnectionTracker::TransceiverUpdatedReason::kSetRemoteDescription, + *receiver_only_transceiver.get(), receiver_index); + } + rtp_receivers_.erase(it); + for (const auto& stream_id : receiver->state().stream_ids()) { + // This was the last occurence of the stream? + if (!IsRemoteStream(rtp_receivers_, stream_id)) + PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter(); + } + if (!is_closed_) + client_->DidRemoveReceiverPlanB(std::move(receiver)); +} + +void RTCPeerConnectionHandler::OnModifyTransceivers( + std::vector<RtpTransceiverState> transceiver_states, + bool is_remote_description) { + DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kUnifiedPlan); + std::vector<std::unique_ptr<blink::WebRTCRtpTransceiver>> web_transceivers( + transceiver_states.size()); + PeerConnectionTracker::TransceiverUpdatedReason update_reason = + !is_remote_description ? PeerConnectionTracker::TransceiverUpdatedReason:: + kSetLocalDescription + : PeerConnectionTracker::TransceiverUpdatedReason:: + kSetRemoteDescription; + for (size_t i = 0; i < transceiver_states.size(); ++i) { + // Figure out if this transceiver is new or if setting the state modified + // the transceiver such that it should be logged by the + // |peer_connection_tracker_|. + uintptr_t transceiver_id = RTCRtpTransceiver::GetId( + transceiver_states[i].webrtc_transceiver().get()); + auto it = FindTransceiver(transceiver_id); + bool transceiver_is_new = (it == rtp_transceivers_.end()); + bool transceiver_was_modified = false; + if (!transceiver_is_new) { + const auto& previous_state = (*it)->state(); + transceiver_was_modified = + previous_state.mid() != transceiver_states[i].mid() || + previous_state.stopped() != transceiver_states[i].stopped() || + previous_state.direction() != transceiver_states[i].direction() || + previous_state.current_direction() != + transceiver_states[i].current_direction(); + } + + // Update the transceiver. + web_transceivers[i] = + CreateOrUpdateTransceiver(std::move(transceiver_states[i])); + + // Log a "transcieverAdded" or "transceiverModified" event in + // chrome://webrtc-internals if new or modified. + if (peer_connection_tracker_ && + (transceiver_is_new || transceiver_was_modified)) { + size_t transceiver_index = GetTransceiverIndex(*web_transceivers[i]); + if (transceiver_is_new) { + peer_connection_tracker_->TrackAddTransceiver( + this, update_reason, *web_transceivers[i].get(), transceiver_index); + } else if (transceiver_was_modified) { + peer_connection_tracker_->TrackModifyTransceiver( + this, update_reason, *web_transceivers[i].get(), transceiver_index); } } } + if (!is_closed_) { + client_->DidModifyTransceivers(std::move(web_transceivers), + is_remote_description); + } } void RTCPeerConnectionHandler::OnDataChannel( std::unique_ptr<RtcDataChannelHandler> handler) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnDataChannelImpl"); if (peer_connection_tracker_) { @@ -2144,7 +2190,7 @@ void RTCPeerConnectionHandler::OnDataChannel( void RTCPeerConnectionHandler::OnIceCandidate( const std::string& sdp, const std::string& sdp_mid, int sdp_mline_index, int component, int address_family) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceCandidateImpl"); scoped_refptr<blink::WebRTCICECandidate> web_candidate = blink::WebRTCICECandidate::Create(blink::WebString::FromUTF8(sdp), @@ -2224,16 +2270,103 @@ RTCPeerConnectionHandler::FindSender(uintptr_t id) { return rtp_senders_.end(); } +std::vector<std::unique_ptr<RTCRtpReceiver>>::iterator +RTCPeerConnectionHandler::FindReceiver(uintptr_t id) { + for (auto it = rtp_receivers_.begin(); it != rtp_receivers_.end(); ++it) { + if ((*it)->Id() == id) + return it; + } + return rtp_receivers_.end(); +} + +std::vector<std::unique_ptr<RTCRtpTransceiver>>::iterator +RTCPeerConnectionHandler::FindTransceiver(uintptr_t id) { + for (auto it = rtp_transceivers_.begin(); it != rtp_transceivers_.end(); + ++it) { + if ((*it)->Id() == id) + return it; + } + return rtp_transceivers_.end(); +} + +size_t RTCPeerConnectionHandler::GetTransceiverIndex( + const blink::WebRTCRtpTransceiver& web_transceiver) { + if (web_transceiver.ImplementationType() == + blink::WebRTCRtpTransceiverImplementationType::kFullTransceiver) { + for (size_t i = 0; i < rtp_transceivers_.size(); ++i) { + if (web_transceiver.Id() == rtp_transceivers_[i]->Id()) + return i; + } + } else if (web_transceiver.ImplementationType() == + blink::WebRTCRtpTransceiverImplementationType::kPlanBSenderOnly) { + const auto web_sender = web_transceiver.Sender(); + for (size_t i = 0; i < rtp_senders_.size(); ++i) { + if (web_sender->Id() == rtp_senders_[i]->Id()) + return i; + } + } else { + RTC_DCHECK( + web_transceiver.ImplementationType() == + blink::WebRTCRtpTransceiverImplementationType::kPlanBReceiverOnly); + const auto web_receiver = web_transceiver.Receiver(); + for (size_t i = 0; i < rtp_receivers_.size(); ++i) { + if (web_receiver->Id() == rtp_receivers_[i]->Id()) + return i; + } + } + NOTREACHED(); + return 0u; +} + +std::unique_ptr<RTCRtpTransceiver> +RTCPeerConnectionHandler::CreateOrUpdateTransceiver( + RtpTransceiverState transceiver_state) { + DCHECK_EQ(sdp_semantics_, blink::WebRTCSdpSemantics::kUnifiedPlan); + DCHECK(transceiver_state.is_initialized()); + DCHECK(transceiver_state.sender_state()); + DCHECK(transceiver_state.receiver_state()); + auto webrtc_transceiver = transceiver_state.webrtc_transceiver(); + auto webrtc_sender = transceiver_state.sender_state()->webrtc_sender(); + auto webrtc_receiver = transceiver_state.receiver_state()->webrtc_receiver(); + + std::unique_ptr<RTCRtpTransceiver> transceiver; + auto it = FindTransceiver(RTCRtpTransceiver::GetId(webrtc_transceiver.get())); + if (it == rtp_transceivers_.end()) { + // Create a new transceiver, including a sender and a receiver. + transceiver = std::make_unique<RTCRtpTransceiver>( + native_peer_connection_, track_adapter_map_, + std::move(transceiver_state)); + rtp_transceivers_.push_back(transceiver->ShallowCopy()); + DCHECK(FindSender(RTCRtpSender::getId(webrtc_sender.get())) == + rtp_senders_.end()); + rtp_senders_.push_back( + std::make_unique<RTCRtpSender>(*transceiver->content_sender())); + DCHECK(FindReceiver(RTCRtpReceiver::getId(webrtc_receiver.get())) == + rtp_receivers_.end()); + rtp_receivers_.push_back( + std::make_unique<RTCRtpReceiver>(*transceiver->content_receiver())); + } else { + // Update the transceiver. This also updates the sender and receiver. + transceiver = (*it)->ShallowCopy(); + transceiver->set_state(std::move(transceiver_state)); + DCHECK(FindSender(RTCRtpSender::getId(webrtc_sender.get())) != + rtp_senders_.end()); + DCHECK(FindReceiver(RTCRtpReceiver::getId(webrtc_receiver.get())) != + rtp_receivers_.end()); + } + return transceiver; +} + scoped_refptr<base::SingleThreadTaskRunner> RTCPeerConnectionHandler::signaling_thread() const { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); return dependency_factory_->GetWebRtcSignalingThread(); } void RTCPeerConnectionHandler::RunSynchronousClosureOnSignalingThread( const base::Closure& closure, const char* trace_event_name) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); scoped_refptr<base::SingleThreadTaskRunner> thread(signaling_thread()); if (!thread.get() || thread->BelongsToCurrentThread()) { TRACE_EVENT0("webrtc", trace_event_name); @@ -2251,7 +2384,7 @@ void RTCPeerConnectionHandler::RunSynchronousClosureOnSignalingThread( void RTCPeerConnectionHandler::ReportICEState( webrtc::PeerConnectionInterface::IceConnectionState new_state) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); if (ice_state_seen_[new_state]) return; ice_state_seen_[new_state] = true; @@ -2260,7 +2393,7 @@ void RTCPeerConnectionHandler::ReportICEState( } void RTCPeerConnectionHandler::ResetUMAStats() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(task_runner_->RunsTasksInCurrentSequence()); num_local_candidates_ipv6_ = 0; num_local_candidates_ipv4_ = 0; ice_connection_checking_start_ = base::TimeTicks(); 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 a4b038365d2..74cb1b77c1a 100644 --- a/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.h +++ b/chromium/content/renderer/media/webrtc/rtc_peer_connection_handler.h @@ -18,15 +18,15 @@ #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread.h" -#include "base/threading/thread_checker.h" #include "content/common/content_export.h" #include "content/renderer/media/webrtc/media_stream_track_metrics.h" #include "content/renderer/media/webrtc/rtc_rtp_receiver.h" #include "content/renderer/media/webrtc/rtc_rtp_sender.h" -#include "content/renderer/media/webrtc/webrtc_media_stream_adapter_map.h" +#include "content/renderer/media/webrtc/transceiver_state_surfacer.h" #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" @@ -45,6 +45,7 @@ namespace content { class PeerConnectionDependencyFactory; class PeerConnectionTracker; class RtcDataChannelHandler; +class SetLocalDescriptionRequest; // Mockable wrapper for blink::WebRTCStatsResponse class CONTENT_EXPORT LocalRTCStatsResponse : public rtc::RefCountInterface { @@ -107,8 +108,10 @@ class CONTENT_EXPORT RTCPeerConnectionHandler const base::WeakPtr<PeerConnectionTracker>& peer_connection_tracker); // blink::WebRTCPeerConnectionHandler implementation - bool Initialize(const blink::WebRTCConfiguration& server_configuration, - const blink::WebMediaConstraints& options) override; + bool Initialize( + const blink::WebRTCConfiguration& server_configuration, + const blink::WebMediaConstraints& options, + blink::WebRTCSdpSemantics original_sdp_semantics_value) override; void CreateOffer(const blink::WebRTCSessionDescriptionRequest& request, const blink::WebMediaConstraints& options) override; @@ -143,10 +146,17 @@ class CONTENT_EXPORT RTCPeerConnectionHandler void GetStats(const blink::WebRTCStatsRequest& request) override; void GetStats( std::unique_ptr<blink::WebRTCStatsReportCallback> callback) override; - std::unique_ptr<blink::WebRTCRtpSender> AddTrack( + webrtc::RTCErrorOr<std::unique_ptr<blink::WebRTCRtpTransceiver>> + AddTransceiverWithTrack(const blink::WebMediaStreamTrack& web_track, + const webrtc::RtpTransceiverInit& init) override; + webrtc::RTCErrorOr<std::unique_ptr<blink::WebRTCRtpTransceiver>> + AddTransceiverWithKind(std::string kind, + const webrtc::RtpTransceiverInit& init) override; + webrtc::RTCErrorOr<std::unique_ptr<blink::WebRTCRtpTransceiver>> AddTrack( const blink::WebMediaStreamTrack& web_track, const blink::WebVector<blink::WebMediaStream>& web_streams) override; - bool RemoveTrack(blink::WebRTCRtpSender* web_sender) override; + webrtc::RTCErrorOr<std::unique_ptr<blink::WebRTCRtpTransceiver>> RemoveTrack( + blink::WebRTCRtpSender* web_sender) override; blink::WebRTCDataChannelHandler* CreateDataChannel( const blink::WebString& label, @@ -185,8 +195,10 @@ class CONTENT_EXPORT RTCPeerConnectionHandler class Observer; friend class Observer; - class WebRtcSetRemoteDescriptionObserverImpl; - friend class WebRtcSetRemoteDescriptionObserverImpl; + class WebRtcSetDescriptionObserverImpl; + friend class WebRtcSetDescriptionObserverImpl; + class SetLocalDescriptionRequest; + friend class SetLocalDescriptionRequest; void OnSignalingChange( webrtc::PeerConnectionInterface::SignalingState new_state); @@ -195,14 +207,10 @@ class CONTENT_EXPORT RTCPeerConnectionHandler void OnIceGatheringChange( webrtc::PeerConnectionInterface::IceGatheringState new_state); void OnRenegotiationNeeded(); - void OnAddRemoteTrack( - scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver, - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> - remote_track_adapter_ref, - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - remote_stream_adapter_refs); - void OnRemoveRemoteTrack( - scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver); + void OnAddReceiverPlanB(RtpReceiverState receiver_state); + void OnRemoveReceiverPlanB(uintptr_t receiver_id); + void OnModifyTransceivers(std::vector<RtpTransceiverState> transceiver_states, + bool is_remote_description); void OnDataChannel(std::unique_ptr<RtcDataChannelHandler> handler); void OnIceCandidate(const std::string& sdp, const std::string& sdp_mid, @@ -240,7 +248,47 @@ class CONTENT_EXPORT RTCPeerConnectionHandler void ReportFirstSessionDescriptions(const FirstSessionDescription& local, const FirstSessionDescription& remote); + void AddTransceiverWithTrackOnSignalingThread( + rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track, + webrtc::RtpTransceiverInit init, + TransceiverStateSurfacer* transceiver_state_surfacer, + webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>* + error_or_transceiver); + void AddTransceiverWithMediaTypeOnSignalingThread( + cricket::MediaType media_type, + webrtc::RtpTransceiverInit init, + TransceiverStateSurfacer* transceiver_state_surfacer, + webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>>* + error_or_transceiver); + void AddTrackOnSignalingThread( + rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track, + std::vector<std::string> stream_ids, + TransceiverStateSurfacer* transceiver_state_surfacer, + webrtc::RTCErrorOr<rtc::scoped_refptr<webrtc::RtpSenderInterface>>* + error_or_sender); + bool RemoveTrackPlanB(blink::WebRTCRtpSender* web_sender); + webrtc::RTCErrorOr<std::unique_ptr<blink::WebRTCRtpTransceiver>> + RemoveTrackUnifiedPlan(blink::WebRTCRtpSender* web_sender); + void RemoveTrackUnifiedPlanOnSignalingThread( + rtc::scoped_refptr<webrtc::RtpSenderInterface> sender, + TransceiverStateSurfacer* transceiver_state_surfacer, + bool* result); std::vector<std::unique_ptr<RTCRtpSender>>::iterator FindSender(uintptr_t id); + std::vector<std::unique_ptr<RTCRtpReceiver>>::iterator FindReceiver( + uintptr_t id); + std::vector<std::unique_ptr<RTCRtpTransceiver>>::iterator FindTransceiver( + uintptr_t id); + // For full transceiver implementations, returns the index of + // |rtp_transceivers_| that correspond to |web_transceiver|. + // For sender-only transceiver implementations, returns the index of + // |rtp_senders_| that correspond to |web_transceiver.Sender()|. + // For receiver-only transceiver implementations, returns the index of + // |rtp_receivers_| that correspond to |web_transceiver.Receiver()|. + // NOTREACHED()-crashes if no correspondent is found. + size_t GetTransceiverIndex( + const blink::WebRTCRtpTransceiver& web_transceiver); + std::unique_ptr<RTCRtpTransceiver> CreateOrUpdateTransceiver( + RtpTransceiverState transceiver_state); scoped_refptr<base::SingleThreadTaskRunner> signaling_thread() const; @@ -254,8 +302,6 @@ class CONTENT_EXPORT RTCPeerConnectionHandler // first call fails. bool initialize_called_; - base::ThreadChecker thread_checker_; - // |client_| is a weak pointer to the blink object (blink::RTCPeerConnection) // that owns this object. // It is valid for the lifetime of this object. @@ -279,20 +325,20 @@ class CONTENT_EXPORT RTCPeerConnectionHandler // needs to reference it, and automatically disposed when there are no longer // any components referencing it. scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map_; - // Map and owners of stream adapters. Every stream that is in use by the peer - // connection has an associated blink and webrtc layer representation of it. - // The map keeps track of the relationship between |blink::WebMediaStream|s - // and |webrtc::MediaStreamInterface|s. Stream adapters are created on the fly - // when a component (such as a sender or receiver) needs to reference it, and - // automatically disposed when there are no longer any components referencing - // it. - scoped_refptr<WebRtcMediaStreamAdapterMap> stream_adapter_map_; + // 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_; - // Maps |RTCRtpReceiver::getId|s of |webrtc::RtpReceiverInterface|s to the - // corresponding content layer receivers. The set of receivers is needed in - // order to keep its associated track's and streams' adapters alive. - std::map<uintptr_t, std::unique_ptr<RTCRtpReceiver>> rtp_receivers_; + // Content layer correspondents of |webrtc::RtpReceiverInterface|. + std::vector<std::unique_ptr<RTCRtpReceiver>> rtp_receivers_; + // Content layer correspondents of |webrtc::RtpTransceiverInterface|. + std::vector<std::unique_ptr<RTCRtpTransceiver>> rtp_transceivers_; base::WeakPtr<PeerConnectionTracker> peer_connection_tracker_; @@ -308,7 +354,6 @@ class CONTENT_EXPORT RTCPeerConnectionHandler // To make sure the observers are released after native_peer_connection_, // they have to come first. scoped_refptr<Observer> peer_connection_observer_; - scoped_refptr<webrtc::UMAObserver> uma_observer_; // |native_peer_connection_| is the libjingle native PeerConnection object. scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection_; 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 3d9ade84d75..51a6af48d59 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 @@ -23,7 +23,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/values.h" #include "content/child/child_process.h" -#include "content/renderer/media/mock_audio_device_factory.h" +#include "content/renderer/media/audio/mock_audio_device_factory.h" #include "content/renderer/media/stream/media_stream_audio_source.h" #include "content/renderer/media/stream/media_stream_audio_track.h" #include "content/renderer/media/stream/media_stream_source.h" @@ -171,14 +171,21 @@ class MockPeerConnectionTracker : public PeerConnectionTracker { scoped_refptr<blink::WebRTCICECandidate> candidate, Source source, bool succeeded)); - MOCK_METHOD3(TrackAddStream, + MOCK_METHOD4(TrackAddTransceiver, void(RTCPeerConnectionHandler* pc_handler, - const blink::WebMediaStream& stream, - Source source)); - MOCK_METHOD3(TrackRemoveStream, + TransceiverUpdatedReason reason, + const blink::WebRTCRtpTransceiver& transceiver, + size_t transceiver_index)); + MOCK_METHOD4(TrackModifyTransceiver, void(RTCPeerConnectionHandler* pc_handler, - const blink::WebMediaStream& stream, - Source source)); + TransceiverUpdatedReason reason, + const blink::WebRTCRtpTransceiver& transceiver, + size_t transceiver_index)); + MOCK_METHOD4(TrackRemoveTransceiver, + void(RTCPeerConnectionHandler* pc_handler, + TransceiverUpdatedReason reason, + const blink::WebRTCRtpTransceiver& transceiver, + size_t transceiver_index)); MOCK_METHOD1(TrackOnIceComplete, void(RTCPeerConnectionHandler* pc_handler)); MOCK_METHOD3(TrackCreateDataChannel, @@ -188,11 +195,11 @@ class MockPeerConnectionTracker : public PeerConnectionTracker { MOCK_METHOD1(TrackStop, void(RTCPeerConnectionHandler* pc_handler)); MOCK_METHOD2(TrackSignalingStateChange, void(RTCPeerConnectionHandler* pc_handler, - WebRTCPeerConnectionHandlerClient::SignalingState state)); + webrtc::PeerConnectionInterface::SignalingState state)); MOCK_METHOD2( TrackIceConnectionStateChange, void(RTCPeerConnectionHandler* pc_handler, - WebRTCPeerConnectionHandlerClient::ICEConnectionState state)); + MockWebRTCPeerConnectionHandlerClient::ICEConnectionState state)); MOCK_METHOD2( TrackIceGatheringStateChange, void(RTCPeerConnectionHandler* pc_handler, @@ -273,6 +280,7 @@ class RTCPeerConnectionHandlerTest : public ::testing::Test { pc_handler_ = CreateRTCPeerConnectionHandlerUnderTest(); mock_tracker_.reset(new NiceMock<MockPeerConnectionTracker>()); blink::WebRTCConfiguration config; + config.sdp_semantics = blink::WebRTCSdpSemantics::kPlanB; blink::WebMediaConstraints constraints; EXPECT_TRUE(pc_handler_->InitializeForTest( config, constraints, mock_tracker_.get()->AsWeakPtr())); @@ -373,14 +381,9 @@ class RTCPeerConnectionHandlerTest : public ::testing::Test { } void StopAllTracks(const blink::WebMediaStream& stream) { - blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; - stream.AudioTracks(audio_tracks); - for (const auto& track : audio_tracks) + for (const auto& track : stream.AudioTracks()) MediaStreamAudioTrack::From(track)->Stop(); - - blink::WebVector<blink::WebMediaStreamTrack> video_tracks; - stream.VideoTracks(video_tracks); - for (const auto& track : video_tracks) + for (const auto& track : stream.VideoTracks()) MediaStreamVideoTrack::GetVideoTrack(track)->Stop(); } @@ -390,22 +393,26 @@ class RTCPeerConnectionHandlerTest : public ::testing::Test { bool AddStream(const blink::WebMediaStream& web_stream) { size_t senders_size_before_add = senders_.size(); - blink::WebVector<blink::WebMediaStreamTrack> web_audio_tracks; - web_stream.AudioTracks(web_audio_tracks); - for (const auto& web_audio_track : web_audio_tracks) { - auto sender = pc_handler_->AddTrack( + for (const auto& web_audio_track : web_stream.AudioTracks()) { + auto error_or_transceiver = pc_handler_->AddTrack( web_audio_track, std::vector<blink::WebMediaStream>({web_stream})); - if (sender) { + if (error_or_transceiver.ok()) { + DCHECK_EQ( + error_or_transceiver.value()->ImplementationType(), + blink::WebRTCRtpTransceiverImplementationType::kPlanBSenderOnly); + auto sender = error_or_transceiver.value()->Sender(); senders_.push_back(std::unique_ptr<RTCRtpSender>( static_cast<RTCRtpSender*>(sender.release()))); } } - blink::WebVector<blink::WebMediaStreamTrack> web_video_tracks; - web_stream.VideoTracks(web_video_tracks); - for (const auto& web_video_track : web_video_tracks) { - auto sender = pc_handler_->AddTrack( + for (const auto& web_video_track : web_stream.VideoTracks()) { + auto error_or_transceiver = pc_handler_->AddTrack( web_video_track, std::vector<blink::WebMediaStream>({web_stream})); - if (sender) { + if (error_or_transceiver.ok()) { + DCHECK_EQ( + error_or_transceiver.value()->ImplementationType(), + blink::WebRTCRtpTransceiverImplementationType::kPlanBSenderOnly); + auto sender = error_or_transceiver.value()->Sender(); senders_.push_back(std::unique_ptr<RTCRtpSender>( static_cast<RTCRtpSender*>(sender.release()))); } @@ -424,20 +431,16 @@ class RTCPeerConnectionHandlerTest : public ::testing::Test { bool RemoveStream(const blink::WebMediaStream& web_stream) { size_t senders_size_before_remove = senders_.size(); - blink::WebVector<blink::WebMediaStreamTrack> web_audio_tracks; - web_stream.AudioTracks(web_audio_tracks); // TODO(hbos): With Unified Plan senders are not removed. // https://crbug.com/799030 - for (const auto& web_audio_track : web_audio_tracks) { + for (const auto& web_audio_track : web_stream.AudioTracks()) { auto it = FindSenderForTrack(web_audio_track); - if (it != senders_.end() && pc_handler_->RemoveTrack((*it).get())) + if (it != senders_.end() && pc_handler_->RemoveTrack((*it).get()).ok()) senders_.erase(it); } - blink::WebVector<blink::WebMediaStreamTrack> web_video_tracks; - web_stream.VideoTracks(web_video_tracks); - for (const auto& web_video_track : web_video_tracks) { + for (const auto& web_video_track : web_stream.VideoTracks()) { auto it = FindSenderForTrack(web_video_track); - if (it != senders_.end() && pc_handler_->RemoveTrack((*it).get())) + if (it != senders_.end() && pc_handler_->RemoveTrack((*it).get()).ok()) senders_.erase(it); } return senders_size_before_remove > senders_.size(); @@ -607,12 +610,12 @@ TEST_F(RTCPeerConnectionHandlerTest, NoCallbacksToClientAfterStop) { pc_handler_->observer()->OnIceConnectionChange( webrtc::PeerConnectionInterface::kIceConnectionDisconnected); - EXPECT_CALL(*mock_client_.get(), DidAddRemoteTrackForMock(_)).Times(0); + EXPECT_CALL(*mock_client_.get(), DidAddReceiverPlanBForMock(_)).Times(0); rtc::scoped_refptr<webrtc::MediaStreamInterface> remote_stream( AddRemoteMockMediaStream("remote_stream", "video", "audio")); InvokeOnAddStream(remote_stream); - EXPECT_CALL(*mock_client_.get(), DidRemoveRemoteTrackForMock(_)).Times(0); + EXPECT_CALL(*mock_client_.get(), DidRemoveReceiverPlanBForMock(_)).Times(0); InvokeOnRemoveStream(remote_stream); EXPECT_CALL(*mock_client_.get(), DidAddRemoteDataChannel(_)).Times(0); @@ -762,6 +765,7 @@ TEST_F(RTCPeerConnectionHandlerTest, setRemoteDescriptionParseError) { TEST_F(RTCPeerConnectionHandlerTest, setConfiguration) { blink::WebRTCConfiguration config; + config.sdp_semantics = blink::WebRTCSdpSemantics::kPlanB; EXPECT_CALL(*mock_tracker_.get(), TrackSetConfiguration(pc_handler_.get(), _)); @@ -775,6 +779,7 @@ TEST_F(RTCPeerConnectionHandlerTest, setConfiguration) { // blink error and false is returned. TEST_F(RTCPeerConnectionHandlerTest, setConfigurationError) { blink::WebRTCConfiguration config; + config.sdp_semantics = blink::WebRTCSdpSemantics::kPlanB; mock_peer_connection_->set_setconfiguration_error_type( webrtc::RTCErrorType::INVALID_MODIFICATION); @@ -802,22 +807,25 @@ TEST_F(RTCPeerConnectionHandlerTest, addAndRemoveStream) { blink::WebMediaStream local_stream( CreateLocalMediaStream(stream_label)); - EXPECT_CALL(*mock_tracker_.get(), - TrackAddStream(pc_handler_.get(), _, - PeerConnectionTracker::SOURCE_LOCAL)); - EXPECT_CALL(*mock_tracker_.get(), - TrackRemoveStream(pc_handler_.get(), _, - PeerConnectionTracker::SOURCE_LOCAL)); + EXPECT_CALL( + *mock_tracker_.get(), + TrackAddTransceiver( + pc_handler_.get(), + PeerConnectionTracker::TransceiverUpdatedReason::kAddTrack, _, _)) + .Times(2); + EXPECT_CALL( + *mock_tracker_.get(), + TrackRemoveTransceiver( + pc_handler_.get(), + PeerConnectionTracker::TransceiverUpdatedReason::kRemoveTrack, _, _)) + .Times(2); EXPECT_TRUE(AddStream(local_stream)); EXPECT_EQ(stream_label, mock_peer_connection_->stream_label()); - EXPECT_EQ(1u, - mock_peer_connection_->local_streams()->at(0)->GetAudioTracks().size()); - EXPECT_EQ(1u, - mock_peer_connection_->local_streams()->at(0)->GetVideoTracks().size()); + EXPECT_EQ(2u, mock_peer_connection_->GetSenders().size()); EXPECT_FALSE(AddStream(local_stream)); EXPECT_TRUE(RemoveStream(local_stream)); - EXPECT_EQ(0u, mock_peer_connection_->local_streams()->count()); + EXPECT_EQ(0u, mock_peer_connection_->GetSenders().size()); StopAllTracks(local_stream); } @@ -827,14 +835,14 @@ TEST_F(RTCPeerConnectionHandlerTest, addStreamWithStoppedAudioAndVideoTrack) { blink::WebMediaStream local_stream( CreateLocalMediaStream(stream_label)); - blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; - local_stream.AudioTracks(audio_tracks); + blink::WebVector<blink::WebMediaStreamTrack> audio_tracks = + local_stream.AudioTracks(); MediaStreamAudioSource* native_audio_source = MediaStreamAudioSource::From(audio_tracks[0].Source()); native_audio_source->StopSource(); - blink::WebVector<blink::WebMediaStreamTrack> video_tracks; - local_stream.VideoTracks(video_tracks); + blink::WebVector<blink::WebMediaStreamTrack> video_tracks = + local_stream.VideoTracks(); MediaStreamVideoSource* native_video_source = static_cast<MediaStreamVideoSource*>( video_tracks[0].Source().GetExtraData()); @@ -842,12 +850,7 @@ TEST_F(RTCPeerConnectionHandlerTest, addStreamWithStoppedAudioAndVideoTrack) { EXPECT_TRUE(AddStream(local_stream)); EXPECT_EQ(stream_label, mock_peer_connection_->stream_label()); - EXPECT_EQ( - 1u, - mock_peer_connection_->local_streams()->at(0)->GetAudioTracks().size()); - EXPECT_EQ( - 1u, - mock_peer_connection_->local_streams()->at(0)->GetVideoTracks().size()); + EXPECT_EQ(2u, mock_peer_connection_->GetSenders().size()); StopAllTracks(local_stream); } @@ -876,8 +879,8 @@ TEST_F(RTCPeerConnectionHandlerTest, GetStatsWithLocalSelector) { blink::WebMediaStream local_stream( CreateLocalMediaStream("local_stream")); EXPECT_TRUE(AddStream(local_stream)); - blink::WebVector<blink::WebMediaStreamTrack> tracks; - local_stream.AudioTracks(tracks); + blink::WebVector<blink::WebMediaStreamTrack> tracks = + local_stream.AudioTracks(); ASSERT_LE(1ul, tracks.size()); scoped_refptr<MockRTCStatsRequest> request( @@ -890,45 +893,13 @@ TEST_F(RTCPeerConnectionHandlerTest, GetStatsWithLocalSelector) { StopAllTracks(local_stream); } -// TODO(hbos): Enable when not mocking or remove test. https://crbug.com/788659 -TEST_F(RTCPeerConnectionHandlerTest, DISABLED_GetStatsWithRemoteSelector) { - rtc::scoped_refptr<webrtc::MediaStreamInterface> remote_stream( - AddRemoteMockMediaStream("remote_stream", "video", "audio")); - std::vector<std::unique_ptr<blink::WebRTCRtpReceiver>> receivers; - // Grab the added receivers and media stream when it's been successfully added - // to the PC. - blink::WebMediaStream webkit_stream; - EXPECT_CALL(*mock_client_.get(), DidAddRemoteTrackForMock(_)) - .WillRepeatedly( - Invoke([&webkit_stream, &receivers]( - std::unique_ptr<blink::WebRTCRtpReceiver>* receiver) { - webkit_stream = (*receiver)->Streams()[0]; - receivers.push_back(std::move(*receiver)); - })); - InvokeOnAddStream(remote_stream); - RunMessageLoopsUntilIdle(); - EXPECT_TRUE(HasReceiverForEveryTrack(remote_stream, receivers)); - - blink::WebVector<blink::WebMediaStreamTrack> tracks; - webkit_stream.AudioTracks(tracks); - ASSERT_LE(1ul, tracks.size()); - - scoped_refptr<MockRTCStatsRequest> request( - new rtc::RefCountedObject<MockRTCStatsRequest>()); - request->setSelector(tracks[0]); - pc_handler_->getStats(request.get()); - RunMessageLoopsUntilIdle(); - EXPECT_EQ(1, request->result()->report_count()); -} - TEST_F(RTCPeerConnectionHandlerTest, GetStatsWithBadSelector) { // The setup is the same as GetStatsWithLocalSelector, but the stream is not // added to the PeerConnection. blink::WebMediaStream local_stream( CreateLocalMediaStream("local_stream_2")); - blink::WebVector<blink::WebMediaStreamTrack> tracks; - - local_stream.AudioTracks(tracks); + blink::WebVector<blink::WebMediaStreamTrack> tracks = + local_stream.AudioTracks(); blink::WebMediaStreamTrack component = tracks[0]; mock_peer_connection_->SetGetStatsResult(false); @@ -1063,67 +1034,6 @@ TEST_F(RTCPeerConnectionHandlerTest, GetRTCStats) { EXPECT_EQ(defined_stats_count, 1); } -TEST_F(RTCPeerConnectionHandlerTest, OnSignalingChange) { - testing::InSequence sequence; - - webrtc::PeerConnectionInterface::SignalingState new_state = - webrtc::PeerConnectionInterface::kHaveRemoteOffer; - EXPECT_CALL( - *mock_tracker_.get(), - TrackSignalingStateChange( - pc_handler_.get(), - WebRTCPeerConnectionHandlerClient::kSignalingStateHaveRemoteOffer)); - EXPECT_CALL( - *mock_client_.get(), - DidChangeSignalingState( - WebRTCPeerConnectionHandlerClient::kSignalingStateHaveRemoteOffer)); - pc_handler_->observer()->OnSignalingChange(new_state); - - new_state = webrtc::PeerConnectionInterface::kHaveLocalPrAnswer; - EXPECT_CALL( - *mock_tracker_.get(), - TrackSignalingStateChange( - pc_handler_.get(), - WebRTCPeerConnectionHandlerClient::kSignalingStateHaveLocalPrAnswer)); - EXPECT_CALL( - *mock_client_.get(), - DidChangeSignalingState( - WebRTCPeerConnectionHandlerClient::kSignalingStateHaveLocalPrAnswer)); - pc_handler_->observer()->OnSignalingChange(new_state); - - new_state = webrtc::PeerConnectionInterface::kHaveLocalOffer; - EXPECT_CALL( - *mock_tracker_.get(), - TrackSignalingStateChange( - pc_handler_.get(), - WebRTCPeerConnectionHandlerClient::kSignalingStateHaveLocalOffer)); - EXPECT_CALL( - *mock_client_.get(), - DidChangeSignalingState( - WebRTCPeerConnectionHandlerClient::kSignalingStateHaveLocalOffer)); - pc_handler_->observer()->OnSignalingChange(new_state); - - new_state = webrtc::PeerConnectionInterface::kHaveRemotePrAnswer; - EXPECT_CALL(*mock_tracker_.get(), - TrackSignalingStateChange(pc_handler_.get(), - WebRTCPeerConnectionHandlerClient:: - kSignalingStateHaveRemotePrAnswer)); - EXPECT_CALL(*mock_client_.get(), - DidChangeSignalingState(WebRTCPeerConnectionHandlerClient:: - kSignalingStateHaveRemotePrAnswer)); - pc_handler_->observer()->OnSignalingChange(new_state); - - new_state = webrtc::PeerConnectionInterface::kClosed; - EXPECT_CALL(*mock_tracker_.get(), - TrackSignalingStateChange( - pc_handler_.get(), - WebRTCPeerConnectionHandlerClient::kSignalingStateClosed)); - EXPECT_CALL(*mock_client_.get(), - DidChangeSignalingState( - WebRTCPeerConnectionHandlerClient::kSignalingStateClosed)); - pc_handler_->observer()->OnSignalingChange(new_state); -} - TEST_F(RTCPeerConnectionHandlerTest, OnIceConnectionChange) { testing::InSequence sequence; @@ -1263,28 +1173,27 @@ TEST_F(RTCPeerConnectionHandlerTest, DISABLED_OnAddAndOnRemoveStream) { AddRemoteMockMediaStream("remote_stream", "video", "audio")); // Grab the added receivers when it's been successfully added to the PC. std::vector<std::unique_ptr<blink::WebRTCRtpReceiver>> receivers_added; - EXPECT_CALL(*mock_client_.get(), DidAddRemoteTrackForMock(_)) + EXPECT_CALL(*mock_client_.get(), DidAddReceiverPlanBForMock(_)) .WillRepeatedly( Invoke([&receivers_added]( std::unique_ptr<blink::WebRTCRtpReceiver>* receiver) { receivers_added.push_back(std::move(*receiver)); })); - EXPECT_CALL(*mock_tracker_.get(), - TrackAddStream(pc_handler_.get(), - testing::Property( - &blink::WebMediaStream::Id, - blink::WebString::FromASCII("remote_stream")), - PeerConnectionTracker::SOURCE_REMOTE)); + EXPECT_CALL( + *mock_tracker_.get(), + TrackAddTransceiver( + pc_handler_.get(), + PeerConnectionTracker::TransceiverUpdatedReason::kAddTrack, _, _)) + .Times(2); // Grab the removed receivers when it's been successfully added to the PC. std::vector<std::unique_ptr<blink::WebRTCRtpReceiver>> receivers_removed; EXPECT_CALL( *mock_tracker_.get(), - TrackRemoveStream( + TrackRemoveTransceiver( pc_handler_.get(), - testing::Property(&blink::WebMediaStream::Id, - blink::WebString::FromASCII("remote_stream")), - PeerConnectionTracker::SOURCE_REMOTE)); - EXPECT_CALL(*mock_client_.get(), DidRemoveRemoteTrackForMock(_)) + PeerConnectionTracker::TransceiverUpdatedReason::kRemoveTrack, _, _)) + .Times(2); + EXPECT_CALL(*mock_client_.get(), DidRemoveReceiverPlanBForMock(_)) .WillRepeatedly( Invoke([&receivers_removed]( std::unique_ptr<blink::WebRTCRtpReceiver>* receiver) { @@ -1303,211 +1212,6 @@ TEST_F(RTCPeerConnectionHandlerTest, DISABLED_OnAddAndOnRemoveStream) { EXPECT_EQ(receivers_added[1]->Id(), receivers_removed[1]->Id()); } -// This test that WebKit is notified about remote track state changes. -// TODO(hbos): Enable when not mocking or remove test. https://crbug.com/788659 -TEST_F(RTCPeerConnectionHandlerTest, DISABLED_RemoteTrackState) { - rtc::scoped_refptr<webrtc::MediaStreamInterface> remote_stream( - AddRemoteMockMediaStream("remote_stream", "video", "audio")); - std::vector<std::unique_ptr<blink::WebRTCRtpReceiver>> receivers; - // Grab the added receivers and media stream when it's been successfully added - // to the PC. - blink::WebMediaStream webkit_stream; - EXPECT_CALL(*mock_client_.get(), DidAddRemoteTrackForMock(_)) - .WillRepeatedly( - Invoke([&webkit_stream, &receivers]( - std::unique_ptr<blink::WebRTCRtpReceiver>* receiver) { - webkit_stream = (*receiver)->Streams()[0]; - receivers.push_back(std::move(*receiver)); - })); - InvokeOnAddStream(remote_stream); - RunMessageLoopsUntilIdle(); - EXPECT_TRUE(HasReceiverForEveryTrack(remote_stream, receivers)); - - blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; - webkit_stream.AudioTracks(audio_tracks); - EXPECT_EQ(blink::WebMediaStreamSource::kReadyStateLive, - audio_tracks[0].Source().GetReadyState()); - - blink::WebVector<blink::WebMediaStreamTrack> video_tracks; - webkit_stream.VideoTracks(video_tracks); - EXPECT_EQ(blink::WebMediaStreamSource::kReadyStateLive, - video_tracks[0].Source().GetReadyState()); - - InvokeOnSignalingThread( - base::Bind(&MockWebRtcAudioTrack::SetEnded, - base::Unretained(static_cast<MockWebRtcAudioTrack*>( - remote_stream->GetAudioTracks()[0].get())))); - EXPECT_EQ(blink::WebMediaStreamSource::kReadyStateEnded, - audio_tracks[0].Source().GetReadyState()); - - InvokeOnSignalingThread( - base::Bind(&MockWebRtcVideoTrack::SetEnded, - base::Unretained(static_cast<MockWebRtcVideoTrack*>( - remote_stream->GetVideoTracks()[0].get())))); - EXPECT_EQ(blink::WebMediaStreamSource::kReadyStateEnded, - video_tracks[0].Source().GetReadyState()); -} - -// TODO(hbos): Enable when not mocking or remove test. https://crbug.com/788659 -TEST_F(RTCPeerConnectionHandlerTest, - DISABLED_RemoveAndAddAudioTrackFromRemoteStream) { - rtc::scoped_refptr<webrtc::MediaStreamInterface> remote_stream( - AddRemoteMockMediaStream("remote_stream", "video", "audio")); - std::vector<std::unique_ptr<blink::WebRTCRtpReceiver>> receivers; - // Grab the added receivers and media stream when it's been successfully added - // to the PC. - blink::WebMediaStream webkit_stream; - EXPECT_CALL(*mock_client_.get(), DidAddRemoteTrackForMock(_)) - .WillRepeatedly( - Invoke([&webkit_stream, &receivers]( - std::unique_ptr<blink::WebRTCRtpReceiver>* receiver) { - webkit_stream = (*receiver)->Streams()[0]; - receivers.push_back(std::move(*receiver)); - })); - InvokeOnAddStream(remote_stream); - RunMessageLoopsUntilIdle(); - EXPECT_TRUE(HasReceiverForEveryTrack(remote_stream, receivers)); - - { - // Test in a small scope so that |audio_tracks| don't hold on to destroyed - // source later. - blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; - webkit_stream.AudioTracks(audio_tracks); - EXPECT_EQ(1u, audio_tracks.size()); - } - - // Remove the Webrtc audio track from the Webrtc MediaStream. - scoped_refptr<webrtc::AudioTrackInterface> webrtc_track = - remote_stream->GetAudioTracks()[0].get(); - InvokeRemoveTrack(remote_stream, webrtc_track.get()); - - { - blink::WebVector<blink::WebMediaStreamTrack> modified_audio_tracks1; - webkit_stream.AudioTracks(modified_audio_tracks1); - EXPECT_EQ(0u, modified_audio_tracks1.size()); - } - - blink::WebHeap::CollectGarbageForTesting(); - - // Add the WebRtc audio track again. - InvokeAddTrack(remote_stream, webrtc_track.get()); - blink::WebVector<blink::WebMediaStreamTrack> modified_audio_tracks2; - webkit_stream.AudioTracks(modified_audio_tracks2); - EXPECT_EQ(1u, modified_audio_tracks2.size()); -} - -// TODO(hbos): Enable when not mocking or remove test. https://crbug.com/788659 -TEST_F(RTCPeerConnectionHandlerTest, - DISABLED_RemoveAndAddVideoTrackFromRemoteStream) { - rtc::scoped_refptr<webrtc::MediaStreamInterface> remote_stream( - AddRemoteMockMediaStream("remote_stream", "video", "audio")); - std::vector<std::unique_ptr<blink::WebRTCRtpReceiver>> receivers; - // Grab the added receivers and media stream when it's been successfully added - // to the PC. - blink::WebMediaStream webkit_stream; - EXPECT_CALL(*mock_client_.get(), DidAddRemoteTrackForMock(_)) - .WillRepeatedly( - Invoke([&webkit_stream, &receivers]( - std::unique_ptr<blink::WebRTCRtpReceiver>* receiver) { - webkit_stream = (*receiver)->Streams()[0]; - receivers.push_back(std::move(*receiver)); - })); - InvokeOnAddStream(remote_stream); - RunMessageLoopsUntilIdle(); - EXPECT_TRUE(HasReceiverForEveryTrack(remote_stream, receivers)); - - { - // Test in a small scope so that |video_tracks| don't hold on to destroyed - // source later. - blink::WebVector<blink::WebMediaStreamTrack> video_tracks; - webkit_stream.VideoTracks(video_tracks); - EXPECT_EQ(1u, video_tracks.size()); - } - - // Remove the Webrtc video track from the Webrtc MediaStream. - scoped_refptr<webrtc::VideoTrackInterface> webrtc_track = - remote_stream->GetVideoTracks()[0].get(); - InvokeRemoveTrack(remote_stream, webrtc_track.get()); - RunMessageLoopsUntilIdle(); - { - blink::WebVector<blink::WebMediaStreamTrack> modified_video_tracks1; - webkit_stream.VideoTracks(modified_video_tracks1); - EXPECT_EQ(0u, modified_video_tracks1.size()); - } - - blink::WebHeap::CollectGarbageForTesting(); - - // Add the WebRtc video track again. - InvokeAddTrack(remote_stream, webrtc_track.get()); - RunMessageLoopsUntilIdle(); - blink::WebVector<blink::WebMediaStreamTrack> modified_video_tracks2; - webkit_stream.VideoTracks(modified_video_tracks2); - EXPECT_EQ(1u, modified_video_tracks2.size()); -} - -// TODO(hbos): Enable when not mocking or remove test. https://crbug.com/788659 -TEST_F(RTCPeerConnectionHandlerTest, - DISABLED_RemoveAndAddTracksFromRemoteStream) { - rtc::scoped_refptr<webrtc::MediaStreamInterface> remote_stream( - AddRemoteMockMediaStream("remote_stream", "video", "audio")); - std::vector<std::unique_ptr<blink::WebRTCRtpReceiver>> receivers; - // Grab the added receivers and media stream when it's been successfully added - // to the PC. - blink::WebMediaStream webkit_stream; - EXPECT_CALL(*mock_client_.get(), DidAddRemoteTrackForMock(_)) - .WillRepeatedly( - Invoke([&webkit_stream, &receivers]( - std::unique_ptr<blink::WebRTCRtpReceiver>* receiver) { - webkit_stream = (*receiver)->Streams()[0]; - receivers.push_back(std::move(*receiver)); - })); - InvokeOnAddStream(remote_stream); - RunMessageLoopsUntilIdle(); - EXPECT_TRUE(HasReceiverForEveryTrack(remote_stream, receivers)); - - { - // Test in a small scope so that |audio_tracks| don't hold on to destroyed - // source later. - blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; - webkit_stream.AudioTracks(audio_tracks); - EXPECT_EQ(1u, audio_tracks.size()); - blink::WebVector<blink::WebMediaStreamTrack> video_tracks; - webkit_stream.VideoTracks(video_tracks); - EXPECT_EQ(1u, video_tracks.size()); - } - - // Remove the Webrtc tracks from the MediaStream. - auto audio_track = remote_stream->GetAudioTracks()[0]; - InvokeRemoveTrack(remote_stream, audio_track.get()); - auto video_track = remote_stream->GetVideoTracks()[0]; - InvokeRemoveTrack(remote_stream, video_track.get()); - RunMessageLoopsUntilIdle(); - - { - blink::WebVector<blink::WebMediaStreamTrack> modified_audio_tracks; - webkit_stream.AudioTracks(modified_audio_tracks); - EXPECT_EQ(0u, modified_audio_tracks.size()); - blink::WebVector<blink::WebMediaStreamTrack> modified_video_tracks; - webkit_stream.VideoTracks(modified_video_tracks); - EXPECT_EQ(0u, modified_video_tracks.size()); - } - - blink::WebHeap::CollectGarbageForTesting(); - - // Add the tracks again. - InvokeAddTrack(remote_stream, audio_track.get()); - InvokeAddTrack(remote_stream, video_track.get()); - - blink::WebHeap::CollectGarbageForTesting(); - - blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; - webkit_stream.AudioTracks(audio_tracks); - EXPECT_EQ(1u, audio_tracks.size()); - blink::WebVector<blink::WebMediaStreamTrack> video_tracks; - webkit_stream.VideoTracks(video_tracks); - EXPECT_EQ(1u, video_tracks.size()); -} - TEST_F(RTCPeerConnectionHandlerTest, OnIceCandidate) { testing::InSequence sequence; EXPECT_CALL(*mock_tracker_.get(), diff --git a/chromium/content/renderer/media/webrtc/rtc_rtp_receiver.cc b/chromium/content/renderer/media/webrtc/rtc_rtp_receiver.cc index a988bd10bb5..200b00beb9e 100644 --- a/chromium/content/renderer/media/webrtc/rtc_rtp_receiver.cc +++ b/chromium/content/renderer/media/webrtc/rtc_rtp_receiver.cc @@ -11,6 +11,96 @@ namespace content { +RtpReceiverState::RtpReceiverState( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner, + scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver, + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref, + std::vector<std::string> stream_id) + : main_task_runner_(std::move(main_task_runner)), + signaling_task_runner_(std::move(signaling_task_runner)), + webrtc_receiver_(std::move(webrtc_receiver)), + is_initialized_(false), + track_ref_(std::move(track_ref)), + stream_ids_(std::move(stream_id)) { + DCHECK(main_task_runner_); + DCHECK(signaling_task_runner_); + DCHECK(webrtc_receiver_); + DCHECK(track_ref_); +} + +RtpReceiverState::RtpReceiverState(RtpReceiverState&& other) + : main_task_runner_(other.main_task_runner_), + signaling_task_runner_(other.signaling_task_runner_), + webrtc_receiver_(std::move(other.webrtc_receiver_)), + is_initialized_(other.is_initialized_), + track_ref_(std::move(other.track_ref_)), + stream_ids_(std::move(other.stream_ids_)) { + // Explicitly null |other|'s task runners for use in destructor. + other.main_task_runner_ = nullptr; + other.signaling_task_runner_ = nullptr; +} + +RtpReceiverState::~RtpReceiverState() { + // It's OK to not be on the main thread if this state has been moved, in which + // case |main_task_runner_| is null. + DCHECK(!main_task_runner_ || main_task_runner_->BelongsToCurrentThread()); +} + +RtpReceiverState& RtpReceiverState::operator=(RtpReceiverState&& other) { + DCHECK_EQ(main_task_runner_, other.main_task_runner_); + DCHECK_EQ(signaling_task_runner_, other.signaling_task_runner_); + // Explicitly null |other|'s task runners for use in destructor. + other.main_task_runner_ = nullptr; + other.signaling_task_runner_ = nullptr; + webrtc_receiver_ = std::move(other.webrtc_receiver_); + track_ref_ = std::move(other.track_ref_); + stream_ids_ = std::move(other.stream_ids_); + return *this; +} + +bool RtpReceiverState::is_initialized() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return is_initialized_; +} + +void RtpReceiverState::Initialize() { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + if (is_initialized_) + return; + track_ref_->InitializeOnMainThread(); + is_initialized_ = true; +} + +scoped_refptr<base::SingleThreadTaskRunner> RtpReceiverState::main_task_runner() + const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return main_task_runner_; +} + +scoped_refptr<base::SingleThreadTaskRunner> +RtpReceiverState::signaling_task_runner() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return signaling_task_runner_; +} + +scoped_refptr<webrtc::RtpReceiverInterface> RtpReceiverState::webrtc_receiver() + const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return webrtc_receiver_; +} + +const std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>& +RtpReceiverState::track_ref() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return track_ref_; +} + +const std::vector<std::string>& RtpReceiverState::stream_ids() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return stream_ids_; +} + class RTCRtpReceiver::RTCRtpReceiverInternal : public base::RefCountedThreadSafe< RTCRtpReceiver::RTCRtpReceiverInternal, @@ -18,37 +108,34 @@ class RTCRtpReceiver::RTCRtpReceiverInternal public: RTCRtpReceiverInternal( scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection, - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<base::SingleThreadTaskRunner> signaling_thread, - rtc::scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver, - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> - track_adapter, - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_adapter_refs) + RtpReceiverState state) : native_peer_connection_(std::move(native_peer_connection)), - main_thread_(std::move(main_thread)), - signaling_thread_(std::move(signaling_thread)), - webrtc_receiver_(std::move(webrtc_receiver)), - track_adapter_(std::move(track_adapter)), - stream_adapter_refs_(std::move(stream_adapter_refs)) { - DCHECK(webrtc_receiver_); - DCHECK(track_adapter_); + main_task_runner_(state.main_task_runner()), + signaling_task_runner_(state.signaling_task_runner()), + webrtc_receiver_(state.webrtc_receiver()), + state_(std::move(state)) { + DCHECK(native_peer_connection_); + DCHECK(state_.is_initialized()); } - const blink::WebMediaStreamTrack& Track() const { - return track_adapter_->web_track(); + const RtpReceiverState& state() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return state_; } - blink::WebVector<blink::WebMediaStream> Streams() const { - blink::WebVector<blink::WebMediaStream> web_streams( - stream_adapter_refs_.size()); - for (size_t i = 0; i < stream_adapter_refs_.size(); ++i) - web_streams[i] = stream_adapter_refs_[i]->adapter().web_stream(); - return web_streams; + void set_state(RtpReceiverState state) { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + DCHECK(state.main_task_runner() == main_task_runner_); + DCHECK(state.signaling_task_runner() == signaling_task_runner_); + DCHECK(state.webrtc_receiver() == webrtc_receiver_); + DCHECK(state.is_initialized()); + state_ = std::move(state); } blink::WebVector<std::unique_ptr<blink::WebRTCRtpContributingSource>> GetSources() { + // The webrtc_recever_ is a proxy, so this is a blocking call to the webrtc + // signalling thread. auto webrtc_sources = webrtc_receiver_->GetSources(); blink::WebVector<std::unique_ptr<blink::WebRTCRtpContributingSource>> sources(webrtc_sources.size()); @@ -60,64 +147,34 @@ class RTCRtpReceiver::RTCRtpReceiverInternal } void GetStats(std::unique_ptr<blink::WebRTCStatsReportCallback> callback) { - signaling_thread_->PostTask( + signaling_task_runner_->PostTask( FROM_HERE, base::BindOnce(&RTCRtpReceiverInternal::GetStatsOnSignalingThread, this, std::move(callback))); } - webrtc::RtpReceiverInterface* webrtc_receiver() const { - return webrtc_receiver_.get(); - } - - const webrtc::MediaStreamTrackInterface& webrtc_track() const { - DCHECK(track_adapter_->webrtc_track()); - return *track_adapter_->webrtc_track(); - } - - bool HasStream(const webrtc::MediaStreamInterface* webrtc_stream) const { - for (const auto& stream_adapter : stream_adapter_refs_) { - if (webrtc_stream == stream_adapter->adapter().webrtc_stream().get()) - return true; - } - return false; - } - - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - StreamAdapterRefs() const { - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_adapter_copies; - stream_adapter_copies.reserve(stream_adapter_refs_.size()); - for (const auto& stream_adapter : stream_adapter_refs_) { - stream_adapter_copies.push_back(stream_adapter->Copy()); - } - return stream_adapter_copies; - } - private: friend struct RTCRtpReceiver::RTCRtpReceiverInternalTraits; - ~RTCRtpReceiverInternal() { DCHECK(main_thread_->BelongsToCurrentThread()); } + ~RTCRtpReceiverInternal() { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + } void GetStatsOnSignalingThread( std::unique_ptr<blink::WebRTCStatsReportCallback> callback) { - native_peer_connection_->GetStats(webrtc_receiver_, - RTCStatsCollectorCallbackImpl::Create( - main_thread_, std::move(callback))); + native_peer_connection_->GetStats( + webrtc_receiver_.get(), RTCStatsCollectorCallbackImpl::Create( + main_task_runner_, std::move(callback))); } const scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection_; - const scoped_refptr<base::SingleThreadTaskRunner> main_thread_; - const scoped_refptr<base::SingleThreadTaskRunner> signaling_thread_; - const rtc::scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver_; - // The track adapter is the glue between blink and webrtc layer tracks. - // Keeping a reference to the adapter ensures it is not disposed, as is - // required as long as the webrtc layer track is in use by the receiver. - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_adapter_; - // Similarly, references needs to be kept to the stream adapters of streams - // associated with the receiver. - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_adapter_refs_; + // Task runners and webrtc receiver: Same information as stored in + // |state_| but const and safe to touch on the signaling thread to + // avoid race with set_state(). + const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; + const scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner_; + const scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver_; + RtpReceiverState state_; }; struct RTCRtpReceiver::RTCRtpReceiverInternalTraits { @@ -128,8 +185,8 @@ struct RTCRtpReceiver::RTCRtpReceiverInternalTraits { static void Destruct(const RTCRtpReceiverInternal* receiver) { // RTCRtpReceiverInternal owns AdapterRefs which have to be destroyed on the // main thread, this ensures delete always happens there. - if (!receiver->main_thread_->BelongsToCurrentThread()) { - receiver->main_thread_->PostTask( + if (!receiver->main_task_runner_->BelongsToCurrentThread()) { + receiver->main_task_runner_->PostTask( FROM_HERE, base::BindOnce( &RTCRtpReceiver::RTCRtpReceiverInternalTraits::Destruct, @@ -147,18 +204,9 @@ uintptr_t RTCRtpReceiver::getId( RTCRtpReceiver::RTCRtpReceiver( scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection, - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<base::SingleThreadTaskRunner> signaling_thread, - rtc::scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver, - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_adapter, - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_adapter_refs) + RtpReceiverState state) : internal_(new RTCRtpReceiverInternal(std::move(native_peer_connection), - std::move(main_thread), - std::move(signaling_thread), - std::move(webrtc_receiver), - std::move(track_adapter), - std::move(stream_adapter_refs))) {} + std::move(state))) {} RTCRtpReceiver::RTCRtpReceiver(const RTCRtpReceiver& other) : internal_(other.internal_) {} @@ -170,20 +218,32 @@ RTCRtpReceiver& RTCRtpReceiver::operator=(const RTCRtpReceiver& other) { return *this; } -std::unique_ptr<RTCRtpReceiver> RTCRtpReceiver::ShallowCopy() const { +const RtpReceiverState& RTCRtpReceiver::state() const { + return internal_->state(); +} + +void RTCRtpReceiver::set_state(RtpReceiverState state) { + internal_->set_state(std::move(state)); +} + +std::unique_ptr<blink::WebRTCRtpReceiver> RTCRtpReceiver::ShallowCopy() const { return std::make_unique<RTCRtpReceiver>(*this); } uintptr_t RTCRtpReceiver::Id() const { - return getId(internal_->webrtc_receiver()); + return getId(internal_->state().webrtc_receiver().get()); } const blink::WebMediaStreamTrack& RTCRtpReceiver::Track() const { - return internal_->Track(); + return internal_->state().track_ref()->web_track(); } -blink::WebVector<blink::WebMediaStream> RTCRtpReceiver::Streams() const { - return internal_->Streams(); +blink::WebVector<blink::WebString> RTCRtpReceiver::StreamIds() const { + const auto& stream_ids = internal_->state().stream_ids(); + blink::WebVector<blink::WebString> web_stream_ids(stream_ids.size()); + for (size_t i = 0; i < stream_ids.size(); ++i) + web_stream_ids[i] = blink::WebString::FromUTF8(stream_ids[i]); + return web_stream_ids; } blink::WebVector<std::unique_ptr<blink::WebRTCRtpContributingSource>> @@ -196,22 +256,66 @@ void RTCRtpReceiver::GetStats( internal_->GetStats(std::move(callback)); } -webrtc::RtpReceiverInterface* RTCRtpReceiver::webrtc_receiver() const { - return internal_->webrtc_receiver(); +RTCRtpReceiverOnlyTransceiver::RTCRtpReceiverOnlyTransceiver( + std::unique_ptr<blink::WebRTCRtpReceiver> receiver) + : receiver_(std::move(receiver)) { + DCHECK(receiver_); +} + +RTCRtpReceiverOnlyTransceiver::~RTCRtpReceiverOnlyTransceiver() {} + +blink::WebRTCRtpTransceiverImplementationType +RTCRtpReceiverOnlyTransceiver::ImplementationType() const { + return blink::WebRTCRtpTransceiverImplementationType::kPlanBReceiverOnly; +} + +uintptr_t RTCRtpReceiverOnlyTransceiver::Id() const { + NOTIMPLEMENTED(); + return 0u; +} + +blink::WebString RTCRtpReceiverOnlyTransceiver::Mid() const { + NOTIMPLEMENTED(); + return blink::WebString(); +} + +std::unique_ptr<blink::WebRTCRtpSender> RTCRtpReceiverOnlyTransceiver::Sender() + const { + NOTIMPLEMENTED(); + return nullptr; +} + +std::unique_ptr<blink::WebRTCRtpReceiver> +RTCRtpReceiverOnlyTransceiver::Receiver() const { + return receiver_->ShallowCopy(); +} + +bool RTCRtpReceiverOnlyTransceiver::Stopped() const { + NOTIMPLEMENTED(); + return false; +} + +webrtc::RtpTransceiverDirection RTCRtpReceiverOnlyTransceiver::Direction() + const { + NOTIMPLEMENTED(); + return webrtc::RtpTransceiverDirection::kSendOnly; } -const webrtc::MediaStreamTrackInterface& RTCRtpReceiver::webrtc_track() const { - return internal_->webrtc_track(); +void RTCRtpReceiverOnlyTransceiver::SetDirection( + webrtc::RtpTransceiverDirection direction) { + NOTIMPLEMENTED(); } -bool RTCRtpReceiver::HasStream( - const webrtc::MediaStreamInterface* webrtc_stream) const { - return internal_->HasStream(webrtc_stream); +base::Optional<webrtc::RtpTransceiverDirection> +RTCRtpReceiverOnlyTransceiver::CurrentDirection() const { + NOTIMPLEMENTED(); + return webrtc::RtpTransceiverDirection::kSendOnly; } -std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> -RTCRtpReceiver::StreamAdapterRefs() const { - return internal_->StreamAdapterRefs(); +base::Optional<webrtc::RtpTransceiverDirection> +RTCRtpReceiverOnlyTransceiver::FiredDirection() const { + NOTIMPLEMENTED(); + return webrtc::RtpTransceiverDirection::kSendOnly; } } // namespace content diff --git a/chromium/content/renderer/media/webrtc/rtc_rtp_receiver.h b/chromium/content/renderer/media/webrtc/rtc_rtp_receiver.h index 29420ae5220..1eb373ad13f 100644 --- a/chromium/content/renderer/media/webrtc/rtc_rtp_receiver.h +++ b/chromium/content/renderer/media/webrtc/rtc_rtp_receiver.h @@ -9,17 +9,88 @@ #include "base/memory/ref_counted.h" #include "base/single_thread_task_runner.h" #include "content/common/content_export.h" -#include "content/renderer/media/webrtc/webrtc_media_stream_adapter_map.h" #include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h" #include "third_party/blink/public/platform/web_media_stream.h" #include "third_party/blink/public/platform/web_media_stream_track.h" #include "third_party/blink/public/platform/web_rtc_rtp_receiver.h" +#include "third_party/blink/public/platform/web_rtc_rtp_transceiver.h" #include "third_party/webrtc/api/mediastreaminterface.h" #include "third_party/webrtc/api/peerconnectioninterface.h" #include "third_party/webrtc/api/rtpreceiverinterface.h" namespace content { +// This class represents the state of a receiver; a snapshot of what a +// webrtc-layer receiver looked like when it was inspected on the signaling +// thread such that this information can be moved to the main thread in a single +// PostTask. It is used to surface state changes to make the blink-layer +// receiver up-to-date. +// +// Blink objects live on the main thread and webrtc objects live on the +// signaling thread. If multiple asynchronous operations begin execution on the +// main thread they are posted and executed in order on the signaling thread. +// For example, operation A and operation B are called in JavaScript. When A is +// done on the signaling thread, webrtc object states will be updated. A +// callback is posted to the main thread so that blink objects can be updated to +// match the result of operation A. But if callback A tries to inspect the +// webrtc objects from the main thread this requires posting back to the +// signaling thread and waiting, which also includes waiting for the previously +// posted task: operation B. Inspecting the webrtc object like this does not +// guarantee you to get the state of operation A. +// +// As such, all state changes associated with an operation have to be surfaced +// in the same callback. This includes copying any states into a separate object +// so that it can be inspected on the main thread without any additional thread +// hops. +// +// The RtpReceiverState is a snapshot of what the webrtc::RtpReceiverInterface +// looked like when the RtpReceiverState was created on the signaling thread. It +// also takes care of initializing track adapters, such that we have access to a +// blink track corresponding to the webrtc track of the receiver. +// +// Except for initialization logic and operator=(), the RtpReceiverState is +// immutable and only accessible on the main thread. +// +// TODO(hbos): [Onion Soup] When the sender implementation is moved to blink +// this will be part of the blink sender instead of the content sender. +// https://crbug.com/787254 +class CONTENT_EXPORT RtpReceiverState { + public: + RtpReceiverState( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner, + scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver, + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref, + std::vector<std::string> stream_ids); + RtpReceiverState(RtpReceiverState&&); + RtpReceiverState(const RtpReceiverState&) = delete; + ~RtpReceiverState(); + + // This is intended to be used for moving the object from the signaling thread + // to the main thread and as such has no thread checks. Once moved to the main + // this should only be invoked on the main thread. + RtpReceiverState& operator=(RtpReceiverState&&); + RtpReceiverState& operator=(const RtpReceiverState&) = delete; + + bool is_initialized() const; + void Initialize(); + + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner() const; + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner() const; + scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver() const; + const std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>& + track_ref() const; + const std::vector<std::string>& stream_ids() const; + + private: + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner_; + scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver_; + bool is_initialized_; + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref_; + std::vector<std::string> stream_ids_; +}; + // Used to surface |webrtc::RtpReceiverInterface| to blink. Multiple // |RTCRtpReceiver|s could reference the same webrtc receiver; |id| is the value // of the pointer to the webrtc receiver. @@ -30,35 +101,23 @@ class CONTENT_EXPORT RTCRtpReceiver : public blink::WebRTCRtpReceiver { RTCRtpReceiver( scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection, - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<base::SingleThreadTaskRunner> signaling_thread, - rtc::scoped_refptr<webrtc::RtpReceiverInterface> webrtc_receiver, - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> - track_adapter, - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_adapter_refs); + RtpReceiverState state); RTCRtpReceiver(const RTCRtpReceiver& other); ~RTCRtpReceiver() override; RTCRtpReceiver& operator=(const RTCRtpReceiver& other); - // Creates a shallow copy of the receiver, representing the same underlying - // webrtc receiver as the original. - std::unique_ptr<RTCRtpReceiver> ShallowCopy() const; + const RtpReceiverState& state() const; + void set_state(RtpReceiverState state); + std::unique_ptr<blink::WebRTCRtpReceiver> ShallowCopy() const override; uintptr_t Id() const override; const blink::WebMediaStreamTrack& Track() const override; - blink::WebVector<blink::WebMediaStream> Streams() const override; + blink::WebVector<blink::WebString> StreamIds() const override; blink::WebVector<std::unique_ptr<blink::WebRTCRtpContributingSource>> GetSources() override; void GetStats(std::unique_ptr<blink::WebRTCStatsReportCallback>) override; - webrtc::RtpReceiverInterface* webrtc_receiver() const; - const webrtc::MediaStreamTrackInterface& webrtc_track() const; - bool HasStream(const webrtc::MediaStreamInterface* webrtc_stream) const; - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - StreamAdapterRefs() const; - private: class RTCRtpReceiverInternal; struct RTCRtpReceiverInternalTraits; @@ -66,6 +125,31 @@ class CONTENT_EXPORT RTCRtpReceiver : public blink::WebRTCRtpReceiver { scoped_refptr<RTCRtpReceiverInternal> internal_; }; +class CONTENT_EXPORT RTCRtpReceiverOnlyTransceiver + : public blink::WebRTCRtpTransceiver { + public: + RTCRtpReceiverOnlyTransceiver( + std::unique_ptr<blink::WebRTCRtpReceiver> receiver); + ~RTCRtpReceiverOnlyTransceiver() override; + + blink::WebRTCRtpTransceiverImplementationType ImplementationType() + const override; + uintptr_t Id() const override; + blink::WebString Mid() const override; + std::unique_ptr<blink::WebRTCRtpSender> Sender() const override; + std::unique_ptr<blink::WebRTCRtpReceiver> Receiver() const override; + bool Stopped() const override; + webrtc::RtpTransceiverDirection Direction() const override; + void SetDirection(webrtc::RtpTransceiverDirection direction) override; + base::Optional<webrtc::RtpTransceiverDirection> CurrentDirection() + const override; + base::Optional<webrtc::RtpTransceiverDirection> FiredDirection() + const override; + + private: + std::unique_ptr<blink::WebRTCRtpReceiver> receiver_; +}; + } // namespace content #endif // CONTENT_RENDERER_MEDIA_WEBRTC_RTC_RTP_RECEIVER_H_ 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 f55c2b22c4c..ebe77e3780c 100644 --- a/chromium/content/renderer/media/webrtc/rtc_rtp_receiver_unittest.cc +++ b/chromium/content/renderer/media/webrtc/rtc_rtp_receiver_unittest.cc @@ -16,7 +16,6 @@ #include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h" #include "content/renderer/media/webrtc/mock_peer_connection_impl.h" #include "content/renderer/media/webrtc/test/webrtc_stats_report_obtainer.h" -#include "content/renderer/media/webrtc/webrtc_media_stream_adapter_map.h" #include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" @@ -34,10 +33,8 @@ class RTCRtpReceiverTest : public ::testing::Test { void SetUp() override { dependency_factory_.reset(new MockPeerConnectionDependencyFactory()); main_thread_ = blink::scheduler::GetSingleThreadTaskRunnerForTesting(); - stream_map_ = new WebRtcMediaStreamAdapterMap( - dependency_factory_.get(), main_thread_, - new WebRtcMediaStreamTrackAdapterMap(dependency_factory_.get(), - main_thread_)); + track_map_ = new WebRtcMediaStreamTrackAdapterMap(dependency_factory_.get(), + main_thread_); peer_connection_ = new rtc::RefCountedObject<MockPeerConnectionImpl>( dependency_factory_.get(), nullptr); } @@ -63,23 +60,23 @@ class RTCRtpReceiverTest : public ::testing::Test { std::unique_ptr<RTCRtpReceiver> CreateReceiver( scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track) { - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_adapter; + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref; base::RunLoop run_loop; dependency_factory_->GetWebRtcSignalingThread()->PostTask( FROM_HERE, base::BindOnce(&RTCRtpReceiverTest::CreateReceiverOnSignalingThread, base::Unretained(this), std::move(webrtc_track), - base::Unretained(&track_adapter), + base::Unretained(&track_ref), base::Unretained(&run_loop))); run_loop.Run(); DCHECK(mock_webrtc_receiver_); - DCHECK(track_adapter); - return std::make_unique<RTCRtpReceiver>( - peer_connection_.get(), main_thread_, - dependency_factory_->GetWebRtcSignalingThread(), - mock_webrtc_receiver_.get(), std::move(track_adapter), - std::vector< - std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>>()); + DCHECK(track_ref); + RtpReceiverState state( + main_thread_, dependency_factory_->GetWebRtcSignalingThread(), + mock_webrtc_receiver_.get(), std::move(track_ref), {}); + state.Initialize(); + return std::make_unique<RTCRtpReceiver>(peer_connection_.get(), + std::move(state)); } scoped_refptr<WebRTCStatsReportObtainer> GetStats() { @@ -92,14 +89,11 @@ class RTCRtpReceiverTest : public ::testing::Test { protected: void CreateReceiverOnSignalingThread( scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track, - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>* - track_adapter, + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>* track_ref, base::RunLoop* run_loop) { mock_webrtc_receiver_ = new rtc::RefCountedObject<webrtc::MockRtpReceiver>(); - *track_adapter = - stream_map_->track_adapter_map()->GetOrCreateRemoteTrackAdapter( - webrtc_track); + *track_ref = track_map_->GetOrCreateRemoteTrackAdapter(webrtc_track); run_loop->Quit(); } @@ -110,7 +104,7 @@ class RTCRtpReceiverTest : public ::testing::Test { std::unique_ptr<MockPeerConnectionDependencyFactory> dependency_factory_; scoped_refptr<base::SingleThreadTaskRunner> main_thread_; - scoped_refptr<WebRtcMediaStreamAdapterMap> stream_map_; + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_map_; rtc::scoped_refptr<MockPeerConnectionImpl> peer_connection_; rtc::scoped_refptr<webrtc::MockRtpReceiver> mock_webrtc_receiver_; std::unique_ptr<RTCRtpReceiver> receiver_; @@ -122,25 +116,25 @@ TEST_F(RTCRtpReceiverTest, CreateReceiver) { receiver_ = CreateReceiver(webrtc_track); EXPECT_FALSE(receiver_->Track().IsNull()); EXPECT_EQ(receiver_->Track().Id().Utf8(), webrtc_track->id()); - EXPECT_EQ(&receiver_->webrtc_track(), webrtc_track); + EXPECT_EQ(receiver_->state().track_ref()->webrtc_track(), webrtc_track); } TEST_F(RTCRtpReceiverTest, ShallowCopy) { scoped_refptr<MockWebRtcAudioTrack> webrtc_track = MockWebRtcAudioTrack::Create("webrtc_track"); receiver_ = CreateReceiver(webrtc_track); - auto copy = receiver_->ShallowCopy(); - EXPECT_EQ(&receiver_->webrtc_track(), webrtc_track); - auto* webrtc_receiver = receiver_->webrtc_receiver(); + auto copy = std::make_unique<RTCRtpReceiver>(*receiver_); + EXPECT_EQ(receiver_->state().track_ref()->webrtc_track(), webrtc_track); + const auto& webrtc_receiver = receiver_->state().webrtc_receiver(); auto web_track_unique_id = receiver_->Track().UniqueId(); // Copy is identical to original. - EXPECT_EQ(copy->webrtc_receiver(), webrtc_receiver); - EXPECT_EQ(©->webrtc_track(), webrtc_track); + EXPECT_EQ(copy->state().webrtc_receiver(), webrtc_receiver); + EXPECT_EQ(copy->state().track_ref()->webrtc_track(), webrtc_track); EXPECT_EQ(copy->Track().UniqueId(), web_track_unique_id); // Copy keeps the internal state alive. receiver_.reset(); - EXPECT_EQ(copy->webrtc_receiver(), webrtc_receiver); - EXPECT_EQ(©->webrtc_track(), webrtc_track); + EXPECT_EQ(copy->state().webrtc_receiver(), webrtc_receiver); + EXPECT_EQ(copy->state().track_ref()->webrtc_track(), webrtc_track); EXPECT_EQ(copy->Track().UniqueId(), web_track_unique_id); } diff --git a/chromium/content/renderer/media/webrtc/rtc_rtp_sender.cc b/chromium/content/renderer/media/webrtc/rtc_rtp_sender.cc index 528c8d26a15..a2d16ec7de7 100644 --- a/chromium/content/renderer/media/webrtc/rtc_rtp_sender.cc +++ b/chromium/content/renderer/media/webrtc/rtc_rtp_sender.cc @@ -36,6 +36,100 @@ void OnSetParametersCompleted(blink::WebRTCVoidRequest request, } // namespace +RtpSenderState::RtpSenderState( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner, + scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender, + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref, + std::vector<std::string> stream_ids) + : main_task_runner_(std::move(main_task_runner)), + signaling_task_runner_(std::move(signaling_task_runner)), + webrtc_sender_(std::move(webrtc_sender)), + is_initialized_(false), + track_ref_(std::move(track_ref)), + stream_ids_(std::move(stream_ids)) { + DCHECK(main_task_runner_); + DCHECK(signaling_task_runner_); + DCHECK(webrtc_sender_); +} + +RtpSenderState::RtpSenderState(RtpSenderState&& other) + : main_task_runner_(other.main_task_runner_), + signaling_task_runner_(other.signaling_task_runner_), + webrtc_sender_(std::move(other.webrtc_sender_)), + is_initialized_(other.is_initialized_), + track_ref_(std::move(other.track_ref_)), + stream_ids_(std::move(other.stream_ids_)) { + other.main_task_runner_ = nullptr; + other.signaling_task_runner_ = nullptr; +} + +RtpSenderState::~RtpSenderState() { + // It's OK to not be on the main thread if this state has been moved, in which + // case |main_task_runner_| is null. + DCHECK(!main_task_runner_ || main_task_runner_->BelongsToCurrentThread()); +} + +RtpSenderState& RtpSenderState::operator=(RtpSenderState&& other) { + DCHECK_EQ(main_task_runner_, other.main_task_runner_); + DCHECK_EQ(signaling_task_runner_, other.signaling_task_runner_); + other.main_task_runner_ = nullptr; + other.signaling_task_runner_ = nullptr; + webrtc_sender_ = std::move(other.webrtc_sender_); + is_initialized_ = other.is_initialized_; + track_ref_ = std::move(other.track_ref_); + stream_ids_ = std::move(other.stream_ids_); + return *this; +} + +bool RtpSenderState::is_initialized() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return is_initialized_; +} + +void RtpSenderState::Initialize() { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + if (track_ref_) + track_ref_->InitializeOnMainThread(); + is_initialized_ = true; +} + +scoped_refptr<base::SingleThreadTaskRunner> RtpSenderState::main_task_runner() + const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return main_task_runner_; +} + +scoped_refptr<base::SingleThreadTaskRunner> +RtpSenderState::signaling_task_runner() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return signaling_task_runner_; +} + +scoped_refptr<webrtc::RtpSenderInterface> RtpSenderState::webrtc_sender() + const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return webrtc_sender_; +} + +const std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>& +RtpSenderState::track_ref() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return track_ref_; +} + +void RtpSenderState::set_track_ref( + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref) { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + DCHECK(!is_initialized_ || !track_ref || track_ref->is_initialized()); + track_ref_ = std::move(track_ref); +} + +std::vector<std::string> RtpSenderState::stream_ids() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return stream_ids_; +} + class RTCRtpSender::RTCRtpSenderInternal : public base::RefCountedThreadSafe< RTCRtpSender::RTCRtpSenderInternal, @@ -43,86 +137,42 @@ class RTCRtpSender::RTCRtpSenderInternal public: RTCRtpSenderInternal( scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection, - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<base::SingleThreadTaskRunner> signaling_thread, - scoped_refptr<WebRtcMediaStreamAdapterMap> stream_map, - rtc::scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender, - blink::WebMediaStreamTrack web_track, - std::vector<blink::WebMediaStream> web_streams) - : native_peer_connection_(std::move(native_peer_connection)), - main_thread_(std::move(main_thread)), - signaling_thread_(std::move(signaling_thread)), - stream_map_(std::move(stream_map)), - webrtc_sender_(std::move(webrtc_sender)) { - DCHECK(main_thread_); - DCHECK(signaling_thread_); - DCHECK(stream_map_); - DCHECK(webrtc_sender_); - if (!web_track.IsNull()) { - track_ref_ = - stream_map_->track_adapter_map()->GetOrCreateLocalTrackAdapter( - web_track); - } - for (size_t i = 0; i < web_streams.size(); ++i) { - if (!web_streams[i].IsNull()) { - stream_refs_.push_back( - stream_map_->GetOrCreateLocalStreamAdapter(web_streams[i])); - } - } - } - - RTCRtpSenderInternal( - scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection, - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<base::SingleThreadTaskRunner> signaling_thread, - scoped_refptr<WebRtcMediaStreamAdapterMap> stream_map, - rtc::scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender, - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref, - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_refs) + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_map, + RtpSenderState state) : native_peer_connection_(std::move(native_peer_connection)), - main_thread_(std::move(main_thread)), - signaling_thread_(std::move(signaling_thread)), - stream_map_(std::move(stream_map)), - webrtc_sender_(std::move(webrtc_sender)), - track_ref_(std::move(track_ref)), - stream_refs_(std::move(stream_refs)) { - DCHECK(main_thread_); - DCHECK(signaling_thread_); - DCHECK(stream_map_); - DCHECK(webrtc_sender_); - } - - webrtc::RtpSenderInterface* webrtc_sender() const { - return webrtc_sender_.get(); + track_map_(std::move(track_map)), + main_task_runner_(state.main_task_runner()), + signaling_task_runner_(state.signaling_task_runner()), + webrtc_sender_(state.webrtc_sender()), + state_(std::move(state)) { + DCHECK(track_map_); + DCHECK(state_.is_initialized()); } - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref() - const { - return track_ref_ ? track_ref_->Copy() : nullptr; + const RtpSenderState& state() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return state_; } - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_refs() const { - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_ref_copies(stream_refs_.size()); - for (size_t i = 0; i < stream_refs_.size(); ++i) - stream_ref_copies[i] = stream_refs_[i]->Copy(); - return stream_ref_copies; + void set_state(RtpSenderState state) { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + DCHECK_EQ(state.main_task_runner(), main_task_runner_); + DCHECK_EQ(state.signaling_task_runner(), signaling_task_runner_); + DCHECK(state.webrtc_sender() == webrtc_sender_); + DCHECK(state.is_initialized()); + state_ = std::move(state); } void ReplaceTrack(blink::WebMediaStreamTrack with_track, base::OnceCallback<void(bool)> callback) { - DCHECK(main_thread_->BelongsToCurrentThread()); + DCHECK(main_task_runner_->BelongsToCurrentThread()); std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref; webrtc::MediaStreamTrackInterface* webrtc_track = nullptr; if (!with_track.IsNull()) { - track_ref = - stream_map_->track_adapter_map()->GetOrCreateLocalTrackAdapter( - with_track); + track_ref = track_map_->GetOrCreateLocalTrackAdapter(with_track); webrtc_track = track_ref->webrtc_track(); } - signaling_thread_->PostTask( + signaling_task_runner_->PostTask( FROM_HERE, base::BindOnce( &RTCRtpSender::RTCRtpSenderInternal::ReplaceTrackOnSignalingThread, @@ -131,14 +181,16 @@ class RTCRtpSender::RTCRtpSenderInternal } std::unique_ptr<blink::WebRTCDTMFSenderHandler> GetDtmfSender() const { - // The webrtc_sender is a proxy, so this is a blocking call to the + // The webrtc_sender() is a proxy, so this is a blocking call to the // webrtc signalling thread. - DCHECK(main_thread_->BelongsToCurrentThread()); - auto dtmf_sender = webrtc_sender()->GetDtmfSender(); + DCHECK(main_task_runner_->BelongsToCurrentThread()); + auto dtmf_sender = webrtc_sender_->GetDtmfSender(); return std::make_unique<RtcDtmfSenderHandler>(dtmf_sender); } std::unique_ptr<webrtc::RtpParameters> GetParameters() { + // The webrtc_sender() is a proxy, so this is a blocking call to the + // webrtc signalling thread. parameters_ = webrtc_sender_->GetParameters(); return std::make_unique<webrtc::RtpParameters>(parameters_); } @@ -146,7 +198,7 @@ class RTCRtpSender::RTCRtpSenderInternal void SetParameters(blink::WebVector<webrtc::RtpEncodingParameters> encodings, webrtc::DegradationPreference degradation_preference, base::OnceCallback<void(webrtc::RTCError)> callback) { - DCHECK(main_thread_->BelongsToCurrentThread()); + DCHECK(main_task_runner_->BelongsToCurrentThread()); webrtc::RtpParameters new_parameters = parameters_; @@ -171,7 +223,7 @@ class RTCRtpSender::RTCRtpSenderInternal encoding.scale_resolution_down_by; } - signaling_thread_->PostTask( + signaling_task_runner_->PostTask( FROM_HERE, base::BindOnce( &RTCRtpSender::RTCRtpSenderInternal::SetParametersOnSignalingThread, @@ -179,7 +231,7 @@ class RTCRtpSender::RTCRtpSenderInternal } void GetStats(std::unique_ptr<blink::WebRTCStatsReportCallback> callback) { - signaling_thread_->PostTask( + signaling_task_runner_->PostTask( FROM_HERE, base::BindOnce( &RTCRtpSender::RTCRtpSenderInternal::GetStatsOnSignalingThread, @@ -187,13 +239,14 @@ class RTCRtpSender::RTCRtpSenderInternal } bool RemoveFromPeerConnection(webrtc::PeerConnectionInterface* pc) { - if (!pc->RemoveTrack(webrtc_sender_)) + DCHECK(main_task_runner_->BelongsToCurrentThread()); + if (!pc->RemoveTrack(webrtc_sender_.get())) return false; // TODO(hbos): Removing the track should null the sender's track, or we // should do |webrtc_sender_->SetTrack(null)| but that is not allowed on a // stopped sender. In the meantime, there is a discrepancy between layers. // https://crbug.com/webrtc/7945 - track_ref_.reset(); + state_.set_track_ref(nullptr); return true; } @@ -202,7 +255,7 @@ class RTCRtpSender::RTCRtpSenderInternal ~RTCRtpSenderInternal() { // Ensured by destructor traits. - DCHECK(main_thread_->BelongsToCurrentThread()); + DCHECK(main_task_runner_->BelongsToCurrentThread()); } // |webrtc_track| is passed as an argument because |track_ref->webrtc_track()| @@ -211,9 +264,9 @@ class RTCRtpSender::RTCRtpSenderInternal std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref, webrtc::MediaStreamTrackInterface* webrtc_track, base::OnceCallback<void(bool)> callback) { - DCHECK(signaling_thread_->BelongsToCurrentThread()); + DCHECK(signaling_task_runner_->BelongsToCurrentThread()); bool result = webrtc_sender_->SetTrack(webrtc_track); - main_thread_->PostTask( + main_task_runner_->PostTask( FROM_HERE, base::BindOnce( &RTCRtpSender::RTCRtpSenderInternal::ReplaceTrackCallback, this, @@ -224,25 +277,25 @@ class RTCRtpSender::RTCRtpSenderInternal bool result, std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref, base::OnceCallback<void(bool)> callback) { - DCHECK(main_thread_->BelongsToCurrentThread()); + DCHECK(main_task_runner_->BelongsToCurrentThread()); if (result) - track_ref_ = std::move(track_ref); + state_.set_track_ref(std::move(track_ref)); std::move(callback).Run(result); } void GetStatsOnSignalingThread( std::unique_ptr<blink::WebRTCStatsReportCallback> callback) { - native_peer_connection_->GetStats(webrtc_sender_, - RTCStatsCollectorCallbackImpl::Create( - main_thread_, std::move(callback))); + native_peer_connection_->GetStats( + webrtc_sender_.get(), RTCStatsCollectorCallbackImpl::Create( + main_task_runner_, std::move(callback))); } void SetParametersOnSignalingThread( webrtc::RtpParameters parameters, base::OnceCallback<void(webrtc::RTCError)> callback) { - DCHECK(signaling_thread_->BelongsToCurrentThread()); + DCHECK(signaling_task_runner_->BelongsToCurrentThread()); webrtc::RTCError result = webrtc_sender_->SetParameters(parameters); - main_thread_->PostTask( + main_task_runner_->PostTask( FROM_HERE, base::BindOnce( &RTCRtpSender::RTCRtpSenderInternal::SetParametersCallback, this, @@ -252,23 +305,19 @@ class RTCRtpSender::RTCRtpSenderInternal void SetParametersCallback( webrtc::RTCError result, base::OnceCallback<void(webrtc::RTCError)> callback) { - DCHECK(main_thread_->BelongsToCurrentThread()); + DCHECK(main_task_runner_->BelongsToCurrentThread()); std::move(callback).Run(std::move(result)); } const scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection_; - const scoped_refptr<base::SingleThreadTaskRunner> main_thread_; - const scoped_refptr<base::SingleThreadTaskRunner> signaling_thread_; - const scoped_refptr<WebRtcMediaStreamAdapterMap> stream_map_; - const rtc::scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender_; - // The track adapter is the glue between blink and webrtc layer tracks. - // Keeping a reference to the adapter ensures it is not disposed, as is - // required as long as the webrtc layer track is in use by the sender. - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref_; - // Similarly, reference needs to be kept to the stream adapters of the - // sender's associated set of streams. - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_refs_; + const scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_map_; + // Task runners and webrtc sender: Same information as stored in + // |state_| but const and safe to touch on the signaling thread to + // avoid race with set_state(). + const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; + const scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner_; + const scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender_; + RtpSenderState state_; webrtc::RtpParameters parameters_; }; @@ -280,8 +329,8 @@ struct RTCRtpSender::RTCRtpSenderInternalTraits { static void Destruct(const RTCRtpSenderInternal* sender) { // RTCRtpSenderInternal owns AdapterRefs which have to be destroyed on the // main thread, this ensures delete always happens there. - if (!sender->main_thread_->BelongsToCurrentThread()) { - sender->main_thread_->PostTask( + if (!sender->main_task_runner_->BelongsToCurrentThread()) { + sender->main_task_runner_->PostTask( FROM_HERE, base::BindOnce(&RTCRtpSender::RTCRtpSenderInternalTraits::Destruct, base::Unretained(sender))); @@ -297,36 +346,11 @@ uintptr_t RTCRtpSender::getId(const webrtc::RtpSenderInterface* webrtc_sender) { RTCRtpSender::RTCRtpSender( scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection, - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<base::SingleThreadTaskRunner> signaling_thread, - scoped_refptr<WebRtcMediaStreamAdapterMap> stream_map, - rtc::scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender, - blink::WebMediaStreamTrack web_track, - std::vector<blink::WebMediaStream> web_streams) - : internal_(new RTCRtpSenderInternal(std::move(native_peer_connection), - std::move(main_thread), - std::move(signaling_thread), - std::move(stream_map), - std::move(webrtc_sender), - std::move(web_track), - std::move(web_streams))) {} - -RTCRtpSender::RTCRtpSender( - scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection, - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<base::SingleThreadTaskRunner> signaling_thread, - scoped_refptr<WebRtcMediaStreamAdapterMap> stream_map, - rtc::scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender, - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref, - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_refs) + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_map, + RtpSenderState state) : internal_(new RTCRtpSenderInternal(std::move(native_peer_connection), - std::move(main_thread), - std::move(signaling_thread), - std::move(stream_map), - std::move(webrtc_sender), - std::move(track_ref), - std::move(stream_refs))) {} + std::move(track_map), + std::move(state))) {} RTCRtpSender::RTCRtpSender(const RTCRtpSender& other) : internal_(other.internal_) {} @@ -338,19 +362,35 @@ RTCRtpSender& RTCRtpSender::operator=(const RTCRtpSender& other) { return *this; } -std::unique_ptr<RTCRtpSender> RTCRtpSender::ShallowCopy() const { +const RtpSenderState& RTCRtpSender::state() const { + return internal_->state(); +} + +void RTCRtpSender::set_state(RtpSenderState state) { + internal_->set_state(std::move(state)); +} + +std::unique_ptr<blink::WebRTCRtpSender> RTCRtpSender::ShallowCopy() const { return std::make_unique<RTCRtpSender>(*this); } uintptr_t RTCRtpSender::Id() const { - return getId(internal_->webrtc_sender()); + return getId(internal_->state().webrtc_sender().get()); } blink::WebMediaStreamTrack RTCRtpSender::Track() const { - auto track_ref = internal_->track_ref(); + const auto& track_ref = internal_->state().track_ref(); return track_ref ? track_ref->web_track() : blink::WebMediaStreamTrack(); } +blink::WebVector<blink::WebString> RTCRtpSender::StreamIds() const { + const auto& stream_ids = internal_->state().stream_ids(); + blink::WebVector<blink::WebString> web_stream_ids(stream_ids.size()); + for (size_t i = 0; i < stream_ids.size(); ++i) + web_stream_ids[i] = blink::WebString::FromUTF8(stream_ids[i]); + return web_stream_ids; +} + void RTCRtpSender::ReplaceTrack(blink::WebMediaStreamTrack with_track, blink::WebRTCVoidRequest request) { internal_->ReplaceTrack( @@ -381,20 +421,6 @@ void RTCRtpSender::GetStats( internal_->GetStats(std::move(callback)); } -webrtc::RtpSenderInterface* RTCRtpSender::webrtc_sender() const { - return internal_->webrtc_sender(); -} - -const webrtc::MediaStreamTrackInterface* RTCRtpSender::webrtc_track() const { - auto track_ref = internal_->track_ref(); - return track_ref ? track_ref->webrtc_track() : nullptr; -} - -std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> -RTCRtpSender::stream_refs() const { - return internal_->stream_refs(); -} - void RTCRtpSender::ReplaceTrack(blink::WebMediaStreamTrack with_track, base::OnceCallback<void(bool)> callback) { internal_->ReplaceTrack(std::move(with_track), std::move(callback)); @@ -405,4 +431,65 @@ bool RTCRtpSender::RemoveFromPeerConnection( return internal_->RemoveFromPeerConnection(pc); } +RTCRtpSenderOnlyTransceiver::RTCRtpSenderOnlyTransceiver( + std::unique_ptr<blink::WebRTCRtpSender> sender) + : sender_(std::move(sender)) { + DCHECK(sender_); +} + +RTCRtpSenderOnlyTransceiver::~RTCRtpSenderOnlyTransceiver() {} + +blink::WebRTCRtpTransceiverImplementationType +RTCRtpSenderOnlyTransceiver::ImplementationType() const { + return blink::WebRTCRtpTransceiverImplementationType::kPlanBSenderOnly; +} + +uintptr_t RTCRtpSenderOnlyTransceiver::Id() const { + NOTIMPLEMENTED(); + return 0u; +} + +blink::WebString RTCRtpSenderOnlyTransceiver::Mid() const { + NOTIMPLEMENTED(); + return blink::WebString(); +} + +std::unique_ptr<blink::WebRTCRtpSender> RTCRtpSenderOnlyTransceiver::Sender() + const { + return sender_->ShallowCopy(); +} + +std::unique_ptr<blink::WebRTCRtpReceiver> +RTCRtpSenderOnlyTransceiver::Receiver() const { + NOTIMPLEMENTED(); + return nullptr; +} + +bool RTCRtpSenderOnlyTransceiver::Stopped() const { + NOTIMPLEMENTED(); + return false; +} + +webrtc::RtpTransceiverDirection RTCRtpSenderOnlyTransceiver::Direction() const { + NOTIMPLEMENTED(); + return webrtc::RtpTransceiverDirection::kSendOnly; +} + +void RTCRtpSenderOnlyTransceiver::SetDirection( + webrtc::RtpTransceiverDirection direction) { + NOTIMPLEMENTED(); +} + +base::Optional<webrtc::RtpTransceiverDirection> +RTCRtpSenderOnlyTransceiver::CurrentDirection() const { + NOTIMPLEMENTED(); + return webrtc::RtpTransceiverDirection::kSendOnly; +} + +base::Optional<webrtc::RtpTransceiverDirection> +RTCRtpSenderOnlyTransceiver::FiredDirection() const { + NOTIMPLEMENTED(); + return webrtc::RtpTransceiverDirection::kSendOnly; +} + } // namespace content diff --git a/chromium/content/renderer/media/webrtc/rtc_rtp_sender.h b/chromium/content/renderer/media/webrtc/rtc_rtp_sender.h index 990b21fb64c..7a96b39e38f 100644 --- a/chromium/content/renderer/media/webrtc/rtc_rtp_sender.h +++ b/chromium/content/renderer/media/webrtc/rtc_rtp_sender.h @@ -11,10 +11,10 @@ #include "base/callback.h" #include "base/single_thread_task_runner.h" #include "content/common/content_export.h" -#include "content/renderer/media/webrtc/webrtc_media_stream_adapter_map.h" #include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h" #include "third_party/blink/public/platform/web_media_stream_track.h" #include "third_party/blink/public/platform/web_rtc_rtp_sender.h" +#include "third_party/blink/public/platform/web_rtc_rtp_transceiver.h" #include "third_party/blink/public/platform/web_rtc_stats.h" #include "third_party/webrtc/api/peerconnectioninterface.h" #include "third_party/webrtc/api/rtpsenderinterface.h" @@ -22,43 +22,108 @@ namespace content { +// This class represents the state of a sender; a snapshot of what a +// webrtc-layer sender looked like when it was inspected on the signaling thread +// such that this information can be moved to the main thread in a single +// PostTask. It is used to surface state changes to make the blink-layer sender +// up-to-date. +// +// Blink objects live on the main thread and webrtc objects live on the +// signaling thread. If multiple asynchronous operations begin execution on the +// main thread they are posted and executed in order on the signaling thread. +// For example, operation A and operation B are called in JavaScript. When A is +// done on the signaling thread, webrtc object states will be updated. A +// callback is posted to the main thread so that blink objects can be updated to +// match the result of operation A. But if callback A tries to inspect the +// webrtc objects from the main thread this requires posting back to the +// signaling thread and waiting, which also includes waiting for the previously +// posted task: operation B. Inspecting the webrtc object like this does not +// guarantee you to get the state of operation A. +// +// As such, all state changes associated with an operation have to be surfaced +// in the same callback. This includes copying any states into a separate object +// so that it can be inspected on the main thread without any additional thread +// hops. +// +// The RtpSenderState is a snapshot of what the webrtc::RtpSenderInterface +// looked like when the RtpSenderState was created on the signaling thread. It +// also takes care of initializing track adapters, such that we have access to a +// blink track corresponding to the webrtc track of the sender. +// +// Except for initialization logic and operator=(), the RtpSenderState is +// immutable and only accessible on the main thread. +// +// TODO(hbos): [Onion Soup] When the sender implementation is moved to blink +// this will be part of the blink sender instead of the content sender. +// https://crbug.com/787254 +class CONTENT_EXPORT RtpSenderState { + public: + RtpSenderState( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner, + scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender, + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref, + std::vector<std::string> stream_ids); + RtpSenderState(RtpSenderState&&); + RtpSenderState(const RtpSenderState&) = delete; + ~RtpSenderState(); + + // This is intended to be used for moving the object from the signaling thread + // to the main thread and as such has no thread checks. Once moved to the main + // this should only be invoked on the main thread. + RtpSenderState& operator=(RtpSenderState&&); + RtpSenderState& operator=(const RtpSenderState&) = delete; + + bool is_initialized() const; + void Initialize(); + + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner() const; + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner() const; + scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender() const; + const std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>& + track_ref() const; + void set_track_ref( + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref); + std::vector<std::string> stream_ids() const; + + private: + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner_; + scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender_; + bool is_initialized_; + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref_; + std::vector<std::string> stream_ids_; +}; + // Used to surface |webrtc::RtpSenderInterface| to blink. Multiple // |RTCRtpSender|s could reference the same webrtc sender; |id| is the value // of the pointer to the webrtc sender. +// TODO(hbos): [Onion Soup] Move all of the implementation inside the blink +// object and remove this class and interface. The blink object is reference +// counted and we can get rid of this "Web"-copyable with "internal" nonsense, +// all the blink object will need is the RtpSenderState. Requires coordination +// with transceivers and receivers since these are tightly coupled. +// https://crbug.com/787254 class CONTENT_EXPORT RTCRtpSender : public blink::WebRTCRtpSender { public: static uintptr_t getId(const webrtc::RtpSenderInterface* webrtc_sender); RTCRtpSender( scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection, - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<base::SingleThreadTaskRunner> signaling_thread, - scoped_refptr<WebRtcMediaStreamAdapterMap> stream_map, - rtc::scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender, - blink::WebMediaStreamTrack web_track, - std::vector<blink::WebMediaStream> web_streams); - RTCRtpSender( - scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection, - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<base::SingleThreadTaskRunner> signaling_thread, - scoped_refptr<WebRtcMediaStreamAdapterMap> stream_map, - rtc::scoped_refptr<webrtc::RtpSenderInterface> webrtc_sender, - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref, - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_refs); + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_map, + RtpSenderState state); RTCRtpSender(const RTCRtpSender& other); ~RTCRtpSender() override; - RTCRtpSender& operator=(const RTCRtpSender& other); - // Creates a shallow copy of the sender, representing the same underlying - // webrtc sender as the original. - // TODO(hbos): Remove in favor of constructor. https://crbug.com/790007 - std::unique_ptr<RTCRtpSender> ShallowCopy() const; + const RtpSenderState& state() const; + void set_state(RtpSenderState state); // blink::WebRTCRtpSender. + std::unique_ptr<blink::WebRTCRtpSender> ShallowCopy() const override; uintptr_t Id() const override; blink::WebMediaStreamTrack Track() const override; + blink::WebVector<blink::WebString> StreamIds() const override; void ReplaceTrack(blink::WebMediaStreamTrack with_track, blink::WebRTCVoidRequest request) override; std::unique_ptr<blink::WebRTCDTMFSenderHandler> GetDtmfSender() @@ -69,10 +134,6 @@ class CONTENT_EXPORT RTCRtpSender : public blink::WebRTCRtpSender { blink::WebRTCVoidRequest) override; void GetStats(std::unique_ptr<blink::WebRTCStatsReportCallback>) override; - webrtc::RtpSenderInterface* webrtc_sender() const; - const webrtc::MediaStreamTrackInterface* webrtc_track() const; - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_refs() const; // The ReplaceTrack() that takes a blink::WebRTCVoidRequest is implemented on // top of this, which returns the result in a callback instead. Allows doing // ReplaceTrack() without having a blink::WebRTCVoidRequest, which can only be @@ -88,6 +149,30 @@ class CONTENT_EXPORT RTCRtpSender : public blink::WebRTCRtpSender { scoped_refptr<RTCRtpSenderInternal> internal_; }; +class CONTENT_EXPORT RTCRtpSenderOnlyTransceiver + : public blink::WebRTCRtpTransceiver { + public: + RTCRtpSenderOnlyTransceiver(std::unique_ptr<blink::WebRTCRtpSender> sender); + ~RTCRtpSenderOnlyTransceiver() override; + + blink::WebRTCRtpTransceiverImplementationType ImplementationType() + const override; + uintptr_t Id() const override; + blink::WebString Mid() const override; + std::unique_ptr<blink::WebRTCRtpSender> Sender() const override; + std::unique_ptr<blink::WebRTCRtpReceiver> Receiver() const override; + bool Stopped() const override; + webrtc::RtpTransceiverDirection Direction() const override; + void SetDirection(webrtc::RtpTransceiverDirection direction) override; + base::Optional<webrtc::RtpTransceiverDirection> CurrentDirection() + const override; + base::Optional<webrtc::RtpTransceiverDirection> FiredDirection() + const override; + + private: + std::unique_ptr<blink::WebRTCRtpSender> sender_; +}; + } // namespace content #endif // CONTENT_RENDERER_MEDIA_WEBRTC_RTC_RTP_SENDER_H_ 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 eb086d2e0d2..0f3f27f9dad 100644 --- a/chromium/content/renderer/media/webrtc/rtc_rtp_sender_unittest.cc +++ b/chromium/content/renderer/media/webrtc/rtc_rtp_sender_unittest.cc @@ -16,7 +16,6 @@ #include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h" #include "content/renderer/media/webrtc/mock_peer_connection_impl.h" #include "content/renderer/media/webrtc/test/webrtc_stats_report_obtainer.h" -#include "content/renderer/media/webrtc/webrtc_media_stream_adapter_map.h" #include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" @@ -40,10 +39,8 @@ class RTCRtpSenderTest : public ::testing::Test { void SetUp() override { dependency_factory_.reset(new MockPeerConnectionDependencyFactory()); main_thread_ = blink::scheduler::GetSingleThreadTaskRunnerForTesting(); - stream_map_ = new WebRtcMediaStreamAdapterMap( - dependency_factory_.get(), main_thread_, - new WebRtcMediaStreamTrackAdapterMap(dependency_factory_.get(), - main_thread_)); + track_map_ = new WebRtcMediaStreamTrackAdapterMap(dependency_factory_.get(), + main_thread_); peer_connection_ = new rtc::RefCountedObject<MockPeerConnectionImpl>( dependency_factory_.get(), nullptr); mock_webrtc_sender_ = new rtc::RefCountedObject<webrtc::MockRtpSender>(); @@ -84,11 +81,18 @@ class RTCRtpSenderTest : public ::testing::Test { std::unique_ptr<RTCRtpSender> CreateSender( blink::WebMediaStreamTrack web_track) { - return std::make_unique<RTCRtpSender>( - peer_connection_.get(), main_thread_, - dependency_factory_->GetWebRtcSignalingThread(), stream_map_, - mock_webrtc_sender_.get(), std::move(web_track), - std::vector<blink::WebMediaStream>()); + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref; + if (!web_track.IsNull()) { + track_ref = track_map_->GetOrCreateLocalTrackAdapter(web_track); + DCHECK(track_ref->is_initialized()); + } + RtpSenderState sender_state(main_thread_, + dependency_factory_->GetWebRtcSignalingThread(), + mock_webrtc_sender_.get(), std::move(track_ref), + std::vector<std::string>()); + sender_state.Initialize(); + return std::make_unique<RTCRtpSender>(peer_connection_.get(), track_map_, + std::move(sender_state)); } // Calls replaceTrack(), which is asynchronous, returning a callback that when @@ -139,7 +143,7 @@ class RTCRtpSenderTest : public ::testing::Test { std::unique_ptr<MockPeerConnectionDependencyFactory> dependency_factory_; scoped_refptr<base::SingleThreadTaskRunner> main_thread_; - scoped_refptr<WebRtcMediaStreamAdapterMap> stream_map_; + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_map_; rtc::scoped_refptr<MockPeerConnectionImpl> peer_connection_; rtc::scoped_refptr<webrtc::MockRtpSender> mock_webrtc_sender_; std::unique_ptr<RTCRtpSender> sender_; diff --git a/chromium/content/renderer/media/webrtc/rtc_rtp_transceiver.cc b/chromium/content/renderer/media/webrtc/rtc_rtp_transceiver.cc new file mode 100644 index 00000000000..7bdda93416d --- /dev/null +++ b/chromium/content/renderer/media/webrtc/rtc_rtp_transceiver.cc @@ -0,0 +1,357 @@ +// 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_rtp_transceiver.h" + +#include "base/logging.h" +#include "base/memory/ref_counted.h" + +namespace content { + +RtpTransceiverState::RtpTransceiverState( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner, + scoped_refptr<webrtc::RtpTransceiverInterface> webrtc_transceiver, + base::Optional<RtpSenderState> sender_state, + base::Optional<RtpReceiverState> receiver_state, + base::Optional<std::string> mid, + bool stopped, + webrtc::RtpTransceiverDirection direction, + base::Optional<webrtc::RtpTransceiverDirection> current_direction, + base::Optional<webrtc::RtpTransceiverDirection> fired_direction) + : main_task_runner_(std::move(main_task_runner)), + signaling_task_runner_(std::move(signaling_task_runner)), + webrtc_transceiver_(std::move(webrtc_transceiver)), + is_initialized_(false), + sender_state_(std::move(sender_state)), + receiver_state_(std::move(receiver_state)), + mid_(std::move(mid)), + stopped_(std::move(stopped)), + direction_(std::move(direction)), + current_direction_(std::move(current_direction)), + fired_direction_(std::move(fired_direction)) { + DCHECK(main_task_runner_); + DCHECK(signaling_task_runner_); + DCHECK(webrtc_transceiver_); +} + +RtpTransceiverState::RtpTransceiverState(RtpTransceiverState&& other) + : main_task_runner_(other.main_task_runner_), + signaling_task_runner_(other.signaling_task_runner_), + webrtc_transceiver_(std::move(other.webrtc_transceiver_)), + is_initialized_(other.is_initialized_), + sender_state_(std::move(other.sender_state_)), + receiver_state_(std::move(other.receiver_state_)), + mid_(std::move(other.mid_)), + stopped_(std::move(other.stopped_)), + direction_(std::move(other.direction_)), + current_direction_(std::move(other.current_direction_)), + fired_direction_(std::move(other.fired_direction_)) { + // Explicitly null |other|'s task runners for use in destructor. + other.main_task_runner_ = nullptr; + other.signaling_task_runner_ = nullptr; +} + +RtpTransceiverState::~RtpTransceiverState() { + // It's OK to not be on the main thread if this state has been moved, in which + // case |main_task_runner_| is null. + DCHECK(!main_task_runner_ || main_task_runner_->BelongsToCurrentThread()); +} + +RtpTransceiverState& RtpTransceiverState::operator=( + RtpTransceiverState&& other) { + DCHECK_EQ(main_task_runner_, other.main_task_runner_); + DCHECK_EQ(signaling_task_runner_, other.signaling_task_runner_); + // Need to be on main thread for sender/receiver state's destructor that can + // be triggered by replacing . + DCHECK(main_task_runner_->BelongsToCurrentThread()); + // Explicitly null |other|'s task runners for use in destructor. + other.main_task_runner_ = nullptr; + other.signaling_task_runner_ = nullptr; + webrtc_transceiver_ = std::move(other.webrtc_transceiver_); + is_initialized_ = other.is_initialized_; + sender_state_ = std::move(other.sender_state_); + receiver_state_ = std::move(other.receiver_state_); + mid_ = std::move(other.mid_); + stopped_ = std::move(other.stopped_); + direction_ = std::move(other.direction_); + current_direction_ = std::move(other.current_direction_); + fired_direction_ = std::move(other.fired_direction_); + return *this; +} + +bool RtpTransceiverState::is_initialized() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return is_initialized_; +} + +void RtpTransceiverState::Initialize() { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + if (sender_state_) + sender_state_->Initialize(); + if (receiver_state_) + receiver_state_->Initialize(); + is_initialized_ = true; +} + +scoped_refptr<base::SingleThreadTaskRunner> +RtpTransceiverState::main_task_runner() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return main_task_runner_; +} + +scoped_refptr<base::SingleThreadTaskRunner> +RtpTransceiverState::signaling_task_runner() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return signaling_task_runner_; +} + +scoped_refptr<webrtc::RtpTransceiverInterface> +RtpTransceiverState::webrtc_transceiver() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return webrtc_transceiver_; +} + +const base::Optional<RtpSenderState>& RtpTransceiverState::sender_state() + const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return sender_state_; +} + +RtpSenderState RtpTransceiverState::MoveSenderState() { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + base::Optional<RtpSenderState> temp(base::nullopt); + sender_state_.swap(temp); + return *std::move(temp); +} + +const base::Optional<RtpReceiverState>& RtpTransceiverState::receiver_state() + const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return receiver_state_; +} + +RtpReceiverState RtpTransceiverState::MoveReceiverState() { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + base::Optional<RtpReceiverState> temp(base::nullopt); + receiver_state_.swap(temp); + return *std::move(temp); +} + +base::Optional<std::string> RtpTransceiverState::mid() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return mid_; +} + +bool RtpTransceiverState::stopped() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return stopped_; +} + +webrtc::RtpTransceiverDirection RtpTransceiverState::direction() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return direction_; +} + +void RtpTransceiverState::set_direction( + webrtc::RtpTransceiverDirection direction) { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + direction_ = direction; +} + +base::Optional<webrtc::RtpTransceiverDirection> +RtpTransceiverState::current_direction() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return current_direction_; +} + +base::Optional<webrtc::RtpTransceiverDirection> +RtpTransceiverState::fired_direction() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return fired_direction_; +} + +class RTCRtpTransceiver::RTCRtpTransceiverInternal + : public base::RefCountedThreadSafe< + RTCRtpTransceiver::RTCRtpTransceiverInternal, + RTCRtpTransceiver::RTCRtpTransceiverInternalTraits> { + public: + RTCRtpTransceiverInternal( + scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection, + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_map, + RtpTransceiverState state) + : main_task_runner_(state.main_task_runner()), + signaling_task_runner_(state.signaling_task_runner()), + webrtc_transceiver_(state.webrtc_transceiver()), + state_(std::move(state)) { + sender_ = std::make_unique<RTCRtpSender>(native_peer_connection, track_map, + state_.MoveSenderState()); + receiver_ = std::make_unique<RTCRtpReceiver>(native_peer_connection, + state_.MoveReceiverState()); + } + + const RtpTransceiverState& state() const { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return state_; + } + + void set_state(RtpTransceiverState state) { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + DCHECK_EQ(state.main_task_runner(), main_task_runner_); + DCHECK_EQ(state.signaling_task_runner(), signaling_task_runner_); + DCHECK(state.webrtc_transceiver() == webrtc_transceiver_); + DCHECK(state.is_initialized()); + state_ = std::move(state); + sender_->set_state(state_.MoveSenderState()); + receiver_->set_state(state_.MoveReceiverState()); + } + + RTCRtpSender* content_sender() { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return sender_.get(); + } + + RTCRtpReceiver* content_receiver() { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + return receiver_.get(); + } + + void SetDirection(webrtc::RtpTransceiverDirection direction) { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + // This implicitly performs a blocking invoke on the webrtc signaling thread + // due to use of PROXY references for |webrtc_transceiver_|. + webrtc_transceiver_->SetDirection(direction); + state_.set_direction(webrtc_transceiver_->direction()); + } + + private: + friend struct RTCRtpTransceiver::RTCRtpTransceiverInternalTraits; + + ~RTCRtpTransceiverInternal() { + // Ensured by destructor traits. + DCHECK(main_task_runner_->BelongsToCurrentThread()); + } + + // Task runners and webrtc transceiver: Same information as stored in |state_| + // but const and safe to touch on the signaling thread to avoid race with + // set_state(). + const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; + const scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner_; + const scoped_refptr<webrtc::RtpTransceiverInterface> webrtc_transceiver_; + RtpTransceiverState state_; + std::unique_ptr<RTCRtpSender> sender_; + std::unique_ptr<RTCRtpReceiver> receiver_; +}; + +struct RTCRtpTransceiver::RTCRtpTransceiverInternalTraits { + private: + friend class base::RefCountedThreadSafe<RTCRtpTransceiverInternal, + RTCRtpTransceiverInternalTraits>; + + static void Destruct(const RTCRtpTransceiverInternal* transceiver) { + // RTCRtpTransceiverInternal owns AdapterRefs which have to be destroyed on + // the main thread, this ensures delete always happens there. + if (!transceiver->main_task_runner_->BelongsToCurrentThread()) { + transceiver->main_task_runner_->PostTask( + FROM_HERE, + base::BindOnce( + &RTCRtpTransceiver::RTCRtpTransceiverInternalTraits::Destruct, + base::Unretained(transceiver))); + return; + } + delete transceiver; + } +}; + +uintptr_t RTCRtpTransceiver::GetId( + const webrtc::RtpTransceiverInterface* webrtc_transceiver) { + return reinterpret_cast<uintptr_t>(webrtc_transceiver); +} + +RTCRtpTransceiver::RTCRtpTransceiver( + scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection, + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_map, + RtpTransceiverState transceiver_state) + : internal_(new RTCRtpTransceiverInternal(std::move(native_peer_connection), + std::move(track_map), + std::move(transceiver_state))) {} + +RTCRtpTransceiver::RTCRtpTransceiver(const RTCRtpTransceiver& other) + : internal_(other.internal_) {} + +RTCRtpTransceiver::~RTCRtpTransceiver() {} + +RTCRtpTransceiver& RTCRtpTransceiver::operator=( + const RTCRtpTransceiver& other) { + internal_ = other.internal_; + return *this; +} + +std::unique_ptr<RTCRtpTransceiver> RTCRtpTransceiver::ShallowCopy() const { + return std::make_unique<RTCRtpTransceiver>(*this); +} + +const RtpTransceiverState& RTCRtpTransceiver::state() const { + return internal_->state(); +} + +RTCRtpSender* RTCRtpTransceiver::content_sender() { + return internal_->content_sender(); +} + +RTCRtpReceiver* RTCRtpTransceiver::content_receiver() { + return internal_->content_receiver(); +} + +void RTCRtpTransceiver::set_state(RtpTransceiverState transceiver_state) { + internal_->set_state(std::move(transceiver_state)); +} + +blink::WebRTCRtpTransceiverImplementationType +RTCRtpTransceiver::ImplementationType() const { + return blink::WebRTCRtpTransceiverImplementationType::kFullTransceiver; +} + +uintptr_t RTCRtpTransceiver::Id() const { + return GetId(internal_->state().webrtc_transceiver().get()); +} + +blink::WebString RTCRtpTransceiver::Mid() const { + const auto& mid = internal_->state().mid(); + return mid ? blink::WebString::FromUTF8(*mid) + : blink::WebString(); // IsNull() +} + +std::unique_ptr<blink::WebRTCRtpSender> RTCRtpTransceiver::Sender() const { + return internal_->content_sender()->ShallowCopy(); +} + +std::unique_ptr<blink::WebRTCRtpReceiver> RTCRtpTransceiver::Receiver() const { + return internal_->content_receiver()->ShallowCopy(); +} + +bool RTCRtpTransceiver::Stopped() const { + return internal_->state().stopped(); +} + +webrtc::RtpTransceiverDirection RTCRtpTransceiver::Direction() const { + return internal_->state().direction(); +} + +void RTCRtpTransceiver::SetDirection( + webrtc::RtpTransceiverDirection direction) { + internal_->SetDirection(direction); +} + +base::Optional<webrtc::RtpTransceiverDirection> +RTCRtpTransceiver::CurrentDirection() const { + return internal_->state().current_direction(); +} + +base::Optional<webrtc::RtpTransceiverDirection> +RTCRtpTransceiver::FiredDirection() const { + return internal_->state().fired_direction(); +} + +} // namespace content diff --git a/chromium/content/renderer/media/webrtc/rtc_rtp_transceiver.h b/chromium/content/renderer/media/webrtc/rtc_rtp_transceiver.h new file mode 100644 index 00000000000..5eadedf1955 --- /dev/null +++ b/chromium/content/renderer/media/webrtc/rtc_rtp_transceiver.h @@ -0,0 +1,160 @@ +// 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_RTP_TRANSCEIVER_H_ +#define CONTENT_RENDERER_MEDIA_WEBRTC_RTC_RTP_TRANSCEIVER_H_ + +#include "base/memory/scoped_refptr.h" +#include "base/optional.h" +#include "base/single_thread_task_runner.h" +#include "content/renderer/media/webrtc/rtc_rtp_receiver.h" +#include "content/renderer/media/webrtc/rtc_rtp_sender.h" +#include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h" +#include "third_party/blink/public/platform/web_rtc_rtp_transceiver.h" +#include "third_party/webrtc/api/rtptransceiverinterface.h" + +namespace content { + +// This class represents the state of a transceiver; a snapshot of what a +// webrtc-layer transceiver looked like when it was inspected on the signaling +// thread such that this information can be moved to the main thread in a single +// PostTask. It is used to surface state changes to make the blink-layer +// transceiver up-to-date. +// +// Blink objects live on the main thread and webrtc objects live on the +// signaling thread. If multiple asynchronous operations begin execution on the +// main thread they are posted and executed in order on the signaling thread. +// For example, operation A and operation B are called in JavaScript. When A is +// done on the signaling thread, webrtc object states will be updated. A +// callback is posted to the main thread so that blink objects can be updated to +// match the result of operation A. But if callback A tries to inspect the +// webrtc objects from the main thread this requires posting back to the +// signaling thread and waiting, which also includes waiting for the previously +// posted task: operation B. Inspecting the webrtc object like this does not +// guarantee you to get the state of operation A. +// +// As such, all state changes associated with an operation have to be surfaced +// in the same callback. This includes copying any states into a separate object +// so that it can be inspected on the main thread without any additional thread +// hops. +// +// The RtpTransceiverState is a snapshot of what the +// webrtc::RtpTransceiverInterface looked like when the RtpTransceiverState was +// created on the signaling thread. It also takes care of initializing sender +// and receiver states, including their track adapters such that we have access +// to a blink track corresponding to the webrtc tracks of the sender and +// receiver. +// +// Except for initialization logic and operator=(), the RtpTransceiverState is +// immutable and only accessible on the main thread. +// +// TODO(hbos): [Onion Soup] When the transceiver implementation is moved to +// blink this will be part of the blink transceiver instead of the content +// transceiver. https://crbug.com/787254 +class CONTENT_EXPORT RtpTransceiverState { + public: + RtpTransceiverState( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner, + scoped_refptr<webrtc::RtpTransceiverInterface> webrtc_transceiver, + base::Optional<RtpSenderState> sender_state, + base::Optional<RtpReceiverState> receiver_state, + base::Optional<std::string> mid, + bool stopped, + webrtc::RtpTransceiverDirection direction, + base::Optional<webrtc::RtpTransceiverDirection> current_direction, + base::Optional<webrtc::RtpTransceiverDirection> fired_direction); + RtpTransceiverState(RtpTransceiverState&&); + RtpTransceiverState(const RtpTransceiverState&) = delete; + ~RtpTransceiverState(); + + // This is intended to be used for moving the object from the signaling thread + // to the main thread and as such has no thread checks. Once moved to the main + // this should only be invoked on the main thread. + RtpTransceiverState& operator=(RtpTransceiverState&&); + RtpTransceiverState& operator=(const RtpTransceiverState&) = delete; + + bool is_initialized() const; + void Initialize(); + + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner() const; + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner() const; + scoped_refptr<webrtc::RtpTransceiverInterface> webrtc_transceiver() const; + const base::Optional<RtpSenderState>& sender_state() const; + RtpSenderState MoveSenderState(); + const base::Optional<RtpReceiverState>& receiver_state() const; + RtpReceiverState MoveReceiverState(); + base::Optional<std::string> mid() const; + bool stopped() const; + webrtc::RtpTransceiverDirection direction() const; + void set_direction(webrtc::RtpTransceiverDirection); + base::Optional<webrtc::RtpTransceiverDirection> current_direction() const; + base::Optional<webrtc::RtpTransceiverDirection> fired_direction() const; + + private: + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner_; + scoped_refptr<webrtc::RtpTransceiverInterface> webrtc_transceiver_; + bool is_initialized_; + base::Optional<RtpSenderState> sender_state_; + base::Optional<RtpReceiverState> receiver_state_; + base::Optional<std::string> mid_; + bool stopped_; + webrtc::RtpTransceiverDirection direction_; + base::Optional<webrtc::RtpTransceiverDirection> current_direction_; + base::Optional<webrtc::RtpTransceiverDirection> fired_direction_; +}; + +// Used to surface |webrtc::RtpTransceiverInterface| to blink. Multiple +// |RTCRtpTransceiver|s could reference the same webrtc transceiver; |id| is +// unique per webrtc transceiver. +// Its methods are accessed on the main thread, internally also performs +// operations on the signaling thread. +// TODO(hbos): [Onion Soup] Remove the content layer versions of this class and +// rely on webrtc directly from blink. Requires coordination with senders and +// receivers. https://crbug.com/787254 +class CONTENT_EXPORT RTCRtpTransceiver : public blink::WebRTCRtpTransceiver { + public: + static uintptr_t GetId( + const webrtc::RtpTransceiverInterface* webrtc_transceiver); + + RTCRtpTransceiver( + scoped_refptr<webrtc::PeerConnectionInterface> native_peer_connection, + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_map, + RtpTransceiverState state); + RTCRtpTransceiver(const RTCRtpTransceiver& other); + ~RTCRtpTransceiver() override; + + RTCRtpTransceiver& operator=(const RTCRtpTransceiver& other); + std::unique_ptr<RTCRtpTransceiver> ShallowCopy() const; + + const RtpTransceiverState& state() const; + void set_state(RtpTransceiverState state); + RTCRtpSender* content_sender(); + RTCRtpReceiver* content_receiver(); + + blink::WebRTCRtpTransceiverImplementationType ImplementationType() + const override; + uintptr_t Id() const override; + blink::WebString Mid() const override; + std::unique_ptr<blink::WebRTCRtpSender> Sender() const override; + std::unique_ptr<blink::WebRTCRtpReceiver> Receiver() const override; + bool Stopped() const override; + webrtc::RtpTransceiverDirection Direction() const override; + void SetDirection(webrtc::RtpTransceiverDirection direction) override; + base::Optional<webrtc::RtpTransceiverDirection> CurrentDirection() + const override; + base::Optional<webrtc::RtpTransceiverDirection> FiredDirection() + const override; + + private: + class RTCRtpTransceiverInternal; + struct RTCRtpTransceiverInternalTraits; + + scoped_refptr<RTCRtpTransceiverInternal> internal_; +}; + +} // namespace content + +#endif // CONTENT_RENDERER_MEDIA_WEBRTC_RTC_RTP_TRANSCEIVER_H_ diff --git a/chromium/content/renderer/media/webrtc/rtc_rtp_transceiver_unittest.cc b/chromium/content/renderer/media/webrtc/rtc_rtp_transceiver_unittest.cc new file mode 100644 index 00000000000..3690936bfc8 --- /dev/null +++ b/chromium/content/renderer/media/webrtc/rtc_rtp_transceiver_unittest.cc @@ -0,0 +1,363 @@ +// 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_rtp_transceiver.h" + +#include <memory> + +#include "base/logging.h" +#include "base/memory/ref_counted.h" +#include "base/message_loop/message_loop.h" +#include "base/optional.h" +#include "base/run_loop.h" +#include "base/single_thread_task_runner.h" +#include "base/synchronization/waitable_event.h" +#include "build/build_config.h" +#include "content/child/child_process.h" +#include "content/renderer/media/stream/media_stream_audio_source.h" +#include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h" +#include "content/renderer/media/webrtc/mock_peer_connection_impl.h" +#include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h" +#include "content/renderer/media/webrtc/webrtc_util.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" +#include "third_party/blink/public/platform/web_media_stream_source.h" +#include "third_party/blink/public/platform/web_string.h" +#include "third_party/blink/public/web/web_heap.h" +#include "third_party/webrtc/api/test/mock_rtpreceiver.h" +#include "third_party/webrtc/api/test/mock_rtpsender.h" + +namespace content { + +class RTCRtpTransceiverTest : public ::testing::Test { + public: + void SetUp() override { + dependency_factory_.reset(new MockPeerConnectionDependencyFactory()); + main_task_runner_ = blink::scheduler::GetSingleThreadTaskRunnerForTesting(); + track_map_ = new WebRtcMediaStreamTrackAdapterMap(dependency_factory_.get(), + main_task_runner_); + peer_connection_ = new rtc::RefCountedObject<MockPeerConnectionImpl>( + dependency_factory_.get(), nullptr); + } + + void TearDown() override { + // Syncing up with the signaling thread ensures any pending operations on + // that thread are executed. If they post back to the main thread, such as + // the sender or receiver destructor traits, this is allowed to execute + // before the test shuts down the threads. + SyncWithSignalingThread(); + blink::WebHeap::CollectAllGarbageForTesting(); + } + + // Wait for the signaling thread to perform any queued tasks, executing tasks + // posted to the current thread in the meantime while waiting. + void SyncWithSignalingThread() const { + base::RunLoop run_loop; + dependency_factory_->GetWebRtcSignalingThread()->PostTask( + FROM_HERE, run_loop.QuitClosure()); + run_loop.Run(); + } + + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner() const { + return dependency_factory_->GetWebRtcSignalingThread(); + } + + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> + CreateLocalTrackAndAdapter(const std::string& id) { + return track_map_->GetOrCreateLocalTrackAdapter(CreateBlinkLocalTrack(id)); + } + + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> + CreateRemoteTrackAndAdapter(const std::string& id) { + rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track = + MockWebRtcAudioTrack::Create(id).get(); + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref; + base::RunLoop run_loop; + signaling_task_runner()->PostTask( + FROM_HERE, + base::BindOnce( + &RTCRtpTransceiverTest::CreateRemoteTrackAdapterOnSignalingThread, + base::Unretained(this), std::move(webrtc_track), + base::Unretained(&track_ref), base::Unretained(&run_loop))); + run_loop.Run(); + DCHECK(track_ref); + return track_ref; + } + + rtc::scoped_refptr<FakeRtpSender> CreateWebRtcSender( + rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track, + const std::string& stream_id) { + return new rtc::RefCountedObject<FakeRtpSender>( + std::move(track), std::vector<std::string>({stream_id})); + } + + rtc::scoped_refptr<FakeRtpReceiver> CreateWebRtcReceiver( + rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track, + const std::string& stream_id) { + rtc::scoped_refptr<webrtc::MediaStreamInterface> remote_stream( + new rtc::RefCountedObject<MockMediaStream>(stream_id)); + return new rtc::RefCountedObject<FakeRtpReceiver>( + track.get(), + std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>( + {remote_stream})); + } + + rtc::scoped_refptr<FakeRtpTransceiver> CreateWebRtcTransceiver( + rtc::scoped_refptr<webrtc::RtpSenderInterface> sender, + rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver, + base::Optional<std::string> mid, + bool stopped, + webrtc::RtpTransceiverDirection direction, + base::Optional<webrtc::RtpTransceiverDirection> current_direction) { + DCHECK(!sender->track() || + sender->track()->kind() == receiver->track()->kind()); + return new rtc::RefCountedObject<FakeRtpTransceiver>( + receiver->track()->kind() == + webrtc::MediaStreamTrackInterface::kAudioKind + ? cricket::MEDIA_TYPE_AUDIO + : cricket::MEDIA_TYPE_VIDEO, + std::move(sender), std::move(receiver), std::move(mid), stopped, + direction, std::move(current_direction)); + } + + RtpTransceiverState CreateTransceiverState( + rtc::scoped_refptr<webrtc::RtpTransceiverInterface> webrtc_transceiver, + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> + sender_track_ref, + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> + receiver_track_ref) { + std::vector<std::string> receiver_stream_ids; + for (const auto& stream : webrtc_transceiver->receiver()->streams()) { + receiver_stream_ids.push_back(stream->id()); + } + return RtpTransceiverState( + main_task_runner_, signaling_task_runner(), webrtc_transceiver.get(), + RtpSenderState(main_task_runner_, signaling_task_runner(), + webrtc_transceiver->sender().get(), + std::move(sender_track_ref), + webrtc_transceiver->sender()->stream_ids()), + RtpReceiverState(main_task_runner_, signaling_task_runner(), + webrtc_transceiver->receiver().get(), + std::move(receiver_track_ref), + std::move(receiver_stream_ids)), + ToBaseOptional(webrtc_transceiver->mid()), + webrtc_transceiver->stopped(), webrtc_transceiver->direction(), + ToBaseOptional(webrtc_transceiver->current_direction()), + ToBaseOptional(webrtc_transceiver->fired_direction())); + } + + protected: + blink::WebMediaStreamTrack CreateBlinkLocalTrack(const std::string& id) { + blink::WebMediaStreamSource web_source; + web_source.Initialize( + blink::WebString::FromUTF8(id), blink::WebMediaStreamSource::kTypeAudio, + blink::WebString::FromUTF8("local_audio_track"), false); + MediaStreamAudioSource* audio_source = new MediaStreamAudioSource(true); + // Takes ownership of |audio_source|. + web_source.SetExtraData(audio_source); + + blink::WebMediaStreamTrack web_track; + web_track.Initialize(web_source.Id(), web_source); + audio_source->ConnectToTrack(web_track); + return web_track; + } + + void CreateRemoteTrackAdapterOnSignalingThread( + rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track, + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>* track_ref, + base::RunLoop* run_loop) { + *track_ref = track_map_->GetOrCreateRemoteTrackAdapter(webrtc_track.get()); + run_loop->Quit(); + } + + private: + base::MessageLoop message_loop_; + + protected: + std::unique_ptr<MockPeerConnectionDependencyFactory> dependency_factory_; + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_map_; + rtc::scoped_refptr<MockPeerConnectionImpl> peer_connection_; +}; + +TEST_F(RTCRtpTransceiverTest, InitializeTransceiverState) { + auto local_track_adapter = CreateLocalTrackAndAdapter("local_track"); + auto remote_track_adapter = CreateRemoteTrackAndAdapter("remote_track"); + auto webrtc_transceiver = CreateWebRtcTransceiver( + CreateWebRtcSender(local_track_adapter->webrtc_track(), "local_stream"), + CreateWebRtcReceiver(remote_track_adapter->webrtc_track(), + "remote_stream"), + base::nullopt, false, webrtc::RtpTransceiverDirection::kSendRecv, + base::nullopt); + RtpTransceiverState transceiver_state = + CreateTransceiverState(webrtc_transceiver, std::move(local_track_adapter), + std::move(remote_track_adapter)); + EXPECT_FALSE(transceiver_state.is_initialized()); + transceiver_state.Initialize(); + + EXPECT_TRUE(transceiver_state.is_initialized()); + // Inspect sender states. + const auto& sender_state = transceiver_state.sender_state(); + EXPECT_TRUE(sender_state); + EXPECT_TRUE(sender_state->is_initialized()); + const auto& webrtc_sender = webrtc_transceiver->sender(); + EXPECT_EQ(sender_state->webrtc_sender().get(), webrtc_sender.get()); + EXPECT_TRUE(sender_state->track_ref()->is_initialized()); + EXPECT_EQ(sender_state->track_ref()->webrtc_track(), + webrtc_sender->track().get()); + EXPECT_EQ(sender_state->stream_ids(), webrtc_sender->stream_ids()); + // Inspect receiver states. + const auto& receiver_state = transceiver_state.receiver_state(); + EXPECT_TRUE(receiver_state); + EXPECT_TRUE(receiver_state->is_initialized()); + const auto& webrtc_receiver = webrtc_transceiver->receiver(); + EXPECT_EQ(receiver_state->webrtc_receiver().get(), webrtc_receiver.get()); + EXPECT_TRUE(receiver_state->track_ref()->is_initialized()); + EXPECT_EQ(receiver_state->track_ref()->webrtc_track(), + webrtc_receiver->track().get()); + std::vector<std::string> receiver_stream_ids; + for (const auto& stream : webrtc_receiver->streams()) { + receiver_stream_ids.push_back(stream->id()); + } + EXPECT_EQ(receiver_state->stream_ids(), receiver_stream_ids); + // Inspect transceiver states. + EXPECT_TRUE( + OptionalEquals(transceiver_state.mid(), webrtc_transceiver->mid())); + EXPECT_EQ(transceiver_state.stopped(), webrtc_transceiver->stopped()); + EXPECT_TRUE(transceiver_state.direction() == webrtc_transceiver->direction()); + EXPECT_TRUE(OptionalEquals(transceiver_state.current_direction(), + webrtc_transceiver->current_direction())); + EXPECT_TRUE(OptionalEquals(transceiver_state.fired_direction(), + webrtc_transceiver->fired_direction())); +} + +TEST_F(RTCRtpTransceiverTest, CreateTranceiver) { + auto local_track_adapter = CreateLocalTrackAndAdapter("local_track"); + auto remote_track_adapter = CreateRemoteTrackAndAdapter("remote_track"); + auto webrtc_transceiver = CreateWebRtcTransceiver( + CreateWebRtcSender(local_track_adapter->webrtc_track(), "local_stream"), + CreateWebRtcReceiver(remote_track_adapter->webrtc_track(), + "remote_stream"), + base::nullopt, false, webrtc::RtpTransceiverDirection::kSendRecv, + base::nullopt); + RtpTransceiverState transceiver_state = + CreateTransceiverState(webrtc_transceiver, std::move(local_track_adapter), + std::move(remote_track_adapter)); + EXPECT_FALSE(transceiver_state.is_initialized()); + transceiver_state.Initialize(); + + RTCRtpTransceiver transceiver(peer_connection_.get(), track_map_, + std::move(transceiver_state)); + EXPECT_TRUE(transceiver.Mid().IsNull()); + EXPECT_TRUE(transceiver.Sender()); + EXPECT_TRUE(transceiver.Receiver()); + EXPECT_FALSE(transceiver.Stopped()); + EXPECT_EQ(transceiver.Direction(), + webrtc::RtpTransceiverDirection::kSendRecv); + EXPECT_FALSE(transceiver.CurrentDirection()); + EXPECT_FALSE(transceiver.FiredDirection()); +} + +TEST_F(RTCRtpTransceiverTest, ModifyTransceiver) { + auto local_track_adapter = CreateLocalTrackAndAdapter("local_track"); + auto remote_track_adapter = CreateRemoteTrackAndAdapter("remote_track"); + auto webrtc_sender = + CreateWebRtcSender(local_track_adapter->webrtc_track(), "local_stream"); + auto webrtc_receiver = CreateWebRtcReceiver( + remote_track_adapter->webrtc_track(), "remote_stream"); + auto webrtc_transceiver = CreateWebRtcTransceiver( + webrtc_sender, webrtc_receiver, base::nullopt, false, + webrtc::RtpTransceiverDirection::kSendRecv, base::nullopt); + + // Create initial state. + RtpTransceiverState initial_transceiver_state = + CreateTransceiverState(webrtc_transceiver, local_track_adapter->Copy(), + remote_track_adapter->Copy()); + EXPECT_FALSE(initial_transceiver_state.is_initialized()); + initial_transceiver_state.Initialize(); + + // Modify the webrtc transceiver and create a new state object for the + // modified state. + *webrtc_transceiver = + *CreateWebRtcTransceiver(webrtc_sender, webrtc_receiver, "MidyMacMidface", + true, webrtc::RtpTransceiverDirection::kInactive, + webrtc::RtpTransceiverDirection::kSendRecv); + RtpTransceiverState modified_transceiver_state = + CreateTransceiverState(webrtc_transceiver, local_track_adapter->Copy(), + remote_track_adapter->Copy()); + EXPECT_FALSE(modified_transceiver_state.is_initialized()); + modified_transceiver_state.Initialize(); + + // Modifying the webrtc transceiver after the initial state was created should + // not have affected the transceiver state. + RTCRtpTransceiver transceiver(peer_connection_.get(), track_map_, + std::move(initial_transceiver_state)); + EXPECT_TRUE(transceiver.Mid().IsNull()); + EXPECT_TRUE(transceiver.Sender()); + EXPECT_TRUE(transceiver.Receiver()); + EXPECT_FALSE(transceiver.Stopped()); + EXPECT_EQ(transceiver.Direction(), + webrtc::RtpTransceiverDirection::kSendRecv); + EXPECT_FALSE(transceiver.CurrentDirection()); + EXPECT_FALSE(transceiver.FiredDirection()); + + // Setting the state should make the transceiver state up-to-date. + transceiver.set_state(std::move(modified_transceiver_state)); + EXPECT_EQ(transceiver.Mid(), "MidyMacMidface"); + EXPECT_TRUE(transceiver.Sender()); + EXPECT_TRUE(transceiver.Receiver()); + EXPECT_TRUE(transceiver.Stopped()); + EXPECT_EQ(transceiver.Direction(), + webrtc::RtpTransceiverDirection::kInactive); + EXPECT_TRUE(transceiver.CurrentDirection() == + webrtc::RtpTransceiverDirection::kSendRecv); + EXPECT_FALSE(transceiver.FiredDirection()); +} + +TEST_F(RTCRtpTransceiverTest, ShallowCopy) { + auto local_track_adapter = CreateLocalTrackAndAdapter("local_track"); + auto remote_track_adapter = CreateRemoteTrackAndAdapter("remote_track"); + auto webrtc_sender = + CreateWebRtcSender(local_track_adapter->webrtc_track(), "local_stream"); + auto webrtc_receiver = CreateWebRtcReceiver( + remote_track_adapter->webrtc_track(), "remote_stream"); + auto webrtc_transceiver = CreateWebRtcTransceiver( + webrtc_sender, webrtc_receiver, base::nullopt, false /* stopped */, + webrtc::RtpTransceiverDirection::kSendRecv, base::nullopt); + + std::unique_ptr<RTCRtpTransceiver> transceiver; + // Create transceiver. + { + RtpTransceiverState transceiver_state = + CreateTransceiverState(webrtc_transceiver, local_track_adapter->Copy(), + remote_track_adapter->Copy()); + EXPECT_FALSE(transceiver_state.is_initialized()); + transceiver_state.Initialize(); + transceiver.reset(new RTCRtpTransceiver(peer_connection_.get(), track_map_, + std::move(transceiver_state))); + } + DCHECK(transceiver); + EXPECT_FALSE(transceiver->Stopped()); + + std::unique_ptr<RTCRtpTransceiver> shallow_copy = transceiver->ShallowCopy(); + // Modifying the shallow copy should modify the original too since they have a + // shared internal state. + { + // Modify webrtc transceiver to be stopped. + *webrtc_transceiver = *CreateWebRtcTransceiver( + webrtc_sender, webrtc_receiver, base::nullopt, true /* stopped */, + webrtc::RtpTransceiverDirection::kSendRecv, base::nullopt); + RtpTransceiverState transceiver_state = + CreateTransceiverState(webrtc_transceiver, local_track_adapter->Copy(), + remote_track_adapter->Copy()); + EXPECT_FALSE(transceiver_state.is_initialized()); + transceiver_state.Initialize(); + // Set the state of the shallow copy. + shallow_copy->set_state(std::move(transceiver_state)); + } + EXPECT_TRUE(shallow_copy->Stopped()); + EXPECT_TRUE(transceiver->Stopped()); +} + +} // namespace content diff --git a/chromium/content/renderer/media/webrtc/rtc_stats.cc b/chromium/content/renderer/media/webrtc/rtc_stats.cc index 0c7478f8646..a24ef5bc613 100644 --- a/chromium/content/renderer/media/webrtc/rtc_stats.cc +++ b/chromium/content/renderer/media/webrtc/rtc_stats.cc @@ -4,6 +4,7 @@ #include "content/renderer/media/webrtc/rtc_stats.h" +#include <algorithm> #include <set> #include <string> @@ -57,6 +58,22 @@ bool IsWhitelistedStats(const webrtc::RTCStats& stats) { return GetStatsWhitelist()->IsWhitelisted(stats); } +// Filters out any unstandardized members; stats should only be surfaced to JS +// if they're standardized. +std::vector<const webrtc::RTCStatsMemberInterface*> StandardizedMembers( + std::vector<const webrtc::RTCStatsMemberInterface*> stats_members) { + // Note that using "is_standarized" avoids having to maintain a whitelist of + // every single standardized member, as we do at the "stats object" level + // with "RTCStatsWhitelist". + stats_members.erase( + std::remove_if(stats_members.begin(), stats_members.end(), + [](const webrtc::RTCStatsMemberInterface* member) { + return !member->is_standardized(); + }), + stats_members.end()); + return stats_members; +} + } // namespace RTCStatsReport::RTCStatsReport( @@ -105,7 +122,7 @@ RTCStats::RTCStats( const webrtc::RTCStats* stats) : stats_owner_(stats_owner), stats_(stats), - stats_members_(stats->Members()) { + stats_members_(StandardizedMembers(stats->Members())) { DCHECK(stats_owner_); DCHECK(stats_); DCHECK(stats_owner_->Get(stats_->id())); diff --git a/chromium/content/renderer/media/webrtc/rtc_stats.h b/chromium/content/renderer/media/webrtc/rtc_stats.h index 937cb25f3f0..370ab41d587 100644 --- a/chromium/content/renderer/media/webrtc/rtc_stats.h +++ b/chromium/content/renderer/media/webrtc/rtc_stats.h @@ -15,6 +15,9 @@ namespace content { +// Wrapper around a webrtc::RTCStatsReport that also filters out any stats +// objects that aren't whitelisted, and any members that aren't standardized +// (using RTCStatsMemberInterface::is_standardized). class CONTENT_EXPORT RTCStatsReport : public blink::WebRTCStatsReport { public: RTCStatsReport( diff --git a/chromium/content/renderer/media/webrtc/rtc_stats_unittest.cc b/chromium/content/renderer/media/webrtc/rtc_stats_unittest.cc index 379f3bc0918..6cf1d5bd49b 100644 --- a/chromium/content/renderer/media/webrtc/rtc_stats_unittest.cc +++ b/chromium/content/renderer/media/webrtc/rtc_stats_unittest.cc @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <memory> + #include "content/renderer/media/webrtc/rtc_stats.h" #include "testing/gtest/include/gtest/gtest.h" @@ -45,4 +47,47 @@ TEST(RTCStatsTest, OnlyIncludeWhitelistedStats_Iteration) { EXPECT_FALSE(report.Next()); } +// Stats object with both a standard and non-standard member, used for the test +// below. +namespace { +class TestStats : public webrtc::RTCStats { + public: + WEBRTC_RTCSTATS_DECL(); + + TestStats(const std::string& id, int64_t timestamp_us); + ~TestStats() override = default; + + webrtc::RTCStatsMember<int32_t> standardized; + webrtc::RTCNonStandardStatsMember<int32_t> non_standardized; +}; + +WEBRTC_RTCSTATS_IMPL(TestStats, + webrtc::RTCStats, + "teststats", + &standardized, + &non_standardized); + +TestStats::TestStats(const std::string& id, int64_t timestamp_us) + : RTCStats(id, timestamp_us), + standardized("standardized"), + non_standardized("non_standardized") {} +} // namespace + +// Similar to how only whitelisted stats objects should be surfaced, only +// standardized members of the whitelisted objects should be surfaced. +TEST(RTCStatsTest, OnlyIncludeStandarizedMembers) { + rtc::scoped_refptr<webrtc::RTCStatsReport> webrtc_report = + webrtc::RTCStatsReport::Create(42); + WhitelistStatsForTesting(TestStats::kType); + webrtc_report->AddStats(std::make_unique<TestStats>("id", 0)); + + // TestStats has two members, but the non-standard member should be filtered + // out. + RTCStatsReport report(webrtc_report.get()); + std::unique_ptr<blink::WebRTCStats> stats = report.Next(); + ASSERT_NE(nullptr, stats); + ASSERT_EQ(1u, stats->MembersCount()); + EXPECT_EQ("standardized", stats->GetMember(0)->GetName()); +} + } // namespace content diff --git a/chromium/content/renderer/media/webrtc/rtc_video_decoder_unittest.cc b/chromium/content/renderer/media/webrtc/rtc_video_decoder_unittest.cc index 050c9f61d84..864cb65f90c 100644 --- a/chromium/content/renderer/media/webrtc/rtc_video_decoder_unittest.cc +++ b/chromium/content/renderer/media/webrtc/rtc_video_decoder_unittest.cc @@ -70,6 +70,8 @@ class RTCVideoDecoderTest capabilities_.supported_profiles.push_back(supported_profile); supported_profile.profile = media::VP8PROFILE_ANY; capabilities_.supported_profiles.push_back(supported_profile); + supported_profile.profile = media::VP9PROFILE_MIN; + capabilities_.supported_profiles.push_back(supported_profile); EXPECT_CALL(*mock_gpu_factories_.get(), GetTaskRunner()) .WillRepeatedly(Return(vda_task_runner_)); @@ -231,6 +233,24 @@ TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnMissingFrames) { rtc_decoder_->Decode(input_image, missingFrames, nullptr, 0)); } +TEST_F(RTCVideoDecoderTest, FallBackToSoftwareOnVp9Svc) { + // HW VP9 decoders don't handle more than one spatial layer. See + // https://crbug.com/webrtc/9304, https://crbug.com/webrtc/9518 for details. + // The RTC video decoder triggers software fallback if it receives stream + // with more than one spatial layer. + CreateDecoder(webrtc::kVideoCodecVP9); + Initialize(); + + webrtc::CodecSpecificInfo codec_specific_info; + codec_specific_info.codecType = webrtc::kVideoCodecVP9; + codec_specific_info.codecSpecific.VP9.ss_data_available = true; + codec_specific_info.codecSpecific.VP9.num_spatial_layers = 2; + + webrtc::EncodedImage input_image; + EXPECT_EQ(WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE, + rtc_decoder_->Decode(input_image, false, &codec_specific_info, 0)); +} + TEST_F(RTCVideoDecoderTest, ReleaseReturnsOk) { CreateDecoder(webrtc::kVideoCodecVP8); Initialize(); diff --git a/chromium/content/renderer/media/webrtc/rtc_video_encoder.cc b/chromium/content/renderer/media/webrtc/rtc_video_encoder.cc index bfa722c5fc2..69f49db28bc 100644 --- a/chromium/content/renderer/media/webrtc/rtc_video_encoder.cc +++ b/chromium/content/renderer/media/webrtc/rtc_video_encoder.cc @@ -17,7 +17,6 @@ #include "base/macros.h" #include "base/metrics/histogram_macros.h" #include "base/numerics/safe_conversions.h" -#include "base/rand_util.h" #include "base/single_thread_task_runner.h" #include "base/synchronization/lock.h" #include "base/synchronization/waitable_event.h" @@ -115,7 +114,8 @@ class RTCVideoEncoder::Impl public base::RefCountedThreadSafe<RTCVideoEncoder::Impl> { public: Impl(media::GpuVideoAcceleratorFactories* gpu_factories, - webrtc::VideoCodecType video_codec_type); + webrtc::VideoCodecType video_codec_type, + webrtc::VideoContentType video_content_type); // Create the VEA and call Initialize() on it. Called once per instantiation, // and then the instance is bound forevermore to whichever thread made the @@ -163,10 +163,9 @@ class RTCVideoEncoder::Impl void RequireBitstreamBuffers(unsigned int input_count, const gfx::Size& input_coded_size, size_t output_buffer_size) override; - void BitstreamBufferReady(int32_t bitstream_buffer_id, - size_t payload_size, - bool key_frame, - base::TimeDelta timestamp) override; + void BitstreamBufferReady( + int32_t bitstream_buffer_id, + const media::BitstreamBufferMetadata& metadata) override; void NotifyError(media::VideoEncodeAccelerator::Error error) override; private: @@ -206,8 +205,7 @@ class RTCVideoEncoder::Impl // Return an encoded output buffer to WebRTC. void ReturnEncodedImage(const webrtc::EncodedImage& image, - int32_t bitstream_buffer_id, - uint16_t picture_id); + int32_t bitstream_buffer_id); void SetStatus(int32_t status); @@ -262,15 +260,15 @@ class RTCVideoEncoder::Impl // encoder. int output_buffers_free_count_; - // 15 bits running index of the VP8 frames. See VP8 RTP spec for details. - uint16_t picture_id_; - // webrtc::VideoEncoder encode complete callback. webrtc::EncodedImageCallback* encoded_image_callback_; // The video codec type, as reported to WebRTC. const webrtc::VideoCodecType video_codec_type_; + // The content type, as reported to WebRTC (screenshare vs realtime video). + const webrtc::VideoContentType video_content_type_; + // Protect |status_|. |status_| is read or written on |gpu_task_runner_| in // Impl. It can be read in RTCVideoEncoder on other threads. mutable base::Lock status_lock_; @@ -285,7 +283,8 @@ class RTCVideoEncoder::Impl }; RTCVideoEncoder::Impl::Impl(media::GpuVideoAcceleratorFactories* gpu_factories, - webrtc::VideoCodecType video_codec_type) + webrtc::VideoCodecType video_codec_type, + webrtc::VideoContentType video_content_type) : gpu_factories_(gpu_factories), async_waiter_(nullptr), async_retval_(nullptr), @@ -295,10 +294,9 @@ RTCVideoEncoder::Impl::Impl(media::GpuVideoAcceleratorFactories* gpu_factories, output_buffers_free_count_(0), encoded_image_callback_(nullptr), video_codec_type_(video_codec_type), + video_content_type_(video_content_type), status_(WEBRTC_VIDEO_CODEC_UNINITIALIZED) { thread_checker_.DetachFromThread(); - // Picture ID should start on a random number. - picture_id_ = static_cast<uint16_t>(base::RandInt(0, 0x7FFF)); } void RTCVideoEncoder::Impl::CreateAndInitializeVEA( @@ -505,13 +503,13 @@ void RTCVideoEncoder::Impl::RequireBitstreamBuffers( SignalAsyncWaiter(WEBRTC_VIDEO_CODEC_OK); } -void RTCVideoEncoder::Impl::BitstreamBufferReady(int32_t bitstream_buffer_id, - size_t payload_size, - bool key_frame, - base::TimeDelta timestamp) { +void RTCVideoEncoder::Impl::BitstreamBufferReady( + int32_t bitstream_buffer_id, + const media::BitstreamBufferMetadata& metadata) { DVLOG(3) << __func__ << " bitstream_buffer_id=" << bitstream_buffer_id - << ", payload_size=" << payload_size << ", key_frame=" << key_frame - << ", timestamp ms=" << timestamp.InMilliseconds(); + << ", payload_size=" << metadata.payload_size_bytes + << ", key_frame=" << metadata.key_frame + << ", timestamp ms=" << metadata.timestamp.InMilliseconds(); DCHECK(thread_checker_.CalledOnValidThread()); if (bitstream_buffer_id < 0 || @@ -522,7 +520,7 @@ void RTCVideoEncoder::Impl::BitstreamBufferReady(int32_t bitstream_buffer_id, } base::SharedMemory* output_buffer = output_buffers_[bitstream_buffer_id].get(); - if (payload_size > output_buffer->mapped_size()) { + if (metadata.payload_size_bytes > output_buffer->mapped_size()) { LogAndNotifyError(FROM_HERE, "invalid payload_size", media::VideoEncodeAccelerator::kPlatformFailureError); return; @@ -537,7 +535,7 @@ void RTCVideoEncoder::Impl::BitstreamBufferReady(int32_t bitstream_buffer_id, // Pop timestamps until we have a match. while (!pending_timestamps_.empty()) { const auto& front_timestamps = pending_timestamps_.front(); - if (front_timestamps.media_timestamp_ == timestamp) { + if (front_timestamps.media_timestamp_ == metadata.timestamp) { rtp_timestamp = front_timestamps.rtp_timestamp; capture_timestamp_ms = front_timestamps.capture_time_ms; pending_timestamps_.pop_front(); @@ -558,19 +556,18 @@ void RTCVideoEncoder::Impl::BitstreamBufferReady(int32_t bitstream_buffer_id, } webrtc::EncodedImage image( - reinterpret_cast<uint8_t*>(output_buffer->memory()), payload_size, - output_buffer->mapped_size()); + reinterpret_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(); image.capture_time_ms_ = capture_timestamp_ms.value(); image._frameType = - (key_frame ? webrtc::kVideoFrameKey : webrtc::kVideoFrameDelta); + (metadata.key_frame ? webrtc::kVideoFrameKey : webrtc::kVideoFrameDelta); + image.content_type_ = video_content_type_; image._completeFrame = true; - ReturnEncodedImage(image, bitstream_buffer_id, picture_id_); - // Picture ID must wrap after reaching the maximum. - picture_id_ = (picture_id_ + 1) & 0x7FFF; + ReturnEncodedImage(image, bitstream_buffer_id); } void RTCVideoEncoder::Impl::NotifyError( @@ -759,11 +756,9 @@ void RTCVideoEncoder::Impl::RegisterEncodeCompleteCallback( void RTCVideoEncoder::Impl::ReturnEncodedImage( const webrtc::EncodedImage& image, - int32_t bitstream_buffer_id, - uint16_t picture_id) { + int32_t bitstream_buffer_id) { DCHECK(thread_checker_.CalledOnValidThread()); - DVLOG(3) << __func__ << " bitstream_buffer_id=" << bitstream_buffer_id - << ", picture_id=" << picture_id; + DVLOG(3) << __func__ << " bitstream_buffer_id=" << bitstream_buffer_id; if (!encoded_image_callback_) return; @@ -798,8 +793,6 @@ void RTCVideoEncoder::Impl::ReturnEncodedImage( info.codecType = video_codec_type_; info.codec_name = ImplementationName(); if (video_codec_type_ == webrtc::kVideoCodecVP8) { - info.codecSpecific.VP8.pictureId = picture_id; - info.codecSpecific.VP8.tl0PicIdx = -1; info.codecSpecific.VP8.keyIdx = -1; } @@ -840,7 +833,7 @@ int32_t RTCVideoEncoder::InitEncode(const webrtc::VideoCodec* codec_settings, Release(); if (codec_settings->codecType == webrtc::kVideoCodecVP8 && - codec_settings->mode == webrtc::kScreensharing && + codec_settings->mode == webrtc::VideoCodecMode::kScreensharing && codec_settings->VP8().numberOfTemporalLayers > 1) { // This is a VP8 stream with screensharing using temporal layers for // temporal scalability. Since this implementation does not yet implement @@ -854,7 +847,11 @@ int32_t RTCVideoEncoder::InitEncode(const webrtc::VideoCodec* codec_settings, } } - impl_ = new Impl(gpu_factories_, ProfileToWebRtcVideoCodecType(profile_)); + impl_ = + new Impl(gpu_factories_, ProfileToWebRtcVideoCodecType(profile_), + (codec_settings->mode == webrtc::VideoCodecMode::kScreensharing) + ? webrtc::VideoContentType::SCREENSHARE + : webrtc::VideoContentType::UNSPECIFIED); base::WaitableEvent initialization_waiter( base::WaitableEvent::ResetPolicy::MANUAL, diff --git a/chromium/content/renderer/media/webrtc/rtc_video_encoder_factory.cc b/chromium/content/renderer/media/webrtc/rtc_video_encoder_factory.cc index 3307c40e0b8..7b89e610a23 100644 --- a/chromium/content/renderer/media/webrtc/rtc_video_encoder_factory.cc +++ b/chromium/content/renderer/media/webrtc/rtc_video_encoder_factory.cc @@ -73,7 +73,7 @@ base::Optional<cricket::VideoCodec> VEAToWebRTCCodec( const int fps = profile.max_framerate_numerator; DCHECK_EQ(1u, profile.max_framerate_denominator); - const rtc::Optional<webrtc::H264::Level> h264_level = + const absl::optional<webrtc::H264::Level> h264_level = webrtc::H264::SupportedLevel(width * height, fps); const webrtc::H264::ProfileLevelId profile_level_id( h264_profile, h264_level.value_or(webrtc::H264::kLevel1)); 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 d3defba9124..2d142d5aa82 100644 --- a/chromium/content/renderer/media/webrtc/rtc_video_encoder_unittest.cc +++ b/chromium/content/renderer/media/webrtc/rtc_video_encoder_unittest.cc @@ -180,7 +180,9 @@ class RTCVideoEncoderTest void ReturnFrameWithTimeStamp(const scoped_refptr<media::VideoFrame>& frame, bool force_keyframe) { - client_->BitstreamBufferReady(0, 0, force_keyframe, frame->timestamp()); + client_->BitstreamBufferReady( + 0, + media::BitstreamBufferMetadata(0, force_keyframe, frame->timestamp())); } void VerifyTimestamp(uint32_t rtp_timestamp, diff --git a/chromium/content/renderer/media/webrtc/transceiver_state_surfacer.cc b/chromium/content/renderer/media/webrtc/transceiver_state_surfacer.cc new file mode 100644 index 00000000000..4792cefac27 --- /dev/null +++ b/chromium/content/renderer/media/webrtc/transceiver_state_surfacer.cc @@ -0,0 +1,225 @@ +// 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/transceiver_state_surfacer.h" + +#include "content/renderer/media/webrtc/webrtc_util.h" +#include "third_party/webrtc/api/rtptransceiverinterface.h" + +namespace content { + +TransceiverStateSurfacer::TransceiverStateSurfacer( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner) + : main_task_runner_(std::move(main_task_runner)), + signaling_task_runner_(std::move(signaling_task_runner)), + is_initialized_(false), + states_obtained_(false) { + DCHECK(main_task_runner_); + DCHECK(signaling_task_runner_); +} + +TransceiverStateSurfacer::TransceiverStateSurfacer( + TransceiverStateSurfacer&& other) + : main_task_runner_(other.main_task_runner_), + signaling_task_runner_(other.signaling_task_runner_), + is_initialized_(other.is_initialized_), + states_obtained_(other.states_obtained_), + transceiver_states_(std::move(other.transceiver_states_)) { + // Explicitly null |other|'s task runners for use in destructor. + other.main_task_runner_ = nullptr; + other.signaling_task_runner_ = nullptr; +} + +TransceiverStateSurfacer::~TransceiverStateSurfacer() { + // It's OK to not be on the main thread if this object has been moved, in + // which case |main_task_runner_| is null. + DCHECK(!main_task_runner_ || main_task_runner_->BelongsToCurrentThread()); +} + +TransceiverStateSurfacer& TransceiverStateSurfacer::operator=( + TransceiverStateSurfacer&& other) { + main_task_runner_ = other.main_task_runner_; + signaling_task_runner_ = other.signaling_task_runner_; + states_obtained_ = other.states_obtained_; + transceiver_states_ = std::move(other.transceiver_states_); + // Explicitly null |other|'s task runners for use in destructor. + other.main_task_runner_ = nullptr; + other.signaling_task_runner_ = nullptr; + return *this; +} + +void TransceiverStateSurfacer::Initialize( + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, + std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> + webrtc_transceivers) { + DCHECK(signaling_task_runner_->BelongsToCurrentThread()); + DCHECK(!is_initialized_); + for (auto& webrtc_transceiver : webrtc_transceivers) { + // Create the sender state. + base::Optional<RtpSenderState> sender_state; + auto webrtc_sender = webrtc_transceiver->sender(); + if (webrtc_sender) { + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> + sender_track_ref; + if (webrtc_sender->track()) { + // The track adapter for this track must already exist for us to obtain + // it, since this cannot be created from the signaling thread. + // TODO(hbos): Consider either making it possible to create local track + // adapters on the signaling thread for initialization on the main + // thread or wait for Onion Souping to simplify this. + // https://crbug.com/787254 + sender_track_ref = + track_adapter_map->GetLocalTrackAdapter(webrtc_sender->track()); + CHECK(sender_track_ref); + } + sender_state = RtpSenderState( + main_task_runner_, signaling_task_runner_, webrtc_sender.get(), + std::move(sender_track_ref), webrtc_sender->stream_ids()); + } + // Create the receiver state. + base::Optional<RtpReceiverState> receiver_state; + auto webrtc_receiver = webrtc_transceiver->receiver(); + if (webrtc_receiver) { + DCHECK(webrtc_receiver->track()); + auto receiver_track_ref = + track_adapter_map->GetOrCreateRemoteTrackAdapter( + webrtc_receiver->track().get()); + DCHECK(receiver_track_ref); + std::vector<std::string> receiver_stream_ids; + for (auto& stream : webrtc_receiver->streams()) { + receiver_stream_ids.push_back(stream->id()); + } + receiver_state = RtpReceiverState( + main_task_runner_, signaling_task_runner_, webrtc_receiver.get(), + std::move(receiver_track_ref), std::move(receiver_stream_ids)); + } + // Create the transceiver state. + transceiver_states_.push_back(RtpTransceiverState( + main_task_runner_, signaling_task_runner_, webrtc_transceiver.get(), + std::move(sender_state), std::move(receiver_state), + ToBaseOptional(webrtc_transceiver->mid()), + webrtc_transceiver->stopped(), webrtc_transceiver->direction(), + ToBaseOptional(webrtc_transceiver->current_direction()), + ToBaseOptional(webrtc_transceiver->fired_direction()))); + } + is_initialized_ = true; +} + +std::vector<RtpTransceiverState> TransceiverStateSurfacer::ObtainStates() { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + DCHECK(is_initialized_); + for (auto& transceiver_state : transceiver_states_) + transceiver_state.Initialize(); + states_obtained_ = true; + return std::move(transceiver_states_); +} + +SurfaceSenderStateOnly::SurfaceSenderStateOnly( + rtc::scoped_refptr<webrtc::RtpSenderInterface> sender) + : sender_(std::move(sender)) { + DCHECK(sender_); +} + +SurfaceSenderStateOnly::~SurfaceSenderStateOnly() {} + +cricket::MediaType SurfaceSenderStateOnly::media_type() const { + return sender_->media_type(); +} + +absl::optional<std::string> SurfaceSenderStateOnly::mid() const { + return absl::nullopt; +} + +rtc::scoped_refptr<webrtc::RtpSenderInterface> SurfaceSenderStateOnly::sender() + const { + return sender_; +} + +rtc::scoped_refptr<webrtc::RtpReceiverInterface> +SurfaceSenderStateOnly::receiver() const { + return nullptr; +} + +bool SurfaceSenderStateOnly::stopped() const { + return false; +} + +webrtc::RtpTransceiverDirection SurfaceSenderStateOnly::direction() const { + return webrtc::RtpTransceiverDirection::kSendOnly; +} + +void SurfaceSenderStateOnly::SetDirection( + webrtc::RtpTransceiverDirection new_direction) { + NOTIMPLEMENTED(); +} + +absl::optional<webrtc::RtpTransceiverDirection> +SurfaceSenderStateOnly::current_direction() const { + return absl::nullopt; +} + +void SurfaceSenderStateOnly::Stop() { + NOTIMPLEMENTED(); +} + +void SurfaceSenderStateOnly::SetCodecPreferences( + rtc::ArrayView<webrtc::RtpCodecCapability> codecs) { + NOTIMPLEMENTED(); +} + +SurfaceReceiverStateOnly::SurfaceReceiverStateOnly( + rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver) + : receiver_(std::move(receiver)) { + DCHECK(receiver_); +} + +SurfaceReceiverStateOnly::~SurfaceReceiverStateOnly() {} + +cricket::MediaType SurfaceReceiverStateOnly::media_type() const { + return receiver_->media_type(); +} + +absl::optional<std::string> SurfaceReceiverStateOnly::mid() const { + return absl::nullopt; +} + +rtc::scoped_refptr<webrtc::RtpSenderInterface> +SurfaceReceiverStateOnly::sender() const { + return nullptr; +} + +rtc::scoped_refptr<webrtc::RtpReceiverInterface> +SurfaceReceiverStateOnly::receiver() const { + return receiver_; +} + +bool SurfaceReceiverStateOnly::stopped() const { + return false; +} + +webrtc::RtpTransceiverDirection SurfaceReceiverStateOnly::direction() const { + return webrtc::RtpTransceiverDirection::kRecvOnly; +} + +void SurfaceReceiverStateOnly::SetDirection( + webrtc::RtpTransceiverDirection new_direction) { + NOTIMPLEMENTED(); +} + +absl::optional<webrtc::RtpTransceiverDirection> +SurfaceReceiverStateOnly::current_direction() const { + return absl::nullopt; +} + +void SurfaceReceiverStateOnly::Stop() { + NOTIMPLEMENTED(); +} + +void SurfaceReceiverStateOnly::SetCodecPreferences( + rtc::ArrayView<webrtc::RtpCodecCapability> codecs) { + NOTIMPLEMENTED(); +} + +} // namespace content diff --git a/chromium/content/renderer/media/webrtc/transceiver_state_surfacer.h b/chromium/content/renderer/media/webrtc/transceiver_state_surfacer.h new file mode 100644 index 00000000000..ab7cdfeb695 --- /dev/null +++ b/chromium/content/renderer/media/webrtc/transceiver_state_surfacer.h @@ -0,0 +1,112 @@ +// 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_TRANSCEIVER_STATE_SURFACER_H_ +#define CONTENT_RENDERER_MEDIA_WEBRTC_TRANSCEIVER_STATE_SURFACER_H_ + +#include "content/renderer/media/webrtc/rtc_rtp_transceiver.h" +#include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h" +#include "third_party/webrtc/api/rtptransceiverinterface.h" +#include "third_party/webrtc/rtc_base/refcount.h" +#include "third_party/webrtc/rtc_base/refcountedobject.h" + +namespace content { + +// Takes care of creating and initializing transceiver states (including sender +// and receiver states). This is usable for both blocking and non-blocking calls +// to the webrtc signaling thread. +// +// The surfacer is initialized on the signaling thread and states are obtained +// on the main thread. It is designed to be initialized and handed off; it is +// not thread safe for concurrent thread usage. +class CONTENT_EXPORT TransceiverStateSurfacer { + public: + TransceiverStateSurfacer( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner); + TransceiverStateSurfacer(TransceiverStateSurfacer&&); + TransceiverStateSurfacer(const TransceiverStateSurfacer&) = delete; + ~TransceiverStateSurfacer(); + + // This is intended to be used for moving the object from the signaling thread + // to the main thread and as such has no thread checks. Once moved to the main + // this should only be invoked on the main thread. + TransceiverStateSurfacer& operator=(TransceiverStateSurfacer&&); + TransceiverStateSurfacer& operator=(const TransceiverStateSurfacer&) = delete; + + bool is_initialized() const { return is_initialized_; } + + // Must be invoked on the signaling thread. + void Initialize( + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, + std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> + transceivers); + + // Must be invoked on the main thread. + std::vector<RtpTransceiverState> ObtainStates(); + + protected: + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner_; + bool is_initialized_; + bool states_obtained_; + std::vector<RtpTransceiverState> transceiver_states_; +}; + +// A dummy implementation of a transceiver used to surface sender state +// information only. It is not thread safe, only designed to be passed on to +// TransceiverStateSurfacer::Initialize(). +class CONTENT_EXPORT SurfaceSenderStateOnly + : public rtc::RefCountedObject<webrtc::RtpTransceiverInterface> { + public: + SurfaceSenderStateOnly(rtc::scoped_refptr<webrtc::RtpSenderInterface> sender); + ~SurfaceSenderStateOnly() override; + + cricket::MediaType media_type() const override; + absl::optional<std::string> mid() const override; + rtc::scoped_refptr<webrtc::RtpSenderInterface> sender() const override; + rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver() const override; + bool stopped() const override; + webrtc::RtpTransceiverDirection direction() const override; + void SetDirection(webrtc::RtpTransceiverDirection new_direction) override; + absl::optional<webrtc::RtpTransceiverDirection> current_direction() + const override; + void Stop() override; + void SetCodecPreferences( + rtc::ArrayView<webrtc::RtpCodecCapability> codecs) override; + + private: + rtc::scoped_refptr<webrtc::RtpSenderInterface> sender_; +}; + +// A dummy implementation of a transceiver used to surface receiver state +// information only. It is not thread safe, only designed to be passed on to +// TransceiverStateSurfacer::Initialize(). +class CONTENT_EXPORT SurfaceReceiverStateOnly + : public rtc::RefCountedObject<webrtc::RtpTransceiverInterface> { + public: + SurfaceReceiverStateOnly( + rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver); + ~SurfaceReceiverStateOnly() override; + + cricket::MediaType media_type() const override; + absl::optional<std::string> mid() const override; + rtc::scoped_refptr<webrtc::RtpSenderInterface> sender() const override; + rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver() const override; + bool stopped() const override; + webrtc::RtpTransceiverDirection direction() const override; + void SetDirection(webrtc::RtpTransceiverDirection new_direction) override; + absl::optional<webrtc::RtpTransceiverDirection> current_direction() + const override; + void Stop() override; + void SetCodecPreferences( + rtc::ArrayView<webrtc::RtpCodecCapability> codecs) override; + + private: + rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver_; +}; + +} // namespace content + +#endif // CONTENT_RENDERER_MEDIA_WEBRTC_TRANSCEIVER_STATE_SURFACER_H_ diff --git a/chromium/content/renderer/media/webrtc/transceiver_state_surfacer_unittest.cc b/chromium/content/renderer/media/webrtc/transceiver_state_surfacer_unittest.cc new file mode 100644 index 00000000000..7f469865324 --- /dev/null +++ b/chromium/content/renderer/media/webrtc/transceiver_state_surfacer_unittest.cc @@ -0,0 +1,294 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/renderer/media/webrtc/transceiver_state_surfacer.h" + +#include <memory> +#include <tuple> + +#include "base/memory/ref_counted.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/stream/media_stream_audio_source.h" +#include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h" +#include "content/renderer/media/webrtc/mock_peer_connection_impl.h" +#include "content/renderer/media/webrtc/webrtc_util.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" +#include "third_party/blink/public/platform/web_media_stream_source.h" +#include "third_party/blink/public/platform/web_media_stream_track.h" +#include "third_party/blink/public/platform/web_string.h" +#include "third_party/blink/public/web/web_heap.h" + +namespace content { + +class TransceiverStateSurfacerTest : public ::testing::Test { + public: + void SetUp() override { + dependency_factory_.reset(new MockPeerConnectionDependencyFactory()); + main_task_runner_ = blink::scheduler::GetSingleThreadTaskRunnerForTesting(); + track_adapter_map_ = new WebRtcMediaStreamTrackAdapterMap( + dependency_factory_.get(), main_task_runner_); + surfacer_.reset(new TransceiverStateSurfacer(main_task_runner_, + signaling_task_runner())); + } + + void TearDown() override { + // Make sure posted tasks get a chance to execute or else the stuff is + // teared down while things are in flight. + base::RunLoop().RunUntilIdle(); + blink::WebHeap::CollectAllGarbageForTesting(); + } + + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner() const { + return dependency_factory_->GetWebRtcSignalingThread(); + } + + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> + CreateLocalTrackAndAdapter(const std::string& id) { + return track_adapter_map_->GetOrCreateLocalTrackAdapter( + CreateBlinkLocalTrack(id)); + } + + rtc::scoped_refptr<webrtc::RtpTransceiverInterface> CreateWebRtcTransceiver( + rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> local_track, + const std::string& local_stream_id, + const std::string& remote_track_id, + const std::string& remote_stream_id) { + return new rtc::RefCountedObject<FakeRtpTransceiver>( + local_track->kind() == webrtc::MediaStreamTrackInterface::kAudioKind + ? cricket::MEDIA_TYPE_AUDIO + : cricket::MEDIA_TYPE_VIDEO, + CreateWebRtcSender(local_track, local_stream_id), + CreateWebRtcReceiver(remote_track_id, remote_stream_id), base::nullopt, + false, webrtc::RtpTransceiverDirection::kSendRecv, base::nullopt); + } + + rtc::scoped_refptr<webrtc::RtpSenderInterface> CreateWebRtcSender( + rtc::scoped_refptr<webrtc::MediaStreamTrackInterface> track, + const std::string& stream_id) { + return new rtc::RefCountedObject<FakeRtpSender>( + std::move(track), std::vector<std::string>({stream_id})); + } + + rtc::scoped_refptr<webrtc::RtpReceiverInterface> CreateWebRtcReceiver( + const std::string& track_id, + const std::string& stream_id) { + rtc::scoped_refptr<webrtc::AudioTrackInterface> remote_track = + MockWebRtcAudioTrack::Create(track_id).get(); + rtc::scoped_refptr<webrtc::MediaStreamInterface> remote_stream( + new rtc::RefCountedObject<MockMediaStream>(stream_id)); + return new rtc::RefCountedObject<FakeRtpReceiver>( + remote_track.get(), + std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>( + {remote_stream})); + } + + // Initializes the surfacer on the signaling thread and signals the waitable + // event when done. The WaitableEvent's Wait() blocks the main thread until + // initialization occurs. + std::unique_ptr<base::WaitableEvent> AsyncInitializeSurfacerWithWaitableEvent( + std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> + transceivers) { + std::unique_ptr<base::WaitableEvent> waitable_event(new base::WaitableEvent( + base::WaitableEvent::ResetPolicy::MANUAL, + base::WaitableEvent::InitialState::NOT_SIGNALED)); + signaling_task_runner()->PostTask( + FROM_HERE, + base::BindOnce( + &TransceiverStateSurfacerTest:: + AsyncInitializeSurfacerWithWaitableEventOnSignalingThread, + base::Unretained(this), std::move(transceivers), + waitable_event.get())); + return waitable_event; + } + + // Initializes the surfacer on the signaling thread and posts back to the main + // thread to execute the callback when done. The RunLoop quits after the + // callback is executed. Use the RunLoop's Run() method to allow the posted + // task (such as the callback) to be executed while waiting. The caller must + // let the loop Run() before destroying it. + std::unique_ptr<base::RunLoop> AsyncInitializeSurfacerWithCallback( + std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> + transceivers, + base::OnceCallback<void()> callback) { + std::unique_ptr<base::RunLoop> run_loop(new base::RunLoop()); + signaling_task_runner()->PostTask( + FROM_HERE, + base::BindOnce(&TransceiverStateSurfacerTest:: + AsyncInitializeSurfacerWithCallbackOnSignalingThread, + base::Unretained(this), std::move(transceivers), + std::move(callback), run_loop.get())); + return run_loop; + } + + void ObtainStatesAndExpectInitialized( + rtc::scoped_refptr<webrtc::RtpTransceiverInterface> webrtc_transceiver) { + auto transceiver_states = surfacer_->ObtainStates(); + EXPECT_EQ(1u, transceiver_states.size()); + auto& transceiver_state = transceiver_states[0]; + EXPECT_EQ(transceiver_state.webrtc_transceiver().get(), + webrtc_transceiver.get()); + // Inspect sender states. + const auto& sender_state = transceiver_state.sender_state(); + EXPECT_TRUE(sender_state); + EXPECT_TRUE(sender_state->is_initialized()); + const auto& webrtc_sender = webrtc_transceiver->sender(); + EXPECT_EQ(sender_state->webrtc_sender().get(), webrtc_sender.get()); + EXPECT_TRUE(sender_state->track_ref()->is_initialized()); + EXPECT_EQ(sender_state->track_ref()->webrtc_track(), + webrtc_sender->track().get()); + EXPECT_EQ(sender_state->stream_ids(), webrtc_sender->stream_ids()); + // Inspect receiver states. + const auto& receiver_state = transceiver_state.receiver_state(); + EXPECT_TRUE(receiver_state); + EXPECT_TRUE(receiver_state->is_initialized()); + const auto& webrtc_receiver = webrtc_transceiver->receiver(); + EXPECT_EQ(receiver_state->webrtc_receiver().get(), webrtc_receiver.get()); + EXPECT_TRUE(receiver_state->track_ref()->is_initialized()); + EXPECT_EQ(receiver_state->track_ref()->webrtc_track(), + webrtc_receiver->track().get()); + std::vector<std::string> receiver_stream_ids; + for (const auto& stream : webrtc_receiver->streams()) { + receiver_stream_ids.push_back(stream->id()); + } + EXPECT_EQ(receiver_state->stream_ids(), receiver_stream_ids); + // Inspect transceiver states. + EXPECT_TRUE( + OptionalEquals(transceiver_state.mid(), webrtc_transceiver->mid())); + EXPECT_EQ(transceiver_state.stopped(), webrtc_transceiver->stopped()); + EXPECT_TRUE(transceiver_state.direction() == + webrtc_transceiver->direction()); + EXPECT_TRUE(OptionalEquals(transceiver_state.current_direction(), + webrtc_transceiver->current_direction())); + } + + private: + blink::WebMediaStreamTrack CreateBlinkLocalTrack(const std::string& id) { + blink::WebMediaStreamSource web_source; + web_source.Initialize( + blink::WebString::FromUTF8(id), blink::WebMediaStreamSource::kTypeAudio, + blink::WebString::FromUTF8("local_audio_track"), false); + MediaStreamAudioSource* audio_source = new MediaStreamAudioSource(true); + // Takes ownership of |audio_source|. + web_source.SetExtraData(audio_source); + + blink::WebMediaStreamTrack web_track; + web_track.Initialize(web_source.Id(), web_source); + audio_source->ConnectToTrack(web_track); + return web_track; + } + + void AsyncInitializeSurfacerWithWaitableEventOnSignalingThread( + std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> + transceivers, + base::WaitableEvent* waitable_event) { + DCHECK(signaling_task_runner()->BelongsToCurrentThread()); + surfacer_->Initialize(track_adapter_map_, std::move(transceivers)); + waitable_event->Signal(); + } + + void AsyncInitializeSurfacerWithCallbackOnSignalingThread( + std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> + transceivers, + base::OnceCallback<void()> callback, + base::RunLoop* run_loop) { + DCHECK(signaling_task_runner()->BelongsToCurrentThread()); + surfacer_->Initialize(track_adapter_map_, std::move(transceivers)); + main_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&TransceiverStateSurfacerTest:: + AsyncInitializeSurfacerWithCallbackOnMainThread, + base::Unretained(this), std::move(callback), run_loop)); + } + + void AsyncInitializeSurfacerWithCallbackOnMainThread( + base::OnceCallback<void()> callback, + base::RunLoop* run_loop) { + DCHECK(main_task_runner_->BelongsToCurrentThread()); + DCHECK(surfacer_->is_initialized()); + std::move(callback).Run(); + run_loop->Quit(); + } + + base::test::ScopedTaskEnvironment scoped_task_environment_; + + protected: + std::unique_ptr<MockPeerConnectionDependencyFactory> dependency_factory_; + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map_; + std::unique_ptr<TransceiverStateSurfacer> surfacer_; +}; + +TEST_F(TransceiverStateSurfacerTest, SurfaceTransceiverBlockingly) { + auto local_track_adapter = CreateLocalTrackAndAdapter("local_track"); + auto webrtc_transceiver = + CreateWebRtcTransceiver(local_track_adapter->webrtc_track(), + "local_stream", "remote_track", "remote_stream"); + auto waitable_event = + AsyncInitializeSurfacerWithWaitableEvent({webrtc_transceiver}); + waitable_event->Wait(); + ObtainStatesAndExpectInitialized(webrtc_transceiver); +} + +TEST_F(TransceiverStateSurfacerTest, SurfaceTransceiverInCallback) { + auto local_track_adapter = CreateLocalTrackAndAdapter("local_track"); + auto webrtc_transceiver = + CreateWebRtcTransceiver(local_track_adapter->webrtc_track(), + "local_stream", "remote_track", "remote_stream"); + auto run_loop = AsyncInitializeSurfacerWithCallback( + {webrtc_transceiver}, + base::BindOnce( + &TransceiverStateSurfacerTest::ObtainStatesAndExpectInitialized, + base::Unretained(this), webrtc_transceiver)); + run_loop->Run(); +} + +TEST_F(TransceiverStateSurfacerTest, SurfaceSenderStateOnly) { + auto local_track_adapter = CreateLocalTrackAndAdapter("local_track"); + auto webrtc_sender = + CreateWebRtcSender(local_track_adapter->webrtc_track(), "local_stream"); + auto waitable_event = AsyncInitializeSurfacerWithWaitableEvent( + {new SurfaceSenderStateOnly(webrtc_sender)}); + waitable_event->Wait(); + auto transceiver_states = surfacer_->ObtainStates(); + EXPECT_EQ(1u, transceiver_states.size()); + auto& transceiver_state = transceiver_states[0]; + EXPECT_TRUE(transceiver_state.sender_state()); + EXPECT_TRUE(transceiver_state.sender_state()->is_initialized()); + EXPECT_FALSE(transceiver_state.receiver_state()); + // Expect transceiver members be be missing for optional members and have + // sensible values for non-optional members. + EXPECT_FALSE(transceiver_state.mid()); + EXPECT_FALSE(transceiver_state.stopped()); + EXPECT_EQ(transceiver_state.direction(), + webrtc::RtpTransceiverDirection::kSendOnly); + EXPECT_FALSE(transceiver_state.current_direction()); +} + +TEST_F(TransceiverStateSurfacerTest, SurfaceReceiverStateOnly) { + auto local_track_adapter = CreateLocalTrackAndAdapter("local_track"); + auto webrtc_receiver = CreateWebRtcReceiver("remote_track", "remote_stream"); + auto waitable_event = AsyncInitializeSurfacerWithWaitableEvent( + {new SurfaceReceiverStateOnly(webrtc_receiver)}); + waitable_event->Wait(); + auto transceiver_states = surfacer_->ObtainStates(); + EXPECT_EQ(1u, transceiver_states.size()); + auto& transceiver_state = transceiver_states[0]; + EXPECT_FALSE(transceiver_state.sender_state()); + EXPECT_TRUE(transceiver_state.receiver_state()); + EXPECT_TRUE(transceiver_state.receiver_state()->is_initialized()); + // Expect transceiver members be be missing for optional members and have + // sensible values for non-optional members. + EXPECT_FALSE(transceiver_state.mid()); + EXPECT_FALSE(transceiver_state.stopped()); + EXPECT_EQ(transceiver_state.direction(), + webrtc::RtpTransceiverDirection::kRecvOnly); + EXPECT_FALSE(transceiver_state.current_direction()); +} + +} // namespace content diff --git a/chromium/content/renderer/media/webrtc/webrtc_audio_renderer.cc b/chromium/content/renderer/media/webrtc/webrtc_audio_renderer.cc index b18f49d21f8..c1ea561596d 100644 --- a/chromium/content/renderer/media/webrtc/webrtc_audio_renderer.cc +++ b/chromium/content/renderer/media/webrtc/webrtc_audio_renderer.cc @@ -11,10 +11,11 @@ #include "base/location.h" #include "base/logging.h" #include "base/metrics/histogram_macros.h" +#include "base/stl_util.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "build/build_config.h" -#include "content/renderer/media/audio_device_factory.h" +#include "content/renderer/media/audio/audio_device_factory.h" #include "content/renderer/media/stream/media_stream_audio_track.h" #include "content/renderer/media/webrtc/peer_connection_remote_audio_source.h" #include "content/renderer/media/webrtc_logging.h" @@ -93,8 +94,7 @@ class SharedAudioRenderer : public MediaStreamAudioRenderer { void Play() override { DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(started_); - if (playing_state_.playing()) + if (!started_ || playing_state_.playing()) return; playing_state_.set_playing(true); on_play_state_changed_.Run(media_stream_, &playing_state_); @@ -102,8 +102,7 @@ class SharedAudioRenderer : public MediaStreamAudioRenderer { void Pause() override { DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(started_); - if (!playing_state_.playing()) + if (!started_ || !playing_state_.playing()) return; playing_state_.set_playing(false); on_play_state_changed_.Run(media_stream_, &playing_state_); @@ -549,7 +548,7 @@ bool WebRtcAudioRenderer::AddPlayingState( DCHECK(state->playing()); // Look up or add the |source| to the map. PlayingStates& array = source_playing_states_[source]; - if (std::find(array.begin(), array.end(), state) != array.end()) + if (base::ContainsValue(array, state)) return false; array.push_back(state); @@ -584,8 +583,8 @@ void WebRtcAudioRenderer::OnPlayStateChanged( const blink::WebMediaStream& media_stream, PlayingState* state) { DCHECK(thread_checker_.CalledOnValidThread()); - blink::WebVector<blink::WebMediaStreamTrack> web_tracks; - media_stream.AudioTracks(web_tracks); + blink::WebVector<blink::WebMediaStreamTrack> web_tracks = + media_stream.AudioTracks(); for (const blink::WebMediaStreamTrack& web_track : web_tracks) { // WebRtcAudioRenderer can only render audio tracks received from a remote 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 7e886d27945..e3e2cce259b 100644 --- a/chromium/content/renderer/media/webrtc/webrtc_audio_renderer_unittest.cc +++ b/chromium/content/renderer/media/webrtc/webrtc_audio_renderer_unittest.cc @@ -13,7 +13,7 @@ #include "base/run_loop.h" #include "build/build_config.h" #include "content/public/renderer/media_stream_audio_renderer.h" -#include "content/renderer/media/audio_device_factory.h" +#include "content/renderer/media/audio/audio_device_factory.h" #include "content/renderer/media/webrtc/webrtc_audio_device_impl.h" #include "media/base/audio_capturer_source.h" #include "media/base/mock_audio_renderer_sink.h" diff --git a/chromium/content/renderer/media/webrtc/webrtc_audio_sink.cc b/chromium/content/renderer/media/webrtc/webrtc_audio_sink.cc index ba37c80ba94..b5a59a0e32e 100644 --- a/chromium/content/renderer/media/webrtc/webrtc_audio_sink.cc +++ b/chromium/content/renderer/media/webrtc/webrtc_audio_sink.cc @@ -27,26 +27,26 @@ WebRtcAudioSink::WebRtcAudioSink( } WebRtcAudioSink::~WebRtcAudioSink() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DVLOG(1) << "WebRtcAudioSink::~WebRtcAudioSink()"; } void WebRtcAudioSink::SetAudioProcessor( scoped_refptr<MediaStreamAudioProcessor> processor) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(processor.get()); adapter_->set_processor(std::move(processor)); } void WebRtcAudioSink::SetLevel( scoped_refptr<MediaStreamAudioLevelCalculator::Level> level) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(level.get()); adapter_->set_level(std::move(level)); } void WebRtcAudioSink::OnEnabledChanged(bool enabled) { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); adapter_->signaling_task_runner()->PostTask( FROM_HERE, base::BindOnce(base::IgnoreResult(&WebRtcAudioSink::Adapter::set_enabled), @@ -55,17 +55,14 @@ void WebRtcAudioSink::OnEnabledChanged(bool enabled) { void WebRtcAudioSink::OnData(const media::AudioBus& audio_bus, base::TimeTicks estimated_capture_time) { - DCHECK(audio_thread_checker_.CalledOnValidThread()); + // No thread check: OnData might be called on different threads (but not + // concurrently). // The following will result in zero, one, or multiple synchronous calls to // DeliverRebufferedAudio(). fifo_.Push(audio_bus); } void WebRtcAudioSink::OnSetFormat(const media::AudioParameters& params) { - // On a format change, the thread delivering audio might have also changed. - audio_thread_checker_.DetachFromThread(); - DCHECK(audio_thread_checker_.CalledOnValidThread()); - DCHECK(params.IsValid()); params_ = params; // Make sure that our params always reflect a buffer size of 10ms. @@ -78,7 +75,6 @@ void WebRtcAudioSink::OnSetFormat(const media::AudioParameters& params) { void WebRtcAudioSink::DeliverRebufferedAudio(const media::AudioBus& audio_bus, int frame_delay) { - DCHECK(audio_thread_checker_.CalledOnValidThread()); DCHECK(params_.IsValid()); // TODO(miu): Why doesn't a WebRTC sink care about reference time passed to diff --git a/chromium/content/renderer/media/webrtc/webrtc_audio_sink.h b/chromium/content/renderer/media/webrtc/webrtc_audio_sink.h index d330bcd1d2f..fee1d51f999 100644 --- a/chromium/content/renderer/media/webrtc/webrtc_audio_sink.h +++ b/chromium/content/renderer/media/webrtc/webrtc_audio_sink.h @@ -8,6 +8,8 @@ #include <stdint.h> #include <memory> +#include <string> +#include <utility> #include <vector> #include "base/macros.h" @@ -166,11 +168,7 @@ class CONTENT_EXPORT WebRtcAudioSink : public MediaStreamAudioSink { // In debug builds, check that WebRtcAudioSink's public methods are all being // called on the main render thread. - base::ThreadChecker thread_checker_; - - // Used to DCHECK that OnSetFormat() and OnData() are called on the same - // thread. - base::ThreadChecker audio_thread_checker_; + THREAD_CHECKER(thread_checker_); DISALLOW_COPY_AND_ASSIGN(WebRtcAudioSink); }; diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.cc b/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.cc deleted file mode 100644 index 835d6194e24..00000000000 --- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.cc +++ /dev/null @@ -1,292 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/media/webrtc/webrtc_media_stream_adapter.h" - -#include <utility> - -#include "base/logging.h" -#include "base/memory/ref_counted.h" -#include "base/threading/thread_task_runner_handle.h" -#include "content/renderer/media/stream/media_stream_audio_track.h" -#include "content/renderer/media/webrtc/peer_connection_dependency_factory.h" -#include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter.h" -#include "third_party/blink/public/platform/web_media_stream_source.h" -#include "third_party/blink/public/platform/web_media_stream_track.h" - -namespace content { - -// static -std::unique_ptr<WebRtcMediaStreamAdapter> -WebRtcMediaStreamAdapter::CreateLocalStreamAdapter( - PeerConnectionDependencyFactory* factory, - scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, - const blink::WebMediaStream& web_stream) { - return std::make_unique<LocalWebRtcMediaStreamAdapter>( - factory, std::move(track_adapter_map), web_stream); -} - -// static -std::unique_ptr<WebRtcMediaStreamAdapter> -WebRtcMediaStreamAdapter::CreateRemoteStreamAdapter( - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, - scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream) { - return std::make_unique<RemoteWebRtcMediaStreamAdapter>( - std::move(main_thread), std::move(track_adapter_map), - std::move(webrtc_stream)); -} - -WebRtcMediaStreamAdapter::WebRtcMediaStreamAdapter( - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, - scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream, - const blink::WebMediaStream& web_stream) - : main_thread_(std::move(main_thread)), - track_adapter_map_(std::move(track_adapter_map)), - webrtc_stream_(std::move(webrtc_stream)), - web_stream_(web_stream) { - DCHECK(main_thread_); - DCHECK(track_adapter_map_); -} - -WebRtcMediaStreamAdapter::~WebRtcMediaStreamAdapter() { - DCHECK(main_thread_->BelongsToCurrentThread()); -} - -LocalWebRtcMediaStreamAdapter::LocalWebRtcMediaStreamAdapter( - PeerConnectionDependencyFactory* factory, - scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, - const blink::WebMediaStream& web_stream) - : WebRtcMediaStreamAdapter(base::ThreadTaskRunnerHandle::Get(), - std::move(track_adapter_map), - nullptr, - web_stream), - factory_(factory) { - webrtc_stream_ = factory_->CreateLocalMediaStream(web_stream.Id().Utf8()); - - blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; - web_stream_.AudioTracks(audio_tracks); - for (blink::WebMediaStreamTrack& audio_track : audio_tracks) - TrackAdded(audio_track); - - blink::WebVector<blink::WebMediaStreamTrack> video_tracks; - web_stream_.VideoTracks(video_tracks); - for (blink::WebMediaStreamTrack& video_track : video_tracks) - TrackAdded(video_track); - - web_stream_.AddObserver(this); -} - -LocalWebRtcMediaStreamAdapter::~LocalWebRtcMediaStreamAdapter() { - DCHECK(main_thread_->BelongsToCurrentThread()); - web_stream_.RemoveObserver(this); - - blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; - web_stream_.AudioTracks(audio_tracks); - for (blink::WebMediaStreamTrack& audio_track : audio_tracks) - TrackRemoved(audio_track); - - blink::WebVector<blink::WebMediaStreamTrack> video_tracks; - web_stream_.VideoTracks(video_tracks); - for (blink::WebMediaStreamTrack& video_track : video_tracks) - TrackRemoved(video_track); -} - -bool LocalWebRtcMediaStreamAdapter::is_initialized() const { - return true; -} - -const scoped_refptr<webrtc::MediaStreamInterface>& -LocalWebRtcMediaStreamAdapter::webrtc_stream() const { - return webrtc_stream_; -} - -const blink::WebMediaStream& LocalWebRtcMediaStreamAdapter::web_stream() const { - return web_stream_; -} - -void LocalWebRtcMediaStreamAdapter::SetTracks( - WebRtcMediaStreamAdapter::TrackAdapterRefs track_refs) { - NOTIMPLEMENTED() << "Not supported for local stream adapters."; -} - -void LocalWebRtcMediaStreamAdapter::TrackAdded( - const blink::WebMediaStreamTrack& web_track) { - DCHECK(adapter_refs_.find(web_track.UniqueId()) == adapter_refs_.end()); - bool is_audio_track = - (web_track.Source().GetType() == blink::WebMediaStreamSource::kTypeAudio); - if (is_audio_track && !MediaStreamAudioTrack::From(web_track)) { - DLOG(ERROR) << "No native track for blink audio track."; - return; - } - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> adapter_ref = - track_adapter_map_->GetOrCreateLocalTrackAdapter(web_track); - if (is_audio_track) { - webrtc_stream_->AddTrack( - static_cast<webrtc::AudioTrackInterface*>(adapter_ref->webrtc_track())); - } else { - webrtc_stream_->AddTrack( - static_cast<webrtc::VideoTrackInterface*>(adapter_ref->webrtc_track())); - } - adapter_refs_.insert( - std::make_pair(web_track.UniqueId(), std::move(adapter_ref))); -} - -void LocalWebRtcMediaStreamAdapter::TrackRemoved( - const blink::WebMediaStreamTrack& web_track) { - auto it = adapter_refs_.find(web_track.UniqueId()); - if (it == adapter_refs_.end()) { - // This can happen for audio tracks that don't have a source, these would - // never be added in the first place. - return; - } - if (web_track.Source().GetType() == blink::WebMediaStreamSource::kTypeAudio) { - webrtc_stream_->RemoveTrack( - static_cast<webrtc::AudioTrackInterface*>(it->second->webrtc_track())); - } else { - webrtc_stream_->RemoveTrack( - static_cast<webrtc::VideoTrackInterface*>(it->second->webrtc_track())); - } - adapter_refs_.erase(it); -} - -// static -bool RemoteWebRtcMediaStreamAdapter::RemoteAdapterRefsContainsTrack( - const RemoteAdapterRefs& adapter_refs, - webrtc::MediaStreamTrackInterface* webrtc_track) { - for (const auto& adapter_ref : adapter_refs) { - if (adapter_ref->webrtc_track() == webrtc_track) - return true; - } - return false; -} - -// static -RemoteWebRtcMediaStreamAdapter::RemoteAdapterRefs -RemoteWebRtcMediaStreamAdapter::GetRemoteAdapterRefsFromWebRtcStream( - const scoped_refptr<WebRtcMediaStreamTrackAdapterMap>& track_adapter_map, - webrtc::MediaStreamInterface* webrtc_stream) { - // TODO(hbos): When adapter's |webrtc_track| can be called from any thread so - // can RemoteAdapterRefsContainsTrack and we can DCHECK here that we don't end - // up with duplicate entries. https://crbug.com/756436 - RemoteAdapterRefs adapter_refs; - for (auto& webrtc_audio_track : webrtc_stream->GetAudioTracks()) { - adapter_refs.push_back(track_adapter_map->GetOrCreateRemoteTrackAdapter( - webrtc_audio_track.get())); - } - for (auto& webrtc_video_track : webrtc_stream->GetVideoTracks()) { - adapter_refs.push_back(track_adapter_map->GetOrCreateRemoteTrackAdapter( - webrtc_video_track.get())); - } - return adapter_refs; -} - -RemoteWebRtcMediaStreamAdapter::RemoteWebRtcMediaStreamAdapter( - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, - scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream) - : WebRtcMediaStreamAdapter(std::move(main_thread), - std::move(track_adapter_map), - std::move(webrtc_stream), - // "null" |WebMediaStream| - blink::WebMediaStream()), - is_initialized_(false), - weak_factory_(this) { - CHECK(!main_thread_->BelongsToCurrentThread()); - CHECK(track_adapter_map_); - - RemoteAdapterRefs adapter_refs = GetRemoteAdapterRefsFromWebRtcStream( - track_adapter_map_, webrtc_stream_.get()); - main_thread_->PostTask( - FROM_HERE, - base::BindOnce(&RemoteWebRtcMediaStreamAdapter::InitializeOnMainThread, - weak_factory_.GetWeakPtr(), webrtc_stream_->id(), - std::move(adapter_refs), - webrtc_stream_->GetAudioTracks().size(), - webrtc_stream_->GetVideoTracks().size())); -} - -RemoteWebRtcMediaStreamAdapter::~RemoteWebRtcMediaStreamAdapter() { - DCHECK(main_thread_->BelongsToCurrentThread()); - SetTracks(RemoteAdapterRefs()); -} - -bool RemoteWebRtcMediaStreamAdapter::is_initialized() const { - base::AutoLock scoped_lock(lock_); - return is_initialized_; -} - -const scoped_refptr<webrtc::MediaStreamInterface>& -RemoteWebRtcMediaStreamAdapter::webrtc_stream() const { - base::AutoLock scoped_lock(lock_); - DCHECK(is_initialized_); - return webrtc_stream_; -} - -const blink::WebMediaStream& RemoteWebRtcMediaStreamAdapter::web_stream() - const { - base::AutoLock scoped_lock(lock_); - DCHECK(is_initialized_); - return web_stream_; -} - -void RemoteWebRtcMediaStreamAdapter::InitializeOnMainThread( - const std::string& label, - RemoteAdapterRefs adapter_refs, - size_t audio_track_count, - size_t video_track_count) { - CHECK(main_thread_->BelongsToCurrentThread()); - CHECK_EQ(audio_track_count + video_track_count, adapter_refs.size()); - - adapter_refs_ = std::move(adapter_refs); - blink::WebVector<blink::WebMediaStreamTrack> web_audio_tracks( - audio_track_count); - blink::WebVector<blink::WebMediaStreamTrack> web_video_tracks( - video_track_count); - size_t audio_i = 0; - size_t video_i = 0; - for (const auto& adapter_ref : adapter_refs_) { - const blink::WebMediaStreamTrack& web_track = adapter_ref->web_track(); - if (web_track.Source().GetType() == blink::WebMediaStreamSource::kTypeAudio) - web_audio_tracks[audio_i++] = web_track; - else - web_video_tracks[video_i++] = web_track; - } - - web_stream_.Initialize(blink::WebString::FromUTF8(label), web_audio_tracks, - web_video_tracks); - CHECK(!web_stream_.IsNull()); - - base::AutoLock scoped_lock(lock_); - is_initialized_ = true; -} - -void RemoteWebRtcMediaStreamAdapter::SetTracks( - WebRtcMediaStreamAdapter::TrackAdapterRefs track_refs) { - DCHECK(main_thread_->BelongsToCurrentThread()); - - // Find removed tracks. - base::EraseIf( - adapter_refs_, - [this, &track_refs]( - const std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>& - track_ref) { - bool erase = !RemoteAdapterRefsContainsTrack(track_refs, - track_ref->webrtc_track()); - if (erase) - web_stream_.RemoveTrack(track_ref->web_track()); - return erase; - }); - // Find added tracks. - for (auto& track_ref : track_refs) { - if (!RemoteAdapterRefsContainsTrack(adapter_refs_, - track_ref->webrtc_track())) { - web_stream_.AddTrack(track_ref->web_track()); - adapter_refs_.push_back(std::move(track_ref)); - } - } -} - -} // namespace content diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.h b/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.h deleted file mode 100644 index 49c6388ec5a..00000000000 --- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.h +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_MEDIA_STREAM_ADAPTER_H_ -#define CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_MEDIA_STREAM_ADAPTER_H_ - -#include <map> -#include <memory> -#include <string> - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "base/sequenced_task_runner.h" -#include "base/single_thread_task_runner.h" -#include "base/synchronization/lock.h" -#include "content/common/content_export.h" -#include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h" -#include "third_party/blink/public/platform/web_media_stream.h" -#include "third_party/webrtc/api/mediastreaminterface.h" - -namespace content { - -class PeerConnectionDependencyFactory; - -// An adapter is the glue between webrtc and blink media streams. Adapters of -// local media streams are created from a blink stream and get a webrtc stream -// correspondent. Adapters of remote media streams are created from a webrtc -// stream and get a blink stream correspondent. The adapter makes sure that when -// the stream it was created from is modified the correspondent is updated to -// reflect the new state. -// The adapters are thread safe but must be constructed on the correct thread -// (local adapters: main thread, remote adapters: webrtc signaling thread) and -// destroyed on the main thread. -class CONTENT_EXPORT WebRtcMediaStreamAdapter { - public: - using TrackAdapterRefs = std::vector< - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>>; - - // Creates an adapter for a local media stream. The adapter is already - // initialized. Invoked on the main thread. - static std::unique_ptr<WebRtcMediaStreamAdapter> CreateLocalStreamAdapter( - PeerConnectionDependencyFactory* factory, - scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, - const blink::WebMediaStream& web_stream); - // Creates an adapter for a remote media stream. Invoked on the webrtc - // signaling thread. The adapter is initialized in a post to the main thread. - static std::unique_ptr<WebRtcMediaStreamAdapter> CreateRemoteStreamAdapter( - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, - scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream); - // Invoke on the main thread. - virtual ~WebRtcMediaStreamAdapter(); - - // Once initialized, |webrtc_stream| and |web_stream| are accessible. An - // initialized adapter remains initialized until destroyed. - virtual bool is_initialized() const = 0; - virtual const scoped_refptr<webrtc::MediaStreamInterface>& webrtc_stream() - const = 0; - virtual const blink::WebMediaStream& web_stream() const = 0; - bool IsEqual(const blink::WebMediaStream& stream) const { - return (web_stream_.IsNull() && stream.IsNull()) || - (web_stream_.Id() == stream.Id()); - } - - virtual void SetTracks(TrackAdapterRefs track_refs) = 0; - - protected: - WebRtcMediaStreamAdapter( - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, - scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream, - const blink::WebMediaStream& web_stream); - - scoped_refptr<base::SingleThreadTaskRunner> main_thread_; - // The map and owner of all track adapters for the associated peer connection. - // When a track is added or removed from this stream, the map provides us with - // a reference to the corresponding track adapter, creating a new one if - // necessary. - scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map_; - - // If |is_initialized()| both of these need to be set and remain constant. - scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream_; - blink::WebMediaStream web_stream_; - - DISALLOW_COPY_AND_ASSIGN(WebRtcMediaStreamAdapter); -}; - -// Adapter implementation for a local |blink::WebMediaStream|. Created and -// destroyed on the main thread. -class LocalWebRtcMediaStreamAdapter : public WebRtcMediaStreamAdapter, - blink::WebMediaStreamObserver { - public: - LocalWebRtcMediaStreamAdapter( - PeerConnectionDependencyFactory* factory, - scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, - const blink::WebMediaStream& web_stream); - ~LocalWebRtcMediaStreamAdapter() override; - - // |WebRtcMediaStreamAdapter| implementation. - bool is_initialized() const override; - const scoped_refptr<webrtc::MediaStreamInterface>& webrtc_stream() - const override; - const blink::WebMediaStream& web_stream() const override; - void SetTracks(TrackAdapterRefs track_refs) override; - - private: - // A map between web track UniqueIDs and references to track adapters. - using LocalAdapterRefMap = - std::map<int, // blink::WebMediaStreamTrack::UniqueId() - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef>>; - - // |MediaStreamObserver| implementation. Also used as a helper functions when - // adding/removing all tracks in the constructor/destructor. - void TrackAdded(const blink::WebMediaStreamTrack& web_track) override; - void TrackRemoved(const blink::WebMediaStreamTrack& web_track) override; - - // Pointer to a |PeerConnectionDependencyFactory|, owned by the - // |RenderThread|. It's valid for the lifetime of |RenderThread|. - PeerConnectionDependencyFactory* const factory_; - - // Track adapters belonging to this stream. Keeping adapter references alive - // ensures the adapters are not disposed by the |track_adapter_map_| as long - // as the webrtc layer track is in use by the webrtc layer stream. - LocalAdapterRefMap adapter_refs_; - - DISALLOW_COPY_AND_ASSIGN(LocalWebRtcMediaStreamAdapter); -}; - -// Adapter implementation for a remote |webrtc::MediaStreamInterface|. Created -// on the the webrtc signaling thread, initialized on the main thread where it -// must be destroyed. -class RemoteWebRtcMediaStreamAdapter : public WebRtcMediaStreamAdapter { - public: - RemoteWebRtcMediaStreamAdapter( - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, - scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream); - ~RemoteWebRtcMediaStreamAdapter() override; - - // |WebRtcMediaStreamAdapter| implementation. - bool is_initialized() const override; - const scoped_refptr<webrtc::MediaStreamInterface>& webrtc_stream() - const override; - const blink::WebMediaStream& web_stream() const override; - void SetTracks(TrackAdapterRefs track_refs) override; - - private: - // Track adapters for the remote webrtc tracks of a stream. - using RemoteAdapterRefs = WebRtcMediaStreamAdapter::TrackAdapterRefs; - - static bool RemoteAdapterRefsContainsTrack( - const RemoteAdapterRefs& adapter_refs, - webrtc::MediaStreamTrackInterface* track); - - // Gets the adapters for the tracks that are members of the webrtc stream. - // Invoke on webrtc signaling thread. New adapters are initialized in a post - // to the main thread after which their |web_track| becomes available. - static RemoteAdapterRefs GetRemoteAdapterRefsFromWebRtcStream( - const scoped_refptr<WebRtcMediaStreamTrackAdapterMap>& track_adapter_map, - webrtc::MediaStreamInterface* webrtc_stream); - - void InitializeOnMainThread(const std::string& label, - RemoteAdapterRefs track_adapter_refs, - size_t audio_track_count, - size_t video_track_count); - - mutable base::Lock lock_; - bool is_initialized_; - // Track adapters belonging to this stream. Keeping adapter references alive - // ensures the adapters are not disposed by the |track_adapter_map_| as long - // as the webrtc layer track is in use by the webrtc layer stream. - RemoteAdapterRefs adapter_refs_; - base::WeakPtrFactory<RemoteWebRtcMediaStreamAdapter> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(RemoteWebRtcMediaStreamAdapter); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_MEDIA_STREAM_ADAPTER_H_ diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_map.cc b/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_map.cc deleted file mode 100644 index b445ce8c893..00000000000 --- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_map.cc +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright (c) 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/media/webrtc/webrtc_media_stream_adapter_map.h" - -namespace content { - -WebRtcMediaStreamAdapterMap::AdapterEntry::AdapterEntry( - std::unique_ptr<WebRtcMediaStreamAdapter> adapter) - : adapter(std::move(adapter)), ref_count(0) { - DCHECK(this->adapter); -} - -WebRtcMediaStreamAdapterMap::AdapterEntry::AdapterEntry(AdapterEntry&& other) - : adapter(other.adapter.release()), ref_count(other.ref_count) {} - -WebRtcMediaStreamAdapterMap::AdapterEntry::~AdapterEntry() { - // |ref_count| is allowed to be non-zero only if this entry has been moved - // which is the case if the |adapter| has already been released. - DCHECK(!ref_count || !adapter); -} - -WebRtcMediaStreamAdapterMap::AdapterRef::AdapterRef( - scoped_refptr<WebRtcMediaStreamAdapterMap> map, - Type type, - AdapterEntry* adapter_entry) - : map_(std::move(map)), type_(type), adapter_entry_(adapter_entry) { - DCHECK(map_); - DCHECK(adapter_entry_); - map_->lock_.AssertAcquired(); - ++adapter_entry_->ref_count; -} - -WebRtcMediaStreamAdapterMap::AdapterRef::~AdapterRef() { - DCHECK(map_->main_thread_->BelongsToCurrentThread()); - std::unique_ptr<WebRtcMediaStreamAdapter> removed_adapter; - { - base::AutoLock scoped_lock(map_->lock_); - --adapter_entry_->ref_count; - if (adapter_entry_->ref_count == 0) { - removed_adapter = std::move(adapter_entry_->adapter); - // "GetOrCreate..." ensures the adapter is initialized and the secondary - // key is set before the last |AdapterRef| is destroyed. We can use either - // the primary or secondary key for removal. - if (type_ == Type::kLocal) { - map_->local_stream_adapters_.EraseByPrimary( - removed_adapter->web_stream().UniqueId()); - } else { - map_->remote_stream_adapters_.EraseByPrimary( - removed_adapter->webrtc_stream().get()); - } - } - } - // Destroy the adapter whilst not holding the lock so that it is safe for - // destructors to use the signaling thread synchronously without any risk of - // deadlock. - removed_adapter.reset(); -} - -std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> -WebRtcMediaStreamAdapterMap::AdapterRef::Copy() const { - base::AutoLock scoped_lock(map_->lock_); - return base::WrapUnique(new AdapterRef(map_, type_, adapter_entry_)); -} - -WebRtcMediaStreamAdapterMap::WebRtcMediaStreamAdapterMap( - PeerConnectionDependencyFactory* const factory, - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map) - : factory_(factory), - main_thread_(std::move(main_thread)), - track_adapter_map_(std::move(track_adapter_map)) { - DCHECK(factory_); - DCHECK(main_thread_); - DCHECK(track_adapter_map_); -} - -WebRtcMediaStreamAdapterMap::~WebRtcMediaStreamAdapterMap() { - DCHECK(local_stream_adapters_.empty()); - DCHECK(remote_stream_adapters_.empty()); -} - -std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> -WebRtcMediaStreamAdapterMap::GetLocalStreamAdapter( - const blink::WebMediaStream& web_stream) { - base::AutoLock scoped_lock(lock_); - AdapterEntry* adapter_entry = - local_stream_adapters_.FindByPrimary(web_stream.UniqueId()); - if (!adapter_entry) - return nullptr; - return base::WrapUnique( - new AdapterRef(this, AdapterRef::Type::kLocal, adapter_entry)); -} - -std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> -WebRtcMediaStreamAdapterMap::GetLocalStreamAdapter( - webrtc::MediaStreamInterface* webrtc_stream) { - base::AutoLock scoped_lock(lock_); - AdapterEntry* adapter_entry = - local_stream_adapters_.FindBySecondary(webrtc_stream); - if (!adapter_entry) - return nullptr; - return base::WrapUnique( - new AdapterRef(this, AdapterRef::Type::kLocal, adapter_entry)); -} - -std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> -WebRtcMediaStreamAdapterMap::GetOrCreateLocalStreamAdapter( - const blink::WebMediaStream& web_stream) { - CHECK(main_thread_->BelongsToCurrentThread()); - CHECK(!web_stream.IsNull()); - base::AutoLock scoped_lock(lock_); - AdapterEntry* adapter_entry = - local_stream_adapters_.FindByPrimary(web_stream.UniqueId()); - if (!adapter_entry) { - std::unique_ptr<WebRtcMediaStreamAdapter> adapter; - { - // Make sure we don't hold the lock while calling out to - // CreateLocalStreamAdapter(). The reason is that constructing a local - // stream adapter, will synchronize with WebRTC's signaling thread and - // callbacks on the signaling thread might end up coming back to us - // and we might need the lock then. - base::AutoUnlock scoped_unlock(lock_); - adapter = WebRtcMediaStreamAdapter::CreateLocalStreamAdapter( - factory_, track_adapter_map_, web_stream); - } - - adapter_entry = local_stream_adapters_.Insert(web_stream.UniqueId(), - std::move(adapter)); - CHECK(adapter_entry->adapter->is_initialized()); - CHECK(adapter_entry->adapter->webrtc_stream()); - local_stream_adapters_.SetSecondaryKey( - web_stream.UniqueId(), adapter_entry->adapter->webrtc_stream().get()); - } - return base::WrapUnique( - new AdapterRef(this, AdapterRef::Type::kLocal, adapter_entry)); -} - -size_t WebRtcMediaStreamAdapterMap::GetLocalStreamCount() const { - base::AutoLock scoped_lock(lock_); - return local_stream_adapters_.PrimarySize(); -} - -std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> -WebRtcMediaStreamAdapterMap::GetRemoteStreamAdapter( - const blink::WebMediaStream& web_stream) { - base::AutoLock scoped_lock(lock_); - AdapterEntry* adapter_entry = - remote_stream_adapters_.FindBySecondary(web_stream.UniqueId()); - if (!adapter_entry) - return nullptr; - return base::WrapUnique( - new AdapterRef(this, AdapterRef::Type::kRemote, adapter_entry)); -} - -std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> -WebRtcMediaStreamAdapterMap::GetRemoteStreamAdapter( - webrtc::MediaStreamInterface* webrtc_stream) { - base::AutoLock scoped_lock(lock_); - AdapterEntry* adapter_entry = - remote_stream_adapters_.FindByPrimary(webrtc_stream); - if (!adapter_entry) - return nullptr; - return base::WrapUnique( - new AdapterRef(this, AdapterRef::Type::kRemote, adapter_entry)); -} - -std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> -WebRtcMediaStreamAdapterMap::GetOrCreateRemoteStreamAdapter( - scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream) { - CHECK(!main_thread_->BelongsToCurrentThread()); - CHECK(webrtc_stream); - base::AutoLock scoped_lock(lock_); - AdapterEntry* adapter_entry = - remote_stream_adapters_.FindByPrimary(webrtc_stream.get()); - if (!adapter_entry) { - // Make sure we don't hold the lock while calling out to - // CreateRemoteStreamAdapter(). The reason is that it might synchronize - // with other threads, possibly the main thread, where we might need to grab - // the lock (e.g. inside of GetOrCreateLocalStreamAdapter()). - std::unique_ptr<WebRtcMediaStreamAdapter> adapter; - { - base::AutoUnlock scoped_unlock(lock_); - adapter = WebRtcMediaStreamAdapter::CreateRemoteStreamAdapter( - main_thread_, track_adapter_map_, webrtc_stream.get()); - } - - adapter_entry = - remote_stream_adapters_.Insert(webrtc_stream.get(), std::move(adapter)); - - // The new adapter is initialized in a post to the main thread. As soon as - // it is initialized we map its |webrtc_stream| to the - // |remote_stream_adapters_| entry as its secondary key. This ensures that - // there is at least one |AdapterRef| alive until after the adapter is - // initialized and its secondary key is set. - main_thread_->PostTask( - FROM_HERE, - base::BindOnce( - &WebRtcMediaStreamAdapterMap::OnRemoteStreamAdapterInitialized, - this, - base::WrapUnique(new AdapterRef(this, AdapterRef::Type::kRemote, - adapter_entry)))); - } - return base::WrapUnique( - new AdapterRef(this, AdapterRef::Type::kRemote, adapter_entry)); -} - -size_t WebRtcMediaStreamAdapterMap::GetRemoteStreamCount() const { - base::AutoLock scoped_lock(lock_); - return remote_stream_adapters_.PrimarySize(); -} - -void WebRtcMediaStreamAdapterMap::OnRemoteStreamAdapterInitialized( - std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> adapter_ref) { - CHECK(main_thread_->BelongsToCurrentThread()); - CHECK(adapter_ref->is_initialized()); - CHECK(!adapter_ref->adapter().web_stream().IsNull()); - { - base::AutoLock scoped_lock(lock_); - remote_stream_adapters_.SetSecondaryKey( - adapter_ref->adapter().webrtc_stream().get(), - adapter_ref->adapter().web_stream().UniqueId()); - } -} - -} // namespace content diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_map.h b/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_map.h deleted file mode 100644 index 1d9c40b6692..00000000000 --- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_map.h +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright (c) 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_MEDIA_STREAM_ADAPTER_MAP_H_ -#define CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_MEDIA_STREAM_ADAPTER_MAP_H_ - -#include <map> -#include <memory> - -#include "base/memory/ref_counted.h" -#include "base/single_thread_task_runner.h" -#include "base/synchronization/lock.h" -#include "content/common/content_export.h" -#include "content/renderer/media/webrtc/two_keys_adapter_map.h" -#include "content/renderer/media/webrtc/webrtc_media_stream_adapter.h" -#include "third_party/blink/public/platform/web_media_stream.h" -#include "third_party/webrtc/api/mediastreaminterface.h" - -namespace content { - -// A map and owner of |WebRtcMediaStreamAdapter|s. Adapters are the glue between -// blink and webrtc layer versions of streams. As long as a stream is in use by -// a peer connection there has to exist an adapter for it. The map takes care of -// creating and disposing stream adapters. Adapters are accessed via -// |AdapterRef|s, when all references to an adapter are destroyed it is -// destroyed and removed from the map. -class CONTENT_EXPORT WebRtcMediaStreamAdapterMap - : public base::RefCountedThreadSafe<WebRtcMediaStreamAdapterMap> { - private: - // The map's entries are reference counted in order to remove the adapter when - // all |AdapterRef|s referencing an entry are destroyed. - // Private section needed here due to |AdapterRef|'s usage of |AdapterEntry|. - struct AdapterEntry { - AdapterEntry(std::unique_ptr<WebRtcMediaStreamAdapter> adapter); - AdapterEntry(AdapterEntry&& other); - ~AdapterEntry(); - - AdapterEntry(const AdapterEntry&) = delete; - AdapterEntry& operator=(const AdapterEntry&) = delete; - - std::unique_ptr<WebRtcMediaStreamAdapter> adapter; - size_t ref_count; - }; - - public: - // Accessor to an adapter to take care of reference counting. When the last - // |AdapterRef| is destroyed, the corresponding adapter is destroyed and - // removed from the map. - class CONTENT_EXPORT AdapterRef { - public: - // Must be invoked on the main thread. If this was the last reference to the - // adapter it will be disposed and removed from the map. - ~AdapterRef(); - - std::unique_ptr<AdapterRef> Copy() const; - bool is_initialized() const { return adapter().is_initialized(); } - const WebRtcMediaStreamAdapter& adapter() const { - return *adapter_entry_->adapter; - } - WebRtcMediaStreamAdapter& adapter() { return *adapter_entry_->adapter; } - - private: - friend class WebRtcMediaStreamAdapterMap; - - enum class Type { kLocal, kRemote }; - - // Increments the |AdapterEntry::ref_count|. Assumes map's |lock_| is held. - AdapterRef(scoped_refptr<WebRtcMediaStreamAdapterMap> map, - Type type, - AdapterEntry* adapter_entry); - - scoped_refptr<WebRtcMediaStreamAdapterMap> map_; - Type type_; - AdapterEntry* adapter_entry_; - }; - - // Must be invoked on the main thread. - WebRtcMediaStreamAdapterMap( - PeerConnectionDependencyFactory* const factory, - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map); - - // Gets a new reference to the local stream adapter, or null if no such - // adapter was found. When all references are destroyed the adapter is - // destroyed and removed from the map. This can be called on any thread, but - // references must be destroyed on the main thread. - // The adapter is a associated with a blink and webrtc stream, lookup works by - // either stream. - std::unique_ptr<AdapterRef> GetLocalStreamAdapter( - const blink::WebMediaStream& web_stream); - std::unique_ptr<AdapterRef> GetLocalStreamAdapter( - webrtc::MediaStreamInterface* webrtc_stream); - // Invoke on the main thread. Gets a new reference to the local stream adapter - // for the web stream. If no adapter exists for the stream one is created. - // When all references are destroyed the adapter is destroyed and removed from - // the map. References must be destroyed on the main thread. - std::unique_ptr<AdapterRef> GetOrCreateLocalStreamAdapter( - const blink::WebMediaStream& web_stream); - size_t GetLocalStreamCount() const; - - // Gets a new reference to the remote stream adapter by ID, or null if no such - // adapter was found. When all references are destroyed the adapter is - // destroyed and removed from the map. This can be called on any thread, but - // references must be destroyed on the main thread. The adapter is a - // associated with a blink and webrtc stream, lookup works by either stream. - // First variety: If an adapter exists it will already be initialized, if one - // does not exist null is returned. - std::unique_ptr<AdapterRef> GetRemoteStreamAdapter( - const blink::WebMediaStream& web_stream); - // Second variety: If an adapter exists it may or may not be initialized, see - // |AdapterRef::is_initialized|. If an adapter does not exist null is - // returned. - std::unique_ptr<AdapterRef> GetRemoteStreamAdapter( - webrtc::MediaStreamInterface* webrtc_stream); - // Invoke on the webrtc signaling thread. Gets a new reference to the remote - // stream adapter for the webrtc stream. If no adapter exists for the stream - // one is created and initialization completes on the main thread in a post. - // When all references are destroyed the adapter is destroyed and removed from - // the map. References must be destroyed on the main thread. - std::unique_ptr<AdapterRef> GetOrCreateRemoteStreamAdapter( - scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream); - size_t GetRemoteStreamCount() const; - - const scoped_refptr<WebRtcMediaStreamTrackAdapterMap>& track_adapter_map() - const { - return track_adapter_map_; - } - - private: - friend class base::RefCountedThreadSafe<WebRtcMediaStreamAdapterMap>; - - // "(blink::WebMediaStream, webrtc::MediaStreamInterface) -> AdapterEntry" - // maps. The primary key is based on the object used to create the adapter. - // Local streams are created from |blink::WebMediaStream|s, remote streams are - // created from |webrtc::MediaStreamInterface|s. - // The adapter keeps the |webrtc::MediaStreamInterface| alive with ref - // counting making it safe to use a raw pointer for key. - using LocalStreamAdapterMap = - TwoKeysAdapterMap<int, // blink::WebMediaStream::UniqueId() - webrtc::MediaStreamInterface*, - AdapterEntry>; - using RemoteStreamAdapterMap = - TwoKeysAdapterMap<webrtc::MediaStreamInterface*, - int, // blink::WebMediaStream::UniqueId() - AdapterEntry>; - - // Invoke on the main thread. - virtual ~WebRtcMediaStreamAdapterMap(); - - void OnRemoteStreamAdapterInitialized( - std::unique_ptr<AdapterRef> adapter_ref); - - // Pointer to a |PeerConnectionDependencyFactory| owned by the |RenderThread|. - // It's valid for the lifetime of |RenderThread|. - PeerConnectionDependencyFactory* const factory_; - const scoped_refptr<base::SingleThreadTaskRunner> main_thread_; - // Takes care of creating and owning track adapters, used by stream adapters. - const scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map_; - - mutable base::Lock lock_; - LocalStreamAdapterMap local_stream_adapters_; - RemoteStreamAdapterMap remote_stream_adapters_; -}; - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_MEDIA_STREAM_ADAPTER_MAP_H_ diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_map_unittest.cc b/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_map_unittest.cc deleted file mode 100644 index 87f0032a8bd..00000000000 --- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_map_unittest.cc +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright (c) 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/media/webrtc/webrtc_media_stream_adapter_map.h" - -#include <memory> -#include <string> - -#include "base/memory/ref_counted.h" -#include "base/run_loop.h" -#include "base/single_thread_task_runner.h" -#include "base/strings/string_number_conversions.h" -#include "base/synchronization/waitable_event.h" -#include "base/test/scoped_task_environment.h" -#include "content/child/child_process.h" -#include "content/renderer/media/mock_audio_device_factory.h" -#include "content/renderer/media/stream/media_stream_video_source.h" -#include "content/renderer/media/stream/media_stream_video_track.h" -#include "content/renderer/media/stream/mock_media_stream_video_source.h" -#include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h" -#include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" -#include "third_party/blink/public/platform/web_media_stream.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_string.h" -#include "third_party/blink/public/platform/web_vector.h" -#include "third_party/blink/public/web/web_heap.h" - -using ::testing::_; - -namespace content { - -class WebRtcMediaStreamAdapterMapTest : public ::testing::Test { - public: - void SetUp() override { - dependency_factory_.reset(new MockPeerConnectionDependencyFactory()); - main_thread_ = blink::scheduler::GetSingleThreadTaskRunnerForTesting(); - map_ = new WebRtcMediaStreamAdapterMap( - dependency_factory_.get(), main_thread_, - new WebRtcMediaStreamTrackAdapterMap(dependency_factory_.get(), - main_thread_)); - } - - void TearDown() override { blink::WebHeap::CollectAllGarbageForTesting(); } - - blink::WebMediaStream CreateLocalStream(const std::string& id) { - blink::WebVector<blink::WebMediaStreamTrack> web_video_tracks( - static_cast<size_t>(1)); - blink::WebMediaStreamSource video_source; - video_source.Initialize("video_source", - blink::WebMediaStreamSource::kTypeVideo, - "video_source", false /* remote */); - MediaStreamVideoSource* native_source = new MockMediaStreamVideoSource(); - video_source.SetExtraData(native_source); - web_video_tracks[0] = MediaStreamVideoTrack::CreateVideoTrack( - native_source, MediaStreamVideoSource::ConstraintsCallback(), true); - - blink::WebMediaStream web_stream; - web_stream.Initialize(blink::WebString::FromUTF8(id), - blink::WebVector<blink::WebMediaStreamTrack>(), - web_video_tracks); - return web_stream; - } - - scoped_refptr<webrtc::MediaStreamInterface> CreateRemoteStream( - const std::string& id) { - scoped_refptr<webrtc::MediaStreamInterface> stream( - new rtc::RefCountedObject<MockMediaStream>(id)); - stream->AddTrack(MockWebRtcAudioTrack::Create("remote_audio_track").get()); - stream->AddTrack(MockWebRtcVideoTrack::Create("remote_video_track").get()); - return stream; - } - - std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> - GetOrCreateRemoteStreamAdapter(webrtc::MediaStreamInterface* webrtc_stream) { - std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> adapter_ref; - dependency_factory_->GetWebRtcSignalingThread()->PostTask( - FROM_HERE, - base::BindOnce(&WebRtcMediaStreamAdapterMapTest:: - GetOrCreateRemoteStreamAdapterOnSignalingThread, - base::Unretained(this), base::Unretained(webrtc_stream), - base::Unretained(&adapter_ref))); - RunMessageLoopsUntilIdle(); - DCHECK(adapter_ref); - return adapter_ref; - } - - protected: - void GetOrCreateRemoteStreamAdapterOnSignalingThread( - webrtc::MediaStreamInterface* webrtc_stream, - std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>* adapter_ref) { - *adapter_ref = map_->GetOrCreateRemoteStreamAdapter(webrtc_stream); - EXPECT_TRUE(*adapter_ref); - } - - // Runs message loops on the webrtc signaling thread and the main thread until - // idle. - void RunMessageLoopsUntilIdle() { - base::WaitableEvent waitable_event( - base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - dependency_factory_->GetWebRtcSignalingThread()->PostTask( - FROM_HERE, base::BindOnce(&WebRtcMediaStreamAdapterMapTest::SignalEvent, - base::Unretained(this), &waitable_event)); - waitable_event.Wait(); - base::RunLoop().RunUntilIdle(); - } - - void SignalEvent(base::WaitableEvent* waitable_event) { - waitable_event->Signal(); - } - - // Message loop and child processes is needed for task queues and threading to - // work, as is necessary to create tracks and adapters. - base::test::ScopedTaskEnvironment scoped_task_environment_; - ChildProcess child_process_; - - std::unique_ptr<MockPeerConnectionDependencyFactory> dependency_factory_; - scoped_refptr<base::SingleThreadTaskRunner> main_thread_; - scoped_refptr<WebRtcMediaStreamAdapterMap> map_; -}; - -TEST_F(WebRtcMediaStreamAdapterMapTest, AddAndRemoveLocalStreamAdapter) { - blink::WebMediaStream local_web_stream = CreateLocalStream("local_stream"); - std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> adapter_ref = - map_->GetOrCreateLocalStreamAdapter(local_web_stream); - EXPECT_TRUE(adapter_ref); - EXPECT_TRUE(adapter_ref->adapter().IsEqual(local_web_stream)); - EXPECT_EQ(1u, map_->GetLocalStreamCount()); - - std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> adapter_ref2 = - map_->GetLocalStreamAdapter(local_web_stream); - EXPECT_TRUE(adapter_ref2); - EXPECT_EQ(&adapter_ref2->adapter(), &adapter_ref->adapter()); - EXPECT_EQ(1u, map_->GetLocalStreamCount()); - - adapter_ref.reset(); - EXPECT_EQ(1u, map_->GetLocalStreamCount()); - adapter_ref2.reset(); - EXPECT_EQ(0u, map_->GetLocalStreamCount()); -} - -TEST_F(WebRtcMediaStreamAdapterMapTest, LookUpLocalAdapterByWebRtcStream) { - blink::WebMediaStream local_web_stream = CreateLocalStream("local_stream"); - std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> adapter_ref = - map_->GetOrCreateLocalStreamAdapter(local_web_stream); - EXPECT_TRUE(adapter_ref); - EXPECT_TRUE(adapter_ref->adapter().IsEqual(local_web_stream)); - EXPECT_EQ(1u, map_->GetLocalStreamCount()); - - std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> adapter_ref2 = - map_->GetLocalStreamAdapter(adapter_ref->adapter().web_stream()); - EXPECT_TRUE(adapter_ref2); - EXPECT_EQ(&adapter_ref2->adapter(), &adapter_ref->adapter()); -} - -TEST_F(WebRtcMediaStreamAdapterMapTest, GetLocalStreamAdapterInvalidID) { - blink::WebMediaStream local_web_stream = CreateLocalStream("missing"); - EXPECT_FALSE(map_->GetLocalStreamAdapter(local_web_stream)); -} - -TEST_F(WebRtcMediaStreamAdapterMapTest, AddAndRemoveRemoteStreamAdapter) { - scoped_refptr<webrtc::MediaStreamInterface> remote_webrtc_stream = - CreateRemoteStream("remote_stream"); - std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> adapter_ref = - GetOrCreateRemoteStreamAdapter(remote_webrtc_stream.get()); - EXPECT_EQ(remote_webrtc_stream, adapter_ref->adapter().webrtc_stream()); - EXPECT_EQ(1u, map_->GetRemoteStreamCount()); - - std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> adapter_ref2 = - map_->GetRemoteStreamAdapter(remote_webrtc_stream.get()); - EXPECT_TRUE(adapter_ref2); - EXPECT_EQ(&adapter_ref2->adapter(), &adapter_ref->adapter()); - EXPECT_EQ(1u, map_->GetRemoteStreamCount()); - - adapter_ref.reset(); - EXPECT_EQ(1u, map_->GetRemoteStreamCount()); - adapter_ref2.reset(); - EXPECT_EQ(0u, map_->GetRemoteStreamCount()); -} - -TEST_F(WebRtcMediaStreamAdapterMapTest, LookUpRemoteAdapterByWebStream) { - scoped_refptr<webrtc::MediaStreamInterface> remote_webrtc_stream = - CreateRemoteStream("remote_stream"); - std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> adapter_ref = - GetOrCreateRemoteStreamAdapter(remote_webrtc_stream.get()); - EXPECT_EQ(remote_webrtc_stream, adapter_ref->adapter().webrtc_stream()); - EXPECT_EQ(1u, map_->GetRemoteStreamCount()); - - std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef> adapter_ref2 = - map_->GetRemoteStreamAdapter( - adapter_ref->adapter().webrtc_stream().get()); - EXPECT_TRUE(adapter_ref2); - EXPECT_EQ(&adapter_ref2->adapter(), &adapter_ref->adapter()); -} - -TEST_F(WebRtcMediaStreamAdapterMapTest, GetRemoteStreamAdapterInvalidID) { - scoped_refptr<webrtc::MediaStreamInterface> remote_webrtc_stream = - CreateRemoteStream("missing"); - EXPECT_FALSE(map_->GetRemoteStreamAdapter(remote_webrtc_stream.get())); -} - -} // namespace content diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc b/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc deleted file mode 100644 index ec8ffdca628..00000000000 --- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc +++ /dev/null @@ -1,400 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/media/webrtc/webrtc_media_stream_adapter.h" - -#include <stddef.h> - -#include <memory> -#include <string> -#include <utility> - -#include "base/run_loop.h" -#include "base/strings/stringprintf.h" -#include "base/synchronization/waitable_event.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/mock_audio_device_factory.h" -#include "content/renderer/media/stream/media_stream_video_source.h" -#include "content/renderer/media/stream/media_stream_video_track.h" -#include "content/renderer/media/stream/mock_constraint_factory.h" -#include "content/renderer/media/stream/mock_media_stream_video_source.h" -#include "content/renderer/media/stream/processed_local_audio_source.h" -#include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h" -#include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" -#include "third_party/blink/public/platform/web_media_stream.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_vector.h" -#include "third_party/blink/public/web/web_heap.h" - -using ::testing::_; - -namespace content { - -class WebRtcMediaStreamAdapterTest : public ::testing::Test { - public: - void SetUp() override { - dependency_factory_.reset(new MockPeerConnectionDependencyFactory()); - track_adapter_map_ = new WebRtcMediaStreamTrackAdapterMap( - dependency_factory_.get(), - blink::scheduler::GetSingleThreadTaskRunnerForTesting()); - } - - void TearDown() override { - track_adapter_map_ = nullptr; - blink::WebHeap::CollectAllGarbageForTesting(); - } - - protected: - // The ScopedTaskEnvironment prevents the ChildProcess from leaking a - // TaskScheduler. - base::test::ScopedTaskEnvironment scoped_task_environment_; - ChildProcess child_process_; - std::unique_ptr<MockPeerConnectionDependencyFactory> dependency_factory_; - scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map_; -}; - -class LocalWebRtcMediaStreamAdapterTest : public WebRtcMediaStreamAdapterTest { - public: - blink::WebMediaStream CreateWebMediaStream( - const std::string& audio_track_id, - const std::string& video_track_id) { - blink::WebVector<blink::WebMediaStreamTrack> audio_tracks( - static_cast<size_t>(1u)); - blink::WebMediaStreamSource audio_source; - audio_source.Initialize(blink::WebString::FromUTF8(audio_track_id), - blink::WebMediaStreamSource::kTypeAudio, - blink::WebString::FromUTF8(audio_track_id), - false /* remote */); - ProcessedLocalAudioSource* const source = new ProcessedLocalAudioSource( - -1 /* consumer_render_frame_id is N/A for non-browser tests */, - MediaStreamDevice(MEDIA_DEVICE_AUDIO_CAPTURE, "mock_audio_device_id", - "Mock audio device", - media::AudioParameters::kAudioCDSampleRate, - media::CHANNEL_LAYOUT_STEREO, - media::AudioParameters::kAudioCDSampleRate / 50), - false /* hotword_enabled */, false /* disable_local_echo */, - AudioProcessingProperties(), - base::Bind(&LocalWebRtcMediaStreamAdapterTest::OnAudioSourceStarted), - dependency_factory_.get()); - source->SetAllowInvalidRenderFrameIdForTesting(true); - audio_source.SetExtraData(source); // Takes ownership. - audio_tracks[0].Initialize(blink::WebString::FromUTF8(audio_track_id), - audio_source); - EXPECT_CALL(*mock_audio_device_factory_.mock_capturer_source(), - Initialize(_, _)); - EXPECT_CALL(*mock_audio_device_factory_.mock_capturer_source(), - SetAutomaticGainControl(true)); - EXPECT_CALL(*mock_audio_device_factory_.mock_capturer_source(), Start()); - EXPECT_CALL(*mock_audio_device_factory_.mock_capturer_source(), Stop()); - CHECK(source->ConnectToTrack(audio_tracks[0])); - - blink::WebVector<blink::WebMediaStreamTrack> video_tracks( - static_cast<size_t>(1u)); - MediaStreamSource::SourceStoppedCallback dummy_callback; - blink::WebMediaStreamSource video_source; - video_source.Initialize(blink::WebString::FromUTF8(video_track_id), - blink::WebMediaStreamSource::kTypeVideo, - blink::WebString::FromUTF8(video_track_id), - false /* remote */); - MediaStreamVideoSource* native_source = new MockMediaStreamVideoSource(); - video_source.SetExtraData(native_source); - video_tracks[0] = MediaStreamVideoTrack::CreateVideoTrack( - blink::WebString::FromUTF8(video_track_id), native_source, - MediaStreamVideoSource::ConstraintsCallback(), true); - - blink::WebMediaStream stream_desc; - stream_desc.Initialize("stream_id", audio_tracks, video_tracks); - return stream_desc; - } - - private: - static void OnAudioSourceStarted(MediaStreamSource* source, - MediaStreamRequestResult result, - const blink::WebString& result_name) {} - - MockAudioDeviceFactory mock_audio_device_factory_; -}; - -class RemoteWebRtcMediaStreamAdapterTest : public WebRtcMediaStreamAdapterTest { - public: - scoped_refptr<webrtc::MediaStreamInterface> CreateWebRtcMediaStream( - const std::string& audio_track_id, - const std::string& video_track_id) { - scoped_refptr<webrtc::MediaStreamInterface> stream( - new rtc::RefCountedObject<MockMediaStream>("remote_stream")); - stream->AddTrack(MockWebRtcAudioTrack::Create(audio_track_id).get()); - stream->AddTrack(MockWebRtcVideoTrack::Create(video_track_id).get()); - return stream; - } - - std::unique_ptr<WebRtcMediaStreamAdapter> CreateRemoteStreamAdapter( - webrtc::MediaStreamInterface* webrtc_stream) { - std::unique_ptr<WebRtcMediaStreamAdapter> adapter; - dependency_factory_->GetWebRtcSignalingThread()->PostTask( - FROM_HERE, - base::BindOnce( - &RemoteWebRtcMediaStreamAdapterTest:: - CreateRemoteStreamAdapterOnSignalingThread, - base::Unretained(this), - base::Unretained( - blink::scheduler::GetSingleThreadTaskRunnerForTesting().get()), - base::Unretained(webrtc_stream), base::Unretained(&adapter))); - RunMessageLoopsUntilIdle(); - DCHECK(adapter); - return adapter; - } - - // Adds the track and gets the adapters for the stream's resulting tracks. - template <typename TrackType> - WebRtcMediaStreamAdapter::TrackAdapterRefs AddTrack( - webrtc::MediaStreamInterface* webrtc_stream, - TrackType* webrtc_track) { - typedef bool (webrtc::MediaStreamInterface::*AddTrack)(TrackType*); - dependency_factory_->GetWebRtcSignalingThread()->PostTask( - FROM_HERE, base::BindOnce(base::IgnoreResult<AddTrack>( - &webrtc::MediaStreamInterface::AddTrack), - base::Unretained(webrtc_stream), - base::Unretained(webrtc_track))); - WebRtcMediaStreamAdapter::TrackAdapterRefs track_refs; - dependency_factory_->GetWebRtcSignalingThread()->PostTask( - FROM_HERE, - base::BindOnce(&RemoteWebRtcMediaStreamAdapterTest:: - GetStreamTrackRefsOnSignalingThread, - base::Unretained(this), base::Unretained(webrtc_stream), - base::Unretained(&track_refs))); - RunMessageLoopsUntilIdle(); - return track_refs; - } - - // Removes the track and gets the adapters for the stream's resulting tracks. - template <typename TrackType> - WebRtcMediaStreamAdapter::TrackAdapterRefs RemoveTrack( - webrtc::MediaStreamInterface* webrtc_stream, - TrackType* webrtc_track) { - typedef bool (webrtc::MediaStreamInterface::*RemoveTrack)(TrackType*); - dependency_factory_->GetWebRtcSignalingThread()->PostTask( - FROM_HERE, - base::BindOnce(base::IgnoreResult<RemoveTrack>( - &webrtc::MediaStreamInterface::RemoveTrack), - base::Unretained(webrtc_stream), - base::Unretained(webrtc_track))); - WebRtcMediaStreamAdapter::TrackAdapterRefs track_refs; - dependency_factory_->GetWebRtcSignalingThread()->PostTask( - FROM_HERE, - base::BindOnce(&RemoteWebRtcMediaStreamAdapterTest:: - GetStreamTrackRefsOnSignalingThread, - base::Unretained(this), base::Unretained(webrtc_stream), - base::Unretained(&track_refs))); - RunMessageLoopsUntilIdle(); - return track_refs; - } - - private: - void CreateRemoteStreamAdapterOnSignalingThread( - base::SingleThreadTaskRunner* main_thread, - webrtc::MediaStreamInterface* webrtc_stream, - std::unique_ptr<WebRtcMediaStreamAdapter>* adapter) { - *adapter = WebRtcMediaStreamAdapter::CreateRemoteStreamAdapter( - main_thread, track_adapter_map_, webrtc_stream); - EXPECT_FALSE((*adapter)->is_initialized()); - } - - void GetStreamTrackRefsOnSignalingThread( - webrtc::MediaStreamInterface* webrtc_stream, - WebRtcMediaStreamAdapter::TrackAdapterRefs* out_track_refs) { - WebRtcMediaStreamAdapter::TrackAdapterRefs track_refs; - for (auto& audio_track : webrtc_stream->GetAudioTracks()) { - track_refs.push_back( - track_adapter_map_->GetOrCreateRemoteTrackAdapter(audio_track.get())); - } - for (auto& video_track : webrtc_stream->GetVideoTracks()) { - track_refs.push_back( - track_adapter_map_->GetOrCreateRemoteTrackAdapter(video_track.get())); - } - *out_track_refs = std::move(track_refs); - } - - // Runs message loops on the webrtc signaling thread and the main thread until - // idle. - void RunMessageLoopsUntilIdle() { - base::WaitableEvent waitable_event( - base::WaitableEvent::ResetPolicy::MANUAL, - base::WaitableEvent::InitialState::NOT_SIGNALED); - dependency_factory_->GetWebRtcSignalingThread()->PostTask( - FROM_HERE, - base::BindOnce(&RemoteWebRtcMediaStreamAdapterTest::SignalEvent, - base::Unretained(this), &waitable_event)); - // TODO(hbos): Use base::RunLoop instead of WaitableEvent. - waitable_event.Wait(); - base::RunLoop().RunUntilIdle(); - } - - void SignalEvent(base::WaitableEvent* waitable_event) { - waitable_event->Signal(); - } -}; - -TEST_F(LocalWebRtcMediaStreamAdapterTest, CreateStreamAdapter) { - blink::WebMediaStream web_stream = - CreateWebMediaStream("audio_track_id", "video_track_id"); - std::unique_ptr<WebRtcMediaStreamAdapter> adapter = - WebRtcMediaStreamAdapter::CreateLocalStreamAdapter( - dependency_factory_.get(), track_adapter_map_, web_stream); - EXPECT_TRUE(adapter->IsEqual(web_stream)); - EXPECT_EQ(1u, adapter->webrtc_stream()->GetAudioTracks().size()); - EXPECT_EQ(1u, adapter->webrtc_stream()->GetVideoTracks().size()); - EXPECT_EQ(web_stream.Id().Utf8(), adapter->webrtc_stream()->id()); -} - -TEST_F(LocalWebRtcMediaStreamAdapterTest, - CreateStreamAdapterWithSharedTrackIds) { - blink::WebMediaStream web_stream = - CreateWebMediaStream("shared_track_id", "shared_track_id"); - std::unique_ptr<WebRtcMediaStreamAdapter> adapter = - WebRtcMediaStreamAdapter::CreateLocalStreamAdapter( - dependency_factory_.get(), track_adapter_map_, web_stream); - EXPECT_TRUE(adapter->IsEqual(web_stream)); - EXPECT_EQ(1u, adapter->webrtc_stream()->GetAudioTracks().size()); - EXPECT_EQ(1u, adapter->webrtc_stream()->GetVideoTracks().size()); - EXPECT_EQ(web_stream.Id().Utf8(), adapter->webrtc_stream()->id()); -} - -// It should not crash if |MediaStream| is created in blink with an unknown -// audio source. This can happen if a |MediaStream| is created with remote audio -// track. -TEST_F(LocalWebRtcMediaStreamAdapterTest, - AdapterForWebStreamWithoutAudioSource) { - // Create a blink MediaStream description. - blink::WebMediaStreamSource audio_source; - audio_source.Initialize("audio source", - blink::WebMediaStreamSource::kTypeAudio, "something", - false /* remote */); - // Without |audio_source.SetExtraData()| it is possible to initialize tracks - // and streams but the source is a dummy. - - blink::WebVector<blink::WebMediaStreamTrack> audio_tracks( - static_cast<size_t>(1)); - audio_tracks[0].Initialize(audio_source.Id(), audio_source); - blink::WebVector<blink::WebMediaStreamTrack> video_tracks( - static_cast<size_t>(0)); - - blink::WebMediaStream web_stream; - web_stream.Initialize("stream_id", audio_tracks, video_tracks); - - std::unique_ptr<WebRtcMediaStreamAdapter> adapter = - WebRtcMediaStreamAdapter::CreateLocalStreamAdapter( - dependency_factory_.get(), track_adapter_map_, web_stream); - EXPECT_TRUE(adapter->IsEqual(web_stream)); - EXPECT_EQ(0u, adapter->webrtc_stream()->GetAudioTracks().size()); - EXPECT_EQ(0u, adapter->webrtc_stream()->GetVideoTracks().size()); - EXPECT_EQ(web_stream.Id().Utf8(), adapter->webrtc_stream()->id()); -} - -TEST_F(LocalWebRtcMediaStreamAdapterTest, RemoveAndAddTrack) { - blink::WebMediaStream web_stream = - CreateWebMediaStream("audio_track_id", "video_track_id"); - std::unique_ptr<WebRtcMediaStreamAdapter> adapter = - WebRtcMediaStreamAdapter::CreateLocalStreamAdapter( - dependency_factory_.get(), track_adapter_map_, web_stream); - EXPECT_TRUE(adapter->IsEqual(web_stream)); - EXPECT_EQ(1u, adapter->webrtc_stream()->GetAudioTracks().size()); - EXPECT_EQ(1u, adapter->webrtc_stream()->GetVideoTracks().size()); - EXPECT_EQ(web_stream.Id().Utf8(), adapter->webrtc_stream()->id()); - - // Modify the web layer stream, make sure the webrtc layer stream is updated. - blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; - web_stream.AudioTracks(audio_tracks); - - web_stream.RemoveTrack(audio_tracks[0]); - EXPECT_TRUE(adapter->webrtc_stream()->GetAudioTracks().empty()); - - blink::WebVector<blink::WebMediaStreamTrack> video_tracks; - web_stream.VideoTracks(video_tracks); - - web_stream.RemoveTrack(video_tracks[0]); - EXPECT_TRUE(adapter->webrtc_stream()->GetVideoTracks().empty()); - - web_stream.AddTrack(audio_tracks[0]); - EXPECT_EQ(1u, adapter->webrtc_stream()->GetAudioTracks().size()); - - web_stream.AddTrack(video_tracks[0]); - EXPECT_EQ(1u, adapter->webrtc_stream()->GetVideoTracks().size()); -} - -TEST_F(RemoteWebRtcMediaStreamAdapterTest, CreateStreamAdapter) { - scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream = - CreateWebRtcMediaStream("audio_track_id", "video_track_id"); - std::unique_ptr<WebRtcMediaStreamAdapter> adapter = - CreateRemoteStreamAdapter(webrtc_stream.get()); - EXPECT_TRUE(adapter->is_initialized()); - EXPECT_EQ(webrtc_stream, adapter->webrtc_stream()); - blink::WebVector<blink::WebMediaStreamTrack> web_audio_tracks; - adapter->web_stream().AudioTracks(web_audio_tracks); - EXPECT_EQ(1u, web_audio_tracks.size()); - blink::WebVector<blink::WebMediaStreamTrack> web_video_tracks; - adapter->web_stream().VideoTracks(web_video_tracks); - EXPECT_EQ(1u, web_video_tracks.size()); -} - -TEST_F(RemoteWebRtcMediaStreamAdapterTest, - CreateStreamAdapterWithSharedTrackIds) { - scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream = - CreateWebRtcMediaStream("shared_track_id", "shared_track_id"); - std::unique_ptr<WebRtcMediaStreamAdapter> adapter = - CreateRemoteStreamAdapter(webrtc_stream.get()); - EXPECT_TRUE(adapter->is_initialized()); - EXPECT_EQ(webrtc_stream, adapter->webrtc_stream()); - blink::WebVector<blink::WebMediaStreamTrack> web_audio_tracks; - adapter->web_stream().AudioTracks(web_audio_tracks); - EXPECT_EQ(1u, web_audio_tracks.size()); - blink::WebVector<blink::WebMediaStreamTrack> web_video_tracks; - adapter->web_stream().VideoTracks(web_video_tracks); - EXPECT_EQ(1u, web_video_tracks.size()); -} - -TEST_F(RemoteWebRtcMediaStreamAdapterTest, RemoveAndAddTrack) { - scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream = - CreateWebRtcMediaStream("audio_track_id", "video_track_id"); - std::unique_ptr<WebRtcMediaStreamAdapter> adapter = - CreateRemoteStreamAdapter(webrtc_stream.get()); - EXPECT_TRUE(adapter->is_initialized()); - EXPECT_EQ(webrtc_stream, adapter->webrtc_stream()); - blink::WebVector<blink::WebMediaStreamTrack> web_audio_tracks; - adapter->web_stream().AudioTracks(web_audio_tracks); - EXPECT_EQ(1u, web_audio_tracks.size()); - blink::WebVector<blink::WebMediaStreamTrack> web_video_tracks; - adapter->web_stream().VideoTracks(web_video_tracks); - EXPECT_EQ(1u, web_video_tracks.size()); - - // Modify the webrtc layer stream, make sure the web layer stream is updated. - rtc::scoped_refptr<webrtc::AudioTrackInterface> webrtc_audio_track = - webrtc_stream->GetAudioTracks()[0]; - adapter->SetTracks( - RemoveTrack(webrtc_stream.get(), webrtc_audio_track.get())); - adapter->web_stream().AudioTracks(web_audio_tracks); - EXPECT_EQ(0u, web_audio_tracks.size()); - - rtc::scoped_refptr<webrtc::VideoTrackInterface> webrtc_video_track = - webrtc_stream->GetVideoTracks()[0]; - adapter->SetTracks( - RemoveTrack(webrtc_stream.get(), webrtc_video_track.get())); - adapter->web_stream().VideoTracks(web_video_tracks); - EXPECT_EQ(0u, web_video_tracks.size()); - - adapter->SetTracks(AddTrack(webrtc_stream.get(), webrtc_audio_track.get())); - adapter->web_stream().AudioTracks(web_audio_tracks); - EXPECT_EQ(1u, web_audio_tracks.size()); - - adapter->SetTracks(AddTrack(webrtc_stream.get(), webrtc_video_track.get())); - adapter->web_stream().VideoTracks(web_video_tracks); - EXPECT_EQ(1u, web_video_tracks.size()); -} - -} // namespace content 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 e03d1719ee0..a20adaaae7b 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 @@ -63,22 +63,24 @@ WebRtcMediaStreamTrackAdapter::WebRtcMediaStreamTrackAdapter( remote_track_can_complete_initialization_( base::WaitableEvent::ResetPolicy::MANUAL, base::WaitableEvent::InitialState::NOT_SIGNALED), - is_initialized_(false) { + is_initialized_(false), + is_disposed_(false) { DCHECK(factory_); DCHECK(main_thread_); } WebRtcMediaStreamTrackAdapter::~WebRtcMediaStreamTrackAdapter() { DCHECK(!remote_track_can_complete_initialization_.IsSignaled()); - DCHECK(!is_initialized_); + DCHECK(is_disposed_); } void WebRtcMediaStreamTrackAdapter::Dispose() { DCHECK(main_thread_->BelongsToCurrentThread()); - if (!is_initialized_) + DCHECK(is_initialized_); + if (is_disposed_) return; remote_track_can_complete_initialization_.Reset(); - is_initialized_ = false; + is_disposed_ = true; if (web_track_.Source().GetType() == blink::WebMediaStreamSource::kTypeAudio) { if (local_track_audio_sink_) @@ -99,10 +101,19 @@ bool WebRtcMediaStreamTrackAdapter::is_initialized() const { return is_initialized_; } +void WebRtcMediaStreamTrackAdapter::InitializeOnMainThread() { + DCHECK(main_thread_->BelongsToCurrentThread()); + if (is_initialized_) + return; + // TODO(hbos): Only ever initialize explicitly, + // remove EnsureTrackIsInitialized(). https://crbug.com/857458 + EnsureTrackIsInitialized(); +} + const blink::WebMediaStreamTrack& WebRtcMediaStreamTrackAdapter::web_track() { DCHECK(main_thread_->BelongsToCurrentThread()); - DCHECK(!web_track_.IsNull()); EnsureTrackIsInitialized(); + DCHECK(!web_track_.IsNull()); return web_track_; } @@ -231,6 +242,7 @@ void WebRtcMediaStreamTrackAdapter:: } void WebRtcMediaStreamTrackAdapter::EnsureTrackIsInitialized() { + DCHECK(main_thread_->BelongsToCurrentThread()); if (is_initialized_) return; @@ -242,7 +254,6 @@ void WebRtcMediaStreamTrackAdapter::EnsureTrackIsInitialized() { void WebRtcMediaStreamTrackAdapter::DisposeLocalAudioTrack() { DCHECK(main_thread_->BelongsToCurrentThread()); - DCHECK(!is_initialized_); DCHECK(local_track_audio_sink_); DCHECK_EQ(web_track_.Source().GetType(), blink::WebMediaStreamSource::kTypeAudio); @@ -256,7 +267,6 @@ void WebRtcMediaStreamTrackAdapter::DisposeLocalAudioTrack() { void WebRtcMediaStreamTrackAdapter::DisposeLocalVideoTrack() { DCHECK(main_thread_->BelongsToCurrentThread()); - DCHECK(!is_initialized_); DCHECK(local_track_video_sink_); DCHECK_EQ(web_track_.Source().GetType(), blink::WebMediaStreamSource::kTypeVideo); @@ -267,7 +277,6 @@ void WebRtcMediaStreamTrackAdapter::DisposeLocalVideoTrack() { void WebRtcMediaStreamTrackAdapter::DisposeRemoteAudioTrack() { DCHECK(main_thread_->BelongsToCurrentThread()); - DCHECK(!is_initialized_); DCHECK(remote_audio_track_adapter_); DCHECK_EQ(web_track_.Source().GetType(), blink::WebMediaStreamSource::kTypeAudio); @@ -280,7 +289,6 @@ void WebRtcMediaStreamTrackAdapter::DisposeRemoteAudioTrack() { void WebRtcMediaStreamTrackAdapter::DisposeRemoteVideoTrack() { DCHECK(main_thread_->BelongsToCurrentThread()); - DCHECK(!is_initialized_); DCHECK(remote_video_track_adapter_); DCHECK_EQ(web_track_.Source().GetType(), blink::WebMediaStreamSource::kTypeVideo); @@ -300,7 +308,7 @@ void WebRtcMediaStreamTrackAdapter:: void WebRtcMediaStreamTrackAdapter::FinalizeRemoteTrackDisposingOnMainThread() { DCHECK(main_thread_->BelongsToCurrentThread()); - DCHECK(!is_initialized_); + DCHECK(is_disposed_); remote_audio_track_adapter_ = nullptr; remote_video_track_adapter_ = nullptr; webrtc_track_ = nullptr; diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter.h b/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter.h index 722738c3950..8be75b5b895 100644 --- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter.h +++ b/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter.h @@ -53,6 +53,7 @@ class CONTENT_EXPORT WebRtcMediaStreamTrackAdapter void Dispose(); bool is_initialized() const; + void InitializeOnMainThread(); // These methods must be called on the main thread. // TODO(hbos): Allow these methods to be called on any thread and make them // const. https://crbug.com/756436 @@ -116,6 +117,7 @@ class CONTENT_EXPORT WebRtcMediaStreamTrackAdapter // completed on the main thread. base::WaitableEvent remote_track_can_complete_initialization_; bool is_initialized_; + bool is_disposed_; blink::WebMediaStreamTrack web_track_; scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track_; // If the track is local, a sink is added to the local webrtc track that is diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.cc b/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.cc index 28d6c1713a4..de3f036beff 100644 --- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.cc +++ b/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.cc @@ -59,6 +59,17 @@ WebRtcMediaStreamTrackAdapterMap::AdapterRef::Copy() const { return base::WrapUnique(new AdapterRef(map_, type_, adapter_)); } +void WebRtcMediaStreamTrackAdapterMap::AdapterRef::InitializeOnMainThread() { + adapter_->InitializeOnMainThread(); + if (type_ == WebRtcMediaStreamTrackAdapterMap::AdapterRef::Type::kRemote) { + base::AutoLock scoped_lock(map_->lock_); + if (!map_->remote_track_adapters_.FindBySecondary(web_track().UniqueId())) { + map_->remote_track_adapters_.SetSecondaryKey(webrtc_track(), + web_track().UniqueId()); + } + } +} + WebRtcMediaStreamTrackAdapterMap::WebRtcMediaStreamTrackAdapterMap( PeerConnectionDependencyFactory* const factory, scoped_refptr<base::SingleThreadTaskRunner> main_thread) @@ -182,13 +193,13 @@ WebRtcMediaStreamTrackAdapterMap::GetOrCreateRemoteTrackAdapter( // entry as its secondary key. This ensures that there is at least one // |AdapterRef| alive until after the adapter is initialized and its secondary // key is set. + auto adapter_ref = base::WrapUnique( + new AdapterRef(this, AdapterRef::Type::kRemote, new_adapter)); main_thread_->PostTask( FROM_HERE, base::BindOnce( - &WebRtcMediaStreamTrackAdapterMap::OnRemoteTrackAdapterInitialized, - this, - base::WrapUnique( - new AdapterRef(this, AdapterRef::Type::kRemote, new_adapter)))); + &WebRtcMediaStreamTrackAdapterMap::AdapterRef::InitializeOnMainThread, + std::move(adapter_ref))); return base::WrapUnique( new AdapterRef(this, AdapterRef::Type::kRemote, new_adapter)); } @@ -198,14 +209,4 @@ size_t WebRtcMediaStreamTrackAdapterMap::GetRemoteTrackCount() const { return remote_track_adapters_.PrimarySize(); } -void WebRtcMediaStreamTrackAdapterMap::OnRemoteTrackAdapterInitialized( - std::unique_ptr<AdapterRef> adapter_ref) { - DCHECK(adapter_ref->is_initialized()); - { - base::AutoLock scoped_lock(lock_); - remote_track_adapters_.SetSecondaryKey(adapter_ref->webrtc_track(), - adapter_ref->web_track().UniqueId()); - } -} - } // namespace content diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h b/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h index c7ef9ed9b92..8c9cbf17c0d 100644 --- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h +++ b/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h @@ -38,6 +38,7 @@ class CONTENT_EXPORT WebRtcMediaStreamTrackAdapterMap std::unique_ptr<AdapterRef> Copy() const; bool is_initialized() const { return adapter_->is_initialized(); } + void InitializeOnMainThread(); const blink::WebMediaStreamTrack& web_track() const { return adapter_->web_track(); } @@ -137,8 +138,6 @@ class CONTENT_EXPORT WebRtcMediaStreamTrackAdapterMap // Invoke on the main thread. virtual ~WebRtcMediaStreamTrackAdapterMap(); - void OnRemoteTrackAdapterInitialized(std::unique_ptr<AdapterRef> adapter_ref); - // Pointer to a |PeerConnectionDependencyFactory| owned by the |RenderThread|. // It's valid for the lifetime of |RenderThread|. PeerConnectionDependencyFactory* const factory_; diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map_unittest.cc b/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map_unittest.cc index 8c5fd3e426f..a141ce50156 100644 --- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map_unittest.cc +++ b/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map_unittest.cc @@ -53,8 +53,8 @@ class WebRtcMediaStreamTrackAdapterMapTest : public ::testing::Test { } std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> - GetOrCreateRemoteTrackAdapter( - webrtc::MediaStreamTrackInterface* webrtc_track) { + GetOrCreateRemoteTrackAdapter(webrtc::MediaStreamTrackInterface* webrtc_track, + bool wait_for_initialization = true) { DCHECK(main_thread_->BelongsToCurrentThread()); std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> adapter; signaling_thread()->PostTask( @@ -63,7 +63,13 @@ class WebRtcMediaStreamTrackAdapterMapTest : public ::testing::Test { GetOrCreateRemoteTrackAdapterOnSignalingThread, base::Unretained(this), base::Unretained(webrtc_track), &adapter)); - RunMessageLoopsUntilIdle(); + RunMessageLoopsUntilIdle(wait_for_initialization); + DCHECK(adapter); + if (wait_for_initialization) { + DCHECK(adapter->is_initialized()); + } else { + DCHECK(!adapter->is_initialized()); + } return adapter; } @@ -76,7 +82,7 @@ class WebRtcMediaStreamTrackAdapterMapTest : public ::testing::Test { // Runs message loops on the webrtc signaling thread and the main thread until // idle. - void RunMessageLoopsUntilIdle() { + void RunMessageLoopsUntilIdle(bool run_loop_on_main_thread = true) { DCHECK(main_thread_->BelongsToCurrentThread()); base::WaitableEvent waitable_event( base::WaitableEvent::ResetPolicy::MANUAL, @@ -86,7 +92,8 @@ class WebRtcMediaStreamTrackAdapterMapTest : public ::testing::Test { RunMessageLoopUntilIdleOnSignalingThread, base::Unretained(this), &waitable_event)); waitable_event.Wait(); - base::RunLoop().RunUntilIdle(); + if (run_loop_on_main_thread) + base::RunLoop().RunUntilIdle(); } void RunMessageLoopUntilIdleOnSignalingThread( @@ -168,6 +175,29 @@ TEST_F(WebRtcMediaStreamTrackAdapterMapTest, AddAndRemoveRemoteTrackAdapter) { } TEST_F(WebRtcMediaStreamTrackAdapterMapTest, + InitializeRemoteTrackAdapterExplicitly) { + scoped_refptr<MockWebRtcAudioTrack> webrtc_track = + MockWebRtcAudioTrack::Create("remote_track"); + std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> adapter_ref = + GetOrCreateRemoteTrackAdapter(webrtc_track.get(), false); + EXPECT_FALSE(adapter_ref->is_initialized()); + adapter_ref->InitializeOnMainThread(); + EXPECT_TRUE(adapter_ref->is_initialized()); + + EXPECT_EQ(1u, map_->GetRemoteTrackCount()); + // Ensure the implicit initialization's posted task is run after it is already + // initialized. + RunMessageLoopsUntilIdle(); + // Destroying all references to the adapter should remove it from the map and + // dispose it. + adapter_ref.reset(); + EXPECT_EQ(0u, map_->GetRemoteTrackCount()); + EXPECT_EQ(nullptr, map_->GetRemoteTrackAdapter(webrtc_track.get())); + // Allow the disposing of track to occur. + RunMessageLoopsUntilIdle(); +} + +TEST_F(WebRtcMediaStreamTrackAdapterMapTest, LocalAndRemoteTrackAdaptersWithSameID) { // Local and remote tracks should be able to use the same id without conflict. const char* id = "id"; diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_unittest.cc b/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_unittest.cc index 7ca513bc07f..74f586d44b1 100644 --- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_unittest.cc +++ b/chromium/content/renderer/media/webrtc/webrtc_media_stream_track_adapter_unittest.cc @@ -37,7 +37,6 @@ class WebRtcMediaStreamTrackAdapterTest : public ::testing::Test { if (track_adapter_) { EXPECT_TRUE(track_adapter_->is_initialized()); track_adapter_->Dispose(); - EXPECT_FALSE(track_adapter_->is_initialized()); track_adapter_ = nullptr; RunMessageLoopsUntilIdle(); } @@ -80,9 +79,9 @@ class WebRtcMediaStreamTrackAdapterTest : public ::testing::Test { dependency_factory_.get(), main_thread_, webrtc_track); } - // Runs message loops on the webrtc signaling thread and the main thread until - // idle. - void RunMessageLoopsUntilIdle() { + // Runs message loops on the webrtc signaling thread and optionally the main + // thread until idle. + void RunMessageLoopsUntilIdle(bool run_loop_on_main_thread = true) { base::WaitableEvent waitable_event( base::WaitableEvent::ResetPolicy::MANUAL, base::WaitableEvent::InitialState::NOT_SIGNALED); @@ -91,7 +90,8 @@ class WebRtcMediaStreamTrackAdapterTest : public ::testing::Test { RunMessageLoopUntilIdleOnSignalingThread, base::Unretained(this), &waitable_event)); waitable_event.Wait(); - base::RunLoop().RunUntilIdle(); + if (run_loop_on_main_thread) + base::RunLoop().RunUntilIdle(); } void RunMessageLoopUntilIdleOnSignalingThread( @@ -157,6 +157,7 @@ TEST_F(WebRtcMediaStreamTrackAdapterTest, RemoteAudioTrack) { base::BindOnce( &WebRtcMediaStreamTrackAdapterTest::CreateRemoteTrackAdapter, base::Unretained(this), base::Unretained(webrtc_track.get()))); + // The adapter is initialized implicitly in a PostTask, allow it to run. RunMessageLoopsUntilIdle(); DCHECK(track_adapter_); EXPECT_TRUE(track_adapter_->is_initialized()); @@ -181,6 +182,7 @@ TEST_F(WebRtcMediaStreamTrackAdapterTest, RemoteVideoTrack) { base::BindOnce( &WebRtcMediaStreamTrackAdapterTest::CreateRemoteTrackAdapter, base::Unretained(this), base::Unretained(webrtc_track.get()))); + // The adapter is initialized implicitly in a PostTask, allow it to run. RunMessageLoopsUntilIdle(); DCHECK(track_adapter_); EXPECT_TRUE(track_adapter_->is_initialized()); @@ -197,4 +199,33 @@ TEST_F(WebRtcMediaStreamTrackAdapterTest, RemoteVideoTrack) { track_adapter_->GetRemoteVideoTrackAdapterForTesting()->initialized()); } +TEST_F(WebRtcMediaStreamTrackAdapterTest, RemoteTrackExplicitlyInitialized) { + scoped_refptr<MockWebRtcAudioTrack> webrtc_track = + MockWebRtcAudioTrack::Create("remote_audio_track"); + dependency_factory_->GetWebRtcSignalingThread()->PostTask( + FROM_HERE, + base::BindOnce( + &WebRtcMediaStreamTrackAdapterTest::CreateRemoteTrackAdapter, + base::Unretained(this), base::Unretained(webrtc_track.get()))); + // Wait for the CreateRemoteTrackAdapter() call, but don't run the main thread + // loop that would have implicitly initialized the adapter. + RunMessageLoopsUntilIdle(false); + DCHECK(track_adapter_); + EXPECT_FALSE(track_adapter_->is_initialized()); + // Explicitly initialize before the main thread loop has a chance to run. + track_adapter_->InitializeOnMainThread(); + EXPECT_TRUE(track_adapter_->is_initialized()); + EXPECT_TRUE(!track_adapter_->web_track().IsNull()); + EXPECT_EQ(track_adapter_->web_track().Source().GetType(), + blink::WebMediaStreamSource::kTypeAudio); + EXPECT_TRUE(track_adapter_->webrtc_track()); + EXPECT_EQ(track_adapter_->webrtc_track()->kind(), + webrtc::MediaStreamTrackInterface::kAudioKind); + EXPECT_EQ(track_adapter_->webrtc_track()->id().c_str(), + track_adapter_->web_track().Id()); + EXPECT_TRUE(track_adapter_->GetRemoteAudioTrackAdapterForTesting()); + EXPECT_TRUE( + track_adapter_->GetRemoteAudioTrackAdapterForTesting()->initialized()); +} + } // namespace content diff --git a/chromium/content/renderer/media/webrtc/webrtc_set_description_observer.cc b/chromium/content/renderer/media/webrtc/webrtc_set_description_observer.cc new file mode 100644 index 00000000000..f36ef07ad97 --- /dev/null +++ b/chromium/content/renderer/media/webrtc/webrtc_set_description_observer.cc @@ -0,0 +1,166 @@ +// Copyright (c) 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/renderer/media/webrtc/webrtc_set_description_observer.h" + +#include "base/logging.h" + +namespace content { + +WebRtcSetDescriptionObserver::States::States() + : signaling_state( + webrtc::PeerConnectionInterface::SignalingState::kClosed) {} + +WebRtcSetDescriptionObserver::States::States(States&& other) + : signaling_state(other.signaling_state), + transceiver_states(std::move(other.transceiver_states)) {} + +WebRtcSetDescriptionObserver::States::~States() = default; + +WebRtcSetDescriptionObserver::States& WebRtcSetDescriptionObserver::States:: +operator=(States&& other) { + signaling_state = other.signaling_state; + transceiver_states = std::move(other.transceiver_states); + return *this; +} + +WebRtcSetDescriptionObserver::WebRtcSetDescriptionObserver() = default; + +WebRtcSetDescriptionObserver::~WebRtcSetDescriptionObserver() = default; + +WebRtcSetDescriptionObserverHandlerImpl:: + WebRtcSetDescriptionObserverHandlerImpl( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner, + scoped_refptr<webrtc::PeerConnectionInterface> pc, + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, + scoped_refptr<WebRtcSetDescriptionObserver> observer, + bool surface_receivers_only) + : main_task_runner_(std::move(main_task_runner)), + signaling_task_runner_(std::move(signaling_task_runner)), + pc_(std::move(pc)), + track_adapter_map_(std::move(track_adapter_map)), + observer_(std::move(observer)), + surface_receivers_only_(surface_receivers_only) {} + +WebRtcSetDescriptionObserverHandlerImpl:: + ~WebRtcSetDescriptionObserverHandlerImpl() = default; + +void WebRtcSetDescriptionObserverHandlerImpl::OnSetDescriptionComplete( + webrtc::RTCError error) { + CHECK(signaling_task_runner_->BelongsToCurrentThread()); + std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> + receiver_only_transceivers; + std::vector<rtc::scoped_refptr<webrtc::RtpTransceiverInterface>> transceivers; + if (surface_receivers_only_) { + for (const auto& receiver : pc_->GetReceivers()) { + transceivers.push_back(new SurfaceReceiverStateOnly(receiver)); + } + } else { + transceivers = pc_->GetTransceivers(); + } + TransceiverStateSurfacer transceiver_state_surfacer(main_task_runner_, + signaling_task_runner_); + transceiver_state_surfacer.Initialize(track_adapter_map_, + std::move(transceivers)); + main_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&WebRtcSetDescriptionObserverHandlerImpl:: + OnSetDescriptionCompleteOnMainThread, + this, std::move(error), pc_->signaling_state(), + std::move(transceiver_state_surfacer))); +} + +void WebRtcSetDescriptionObserverHandlerImpl:: + OnSetDescriptionCompleteOnMainThread( + webrtc::RTCError error, + webrtc::PeerConnectionInterface::SignalingState signaling_state, + TransceiverStateSurfacer transceiver_state_surfacer) { + CHECK(main_task_runner_->BelongsToCurrentThread()); + WebRtcSetDescriptionObserver::States states; + states.signaling_state = signaling_state; + states.transceiver_states = transceiver_state_surfacer.ObtainStates(); + observer_->OnSetDescriptionComplete(std::move(error), std::move(states)); +} + +scoped_refptr<WebRtcSetLocalDescriptionObserverHandler> +WebRtcSetLocalDescriptionObserverHandler::Create( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner, + scoped_refptr<webrtc::PeerConnectionInterface> pc, + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, + scoped_refptr<WebRtcSetDescriptionObserver> observer, + bool surface_receivers_only) { + return new rtc::RefCountedObject<WebRtcSetLocalDescriptionObserverHandler>( + std::move(main_task_runner), std::move(signaling_task_runner), + std::move(pc), std::move(track_adapter_map), std::move(observer), + surface_receivers_only); +} + +WebRtcSetLocalDescriptionObserverHandler:: + WebRtcSetLocalDescriptionObserverHandler( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner, + scoped_refptr<webrtc::PeerConnectionInterface> pc, + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, + scoped_refptr<WebRtcSetDescriptionObserver> observer, + bool surface_receivers_only) + : handler_impl_(new WebRtcSetDescriptionObserverHandlerImpl( + std::move(main_task_runner), + std::move(signaling_task_runner), + std::move(pc), + std::move(track_adapter_map), + std::move(observer), + surface_receivers_only)) {} + +WebRtcSetLocalDescriptionObserverHandler:: + ~WebRtcSetLocalDescriptionObserverHandler() = default; + +void WebRtcSetLocalDescriptionObserverHandler::OnSuccess() { + handler_impl_->OnSetDescriptionComplete(webrtc::RTCError::OK()); +} + +void WebRtcSetLocalDescriptionObserverHandler::OnFailure( + webrtc::RTCError error) { + handler_impl_->OnSetDescriptionComplete(std::move(error)); +} + +scoped_refptr<WebRtcSetRemoteDescriptionObserverHandler> +WebRtcSetRemoteDescriptionObserverHandler::Create( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner, + scoped_refptr<webrtc::PeerConnectionInterface> pc, + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, + scoped_refptr<WebRtcSetDescriptionObserver> observer, + bool surface_receivers_only) { + return new rtc::RefCountedObject<WebRtcSetRemoteDescriptionObserverHandler>( + std::move(main_task_runner), std::move(signaling_task_runner), + std::move(pc), std::move(track_adapter_map), std::move(observer), + surface_receivers_only); +} + +WebRtcSetRemoteDescriptionObserverHandler:: + WebRtcSetRemoteDescriptionObserverHandler( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner, + scoped_refptr<webrtc::PeerConnectionInterface> pc, + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, + scoped_refptr<WebRtcSetDescriptionObserver> observer, + bool surface_receivers_only) + : handler_impl_(new WebRtcSetDescriptionObserverHandlerImpl( + std::move(main_task_runner), + std::move(signaling_task_runner), + std::move(pc), + std::move(track_adapter_map), + std::move(observer), + surface_receivers_only)) {} + +WebRtcSetRemoteDescriptionObserverHandler:: + ~WebRtcSetRemoteDescriptionObserverHandler() = default; + +void WebRtcSetRemoteDescriptionObserverHandler::OnSetRemoteDescriptionComplete( + webrtc::RTCError error) { + handler_impl_->OnSetDescriptionComplete(std::move(error)); +} + +} // namespace content diff --git a/chromium/content/renderer/media/webrtc/webrtc_set_description_observer.h b/chromium/content/renderer/media/webrtc/webrtc_set_description_observer.h new file mode 100644 index 00000000000..41e84950259 --- /dev/null +++ b/chromium/content/renderer/media/webrtc/webrtc_set_description_observer.h @@ -0,0 +1,186 @@ +// Copyright (c) 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_SET_DESCRIPTION_OBSERVER_H_ +#define CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_SET_DESCRIPTION_OBSERVER_H_ + +#include <vector> + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_refptr.h" +#include "base/single_thread_task_runner.h" +#include "base/threading/thread_task_runner_handle.h" +#include "content/common/content_export.h" +#include "content/renderer/media/webrtc/rtc_peer_connection_handler.h" +#include "content/renderer/media/webrtc/rtc_rtp_receiver.h" +#include "content/renderer/media/webrtc/rtc_rtp_sender.h" +#include "content/renderer/media/webrtc/rtc_rtp_transceiver.h" +#include "content/renderer/media/webrtc/transceiver_state_surfacer.h" +#include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h" +#include "third_party/webrtc/api/jsep.h" +#include "third_party/webrtc/api/peerconnectioninterface.h" +#include "third_party/webrtc/api/rtcerror.h" +#include "third_party/webrtc/api/rtpreceiverinterface.h" +#include "third_party/webrtc/api/setremotedescriptionobserverinterface.h" +#include "third_party/webrtc/rtc_base/refcount.h" +#include "third_party/webrtc/rtc_base/refcountedobject.h" +#include "third_party/webrtc/rtc_base/scoped_ref_ptr.h" + +namespace content { + +// The content layer correspondent of the setLocalDescription() observer +// (webrtc::SetSessionDescriptionObserver) and setRemoteDescription() observer +// (webrtc::SetRemoteDescriptionObserverInterface). The implementation should +// process the state changes of the Set[Local/Remote]Description() by inspecting +// the updated States. +class CONTENT_EXPORT WebRtcSetDescriptionObserver + : public base::RefCountedThreadSafe<WebRtcSetDescriptionObserver> { + public: + // The states as they were when the operation finished on the webrtc signaling + // thread. Note that other operations may have occurred while jumping back to + // the main thread, but these must be handled separately. + struct CONTENT_EXPORT States { + States(); + States(States&& other); + ~States(); + + States& operator=(States&& other); + + webrtc::PeerConnectionInterface::SignalingState signaling_state; + std::vector<RtpTransceiverState> transceiver_states; + + DISALLOW_COPY_AND_ASSIGN(States); + }; + + WebRtcSetDescriptionObserver(); + + // Invoked in a PostTask() on the main thread after the SetLocalDescription() + // or SetRemoteDescription() operation completed on the webrtc signaling + // thread. + virtual void OnSetDescriptionComplete(webrtc::RTCError error, + States states) = 0; + + protected: + friend class base::RefCountedThreadSafe<WebRtcSetDescriptionObserver>; + virtual ~WebRtcSetDescriptionObserver(); + + DISALLOW_COPY_AND_ASSIGN(WebRtcSetDescriptionObserver); +}; + +// Takes care of surfacing WebRtcSetDescriptionObserver::State information from +// the webrtc signaling thread to the main thread. With the state information +// obtained, invokes |observer_|'s +// WebRtcSetDescriptionObserver::OnSetDescriptionComplete() on the main thread. +// +// This implements the behavior +// of both WebRtcSetLocalDescriptionObserverHandler and +// WebRtcSetRemoteDescriptionObserverHandler, but these are put in different +// classes because local and remote description observers have different +// interfaces in webrtc. +class CONTENT_EXPORT WebRtcSetDescriptionObserverHandlerImpl + : public base::RefCountedThreadSafe< + WebRtcSetDescriptionObserverHandlerImpl> { + public: + WebRtcSetDescriptionObserverHandlerImpl( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner, + scoped_refptr<webrtc::PeerConnectionInterface> pc, + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, + scoped_refptr<WebRtcSetDescriptionObserver> observer, + bool surface_receivers_only); + + // Must be called on the webrtc signaling thread internally by the handler + // when the Set[Local/Remote]Description() operation finishes. + void OnSetDescriptionComplete(webrtc::RTCError error); + + private: + friend class base::RefCountedThreadSafe< + WebRtcSetDescriptionObserverHandlerImpl>; + virtual ~WebRtcSetDescriptionObserverHandlerImpl(); + + void OnSetDescriptionCompleteOnMainThread( + webrtc::RTCError error, + webrtc::PeerConnectionInterface::SignalingState signaling_state, + TransceiverStateSurfacer transceiver_state_surfacer); + + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner_; + scoped_refptr<webrtc::PeerConnectionInterface> pc_; + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map_; + scoped_refptr<WebRtcSetDescriptionObserver> observer_; + bool surface_receivers_only_; + + DISALLOW_COPY_AND_ASSIGN(WebRtcSetDescriptionObserverHandlerImpl); +}; + +// An implementation of webrtc::SetSessionDescriptionObserver for performing the +// operations of WebRtcSetDescriptionObserverHandlerImpl. +class CONTENT_EXPORT WebRtcSetLocalDescriptionObserverHandler + : public webrtc::SetSessionDescriptionObserver { + public: + static scoped_refptr<WebRtcSetLocalDescriptionObserverHandler> Create( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner, + scoped_refptr<webrtc::PeerConnectionInterface> pc, + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, + scoped_refptr<WebRtcSetDescriptionObserver> observer, + bool surface_receivers_only); + + // webrtc::SetSessionDescriptionObserver implementation. Implementation calls + // WebRtcSetDescriptionObserverHandlerImpl::OnSetDescriptionComplete(). + void OnSuccess() override; + void OnFailure(webrtc::RTCError error) override; + + protected: + WebRtcSetLocalDescriptionObserverHandler( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner, + scoped_refptr<webrtc::PeerConnectionInterface> pc, + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, + scoped_refptr<WebRtcSetDescriptionObserver> observer, + bool surface_receivers_only); + ~WebRtcSetLocalDescriptionObserverHandler() override; + + scoped_refptr<WebRtcSetDescriptionObserverHandlerImpl> handler_impl_; + + DISALLOW_COPY_AND_ASSIGN(WebRtcSetLocalDescriptionObserverHandler); +}; + +// An implementation of webrtc::SetRemoteDescriptionObserverInterface for +// performing the operations of WebRtcSetDescriptionObserverHandlerImpl. +class CONTENT_EXPORT WebRtcSetRemoteDescriptionObserverHandler + : public webrtc::SetRemoteDescriptionObserverInterface { + public: + static scoped_refptr<WebRtcSetRemoteDescriptionObserverHandler> Create( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner, + scoped_refptr<webrtc::PeerConnectionInterface> pc, + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, + scoped_refptr<WebRtcSetDescriptionObserver> observer, + bool surface_receivers_only); + + // webrtc::SetRemoteDescriptionObserverInterface implementation. + // Implementation calls + // WebRtcSetDescriptionObserverHandlerImpl::OnSetDescriptionComplete(). + void OnSetRemoteDescriptionComplete(webrtc::RTCError error) override; + + protected: + WebRtcSetRemoteDescriptionObserverHandler( + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner, + scoped_refptr<webrtc::PeerConnectionInterface> pc, + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map, + scoped_refptr<WebRtcSetDescriptionObserver> observer, + bool surface_receivers_only); + ~WebRtcSetRemoteDescriptionObserverHandler() override; + + scoped_refptr<WebRtcSetDescriptionObserverHandlerImpl> handler_impl_; + + DISALLOW_COPY_AND_ASSIGN(WebRtcSetRemoteDescriptionObserverHandler); +}; + +} // namespace content + +#endif // CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_SET_DESCRIPTION_OBSERVER_H_ diff --git a/chromium/content/renderer/media/webrtc/webrtc_set_remote_description_observer_unittest.cc b/chromium/content/renderer/media/webrtc/webrtc_set_description_observer_unittest.cc index 5b861458a11..c2f7dc786b0 100644 --- a/chromium/content/renderer/media/webrtc/webrtc_set_remote_description_observer_unittest.cc +++ b/chromium/content/renderer/media/webrtc/webrtc_set_description_observer_unittest.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/renderer/media/webrtc/webrtc_set_remote_description_observer.h" +#include "content/renderer/media/webrtc/webrtc_set_description_observer.h" #include <memory> #include <utility> @@ -16,7 +16,6 @@ #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" -#include "content/renderer/media/webrtc/webrtc_media_stream_adapter_map.h" #include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter_map.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" @@ -29,35 +28,41 @@ using ::testing::Return; namespace content { -class WebRtcSetRemoteDescriptionObserverForTest - : public WebRtcSetRemoteDescriptionObserver { +class WebRtcSetDescriptionObserverForTest + : public WebRtcSetDescriptionObserver { public: - bool called() const { return states_or_error_.has_value(); } - bool result() const { return states_or_error_->ok(); } + bool called() const { return called_; } - const WebRtcSetRemoteDescriptionObserver::States& states() const { - DCHECK(called() && result()); - return states_or_error_->value(); + const WebRtcSetDescriptionObserver::States& states() const { + DCHECK(called_); + return states_; } const webrtc::RTCError& error() const { - DCHECK(called() && !result()); - return states_or_error_->error(); + DCHECK(called_); + return error_; } - // WebRtcSetRemoteDescriptionObserver implementation. - void OnSetRemoteDescriptionComplete( - webrtc::RTCErrorOr<States> states_or_error) override { - states_or_error_ = std::move(states_or_error); + // WebRtcSetDescriptionObserver implementation. + void OnSetDescriptionComplete( + webrtc::RTCError error, + WebRtcSetDescriptionObserver::States states) override { + called_ = true; + error_ = std::move(error); + states_ = std::move(states); } private: - ~WebRtcSetRemoteDescriptionObserverForTest() override {} + ~WebRtcSetDescriptionObserverForTest() override {} - base::Optional<webrtc::RTCErrorOr<WebRtcSetRemoteDescriptionObserver::States>> - states_or_error_; - WebRtcSetRemoteDescriptionObserver::States states_; + bool called_ = false; + webrtc::RTCError error_; + WebRtcSetDescriptionObserver::States states_; }; +// TODO(hbos): This only tests WebRtcSetRemoteDescriptionObserverHandler, +// parameterize the test to make it also test +// WebRtcSetLocalDescriptionObserverHandler and with "surface_receivers_only" as +// both true and false. https://crbug.com/865006 class WebRtcSetRemoteDescriptionObserverHandlerTest : public ::testing::Test { public: void SetUp() override { @@ -66,14 +71,13 @@ class WebRtcSetRemoteDescriptionObserverHandlerTest : public ::testing::Test { new cricket::FakeMediaEngine()))); dependency_factory_.reset(new MockPeerConnectionDependencyFactory()); main_thread_ = blink::scheduler::GetSingleThreadTaskRunnerForTesting(); - scoped_refptr<WebRtcMediaStreamAdapterMap> map = - new WebRtcMediaStreamAdapterMap( - dependency_factory_.get(), main_thread_, - new WebRtcMediaStreamTrackAdapterMap(dependency_factory_.get(), - main_thread_)); - observer_ = new WebRtcSetRemoteDescriptionObserverForTest(); + scoped_refptr<WebRtcMediaStreamTrackAdapterMap> map = + new WebRtcMediaStreamTrackAdapterMap(dependency_factory_.get(), + main_thread_); + observer_ = new WebRtcSetDescriptionObserverForTest(); observer_handler_ = WebRtcSetRemoteDescriptionObserverHandler::Create( - main_thread_, pc_, map, observer_); + main_thread_, dependency_factory_->GetWebRtcSignalingThread(), pc_, map, + observer_, true /* surface_receivers_only*/); } void TearDown() override { blink::WebHeap::CollectAllGarbageForTesting(); } @@ -106,7 +110,7 @@ class WebRtcSetRemoteDescriptionObserverHandlerTest : public ::testing::Test { scoped_refptr<webrtc::MockPeerConnection> pc_; std::unique_ptr<MockPeerConnectionDependencyFactory> dependency_factory_; scoped_refptr<base::SingleThreadTaskRunner> main_thread_; - scoped_refptr<WebRtcSetRemoteDescriptionObserverForTest> observer_; + scoped_refptr<WebRtcSetDescriptionObserverForTest> observer_; scoped_refptr<WebRtcSetRemoteDescriptionObserverHandler> observer_handler_; std::vector<rtc::scoped_refptr<webrtc::RtpReceiverInterface>> receivers_; @@ -124,28 +128,65 @@ TEST_F(WebRtcSetRemoteDescriptionObserverHandlerTest, OnSuccess) { {added_stream.get()}))); receivers_.push_back(added_receiver.get()); + EXPECT_CALL(*pc_, signaling_state()) + .WillRepeatedly(Return(webrtc::PeerConnectionInterface::kStable)); EXPECT_CALL(*pc_, GetReceivers()).WillRepeatedly(Return(receivers_)); InvokeOnSetRemoteDescriptionComplete(webrtc::RTCError::OK()); EXPECT_TRUE(observer_->called()); - EXPECT_TRUE(observer_->result()); - - EXPECT_EQ(1u, observer_->states().receiver_states.size()); - const WebRtcReceiverState& receiver_state = - observer_->states().receiver_states[0]; - EXPECT_EQ(added_receiver, receiver_state.receiver); - EXPECT_EQ(added_track, receiver_state.track_ref->webrtc_track()); - EXPECT_EQ(1u, receiver_state.stream_refs.size()); - EXPECT_EQ(added_stream, - receiver_state.stream_refs[0]->adapter().webrtc_stream()); + EXPECT_TRUE(observer_->error().ok()); + + EXPECT_EQ(webrtc::PeerConnectionInterface::kStable, + observer_->states().signaling_state); + + EXPECT_EQ(1u, observer_->states().transceiver_states.size()); + const RtpTransceiverState& transceiver_state = + observer_->states().transceiver_states[0]; + EXPECT_FALSE(transceiver_state.sender_state()); + EXPECT_TRUE(transceiver_state.receiver_state()); + const RtpReceiverState& receiver_state = *transceiver_state.receiver_state(); + EXPECT_EQ(added_receiver, receiver_state.webrtc_receiver()); + EXPECT_EQ(added_track, receiver_state.track_ref()->webrtc_track()); + EXPECT_EQ(1u, receiver_state.stream_ids().size()); + EXPECT_EQ(added_stream->id(), receiver_state.stream_ids()[0]); } TEST_F(WebRtcSetRemoteDescriptionObserverHandlerTest, OnFailure) { - webrtc::RTCError error(webrtc::RTCErrorType::INVALID_PARAMETER, "Oh noes!"); - InvokeOnSetRemoteDescriptionComplete(std::move(error)); + scoped_refptr<MockWebRtcAudioTrack> added_track = + MockWebRtcAudioTrack::Create("added_track"); + scoped_refptr<webrtc::MediaStreamInterface> added_stream( + new rtc::RefCountedObject<MockMediaStream>("added_stream")); + scoped_refptr<webrtc::RtpReceiverInterface> added_receiver( + new rtc::RefCountedObject<FakeRtpReceiver>( + added_track.get(), + std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>( + {added_stream.get()}))); + + receivers_.push_back(added_receiver.get()); + EXPECT_CALL(*pc_, signaling_state()) + .WillRepeatedly(Return(webrtc::PeerConnectionInterface::kStable)); + EXPECT_CALL(*pc_, GetReceivers()).WillRepeatedly(Return(receivers_)); + + InvokeOnSetRemoteDescriptionComplete( + webrtc::RTCError(webrtc::RTCErrorType::INVALID_PARAMETER, "Oh noes!")); EXPECT_TRUE(observer_->called()); - EXPECT_FALSE(observer_->result()); + EXPECT_FALSE(observer_->error().ok()); EXPECT_EQ(std::string("Oh noes!"), observer_->error().message()); + + // Verify states were surfaced even though we got an error. + EXPECT_EQ(webrtc::PeerConnectionInterface::kStable, + observer_->states().signaling_state); + + EXPECT_EQ(1u, observer_->states().transceiver_states.size()); + const RtpTransceiverState& transceiver_state = + observer_->states().transceiver_states[0]; + EXPECT_FALSE(transceiver_state.sender_state()); + EXPECT_TRUE(transceiver_state.receiver_state()); + const RtpReceiverState& receiver_state = *transceiver_state.receiver_state(); + EXPECT_EQ(added_receiver, receiver_state.webrtc_receiver()); + EXPECT_EQ(added_track, receiver_state.track_ref()->webrtc_track()); + EXPECT_EQ(1u, receiver_state.stream_ids().size()); + EXPECT_EQ(added_stream->id(), receiver_state.stream_ids()[0]); } } // namespace content diff --git a/chromium/content/renderer/media/webrtc/webrtc_set_remote_description_observer.cc b/chromium/content/renderer/media/webrtc/webrtc_set_remote_description_observer.cc deleted file mode 100644 index 0ebb644548b..00000000000 --- a/chromium/content/renderer/media/webrtc/webrtc_set_remote_description_observer.cc +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (c) 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/media/webrtc/webrtc_set_remote_description_observer.h" - -#include "base/logging.h" - -namespace content { - -WebRtcReceiverState::WebRtcReceiverState( - scoped_refptr<webrtc::RtpReceiverInterface> receiver, - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref, - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_refs) - : receiver(std::move(receiver)), - track_ref(std::move(track_ref)), - stream_refs(std::move(stream_refs)) {} - -WebRtcReceiverState::WebRtcReceiverState(WebRtcReceiverState&& other) = default; - -WebRtcReceiverState& WebRtcReceiverState::operator=( - WebRtcReceiverState&& other) = default; - -WebRtcReceiverState::~WebRtcReceiverState() {} - -WebRtcSetRemoteDescriptionObserver::States::States() {} - -WebRtcSetRemoteDescriptionObserver::States::States(States&& other) - : receiver_states(std::move(other.receiver_states)) {} - -WebRtcSetRemoteDescriptionObserver::States::~States() {} - -WebRtcSetRemoteDescriptionObserver::States& -WebRtcSetRemoteDescriptionObserver::States::operator=(States&& other) { - receiver_states = std::move(other.receiver_states); - return *this; -} - -void WebRtcSetRemoteDescriptionObserver::States::CheckInvariants() const { - // Invariants: - // - All receiver states have a stream ref - // - All receiver states refer to streams that are non-null. - for (auto& receiver_state : receiver_states) { - for (auto& stream_ref : receiver_state.stream_refs) { - CHECK(stream_ref); - CHECK(!stream_ref->adapter().web_stream().IsNull()); - } - } -} - -WebRtcSetRemoteDescriptionObserver::WebRtcSetRemoteDescriptionObserver() {} - -WebRtcSetRemoteDescriptionObserver::~WebRtcSetRemoteDescriptionObserver() {} - -scoped_refptr<WebRtcSetRemoteDescriptionObserverHandler> -WebRtcSetRemoteDescriptionObserverHandler::Create( - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<webrtc::PeerConnectionInterface> pc, - scoped_refptr<WebRtcMediaStreamAdapterMap> stream_adapter_map, - scoped_refptr<WebRtcSetRemoteDescriptionObserver> observer) { - return new rtc::RefCountedObject<WebRtcSetRemoteDescriptionObserverHandler>( - std::move(main_thread), std::move(pc), std::move(stream_adapter_map), - std::move(observer)); -} - -WebRtcSetRemoteDescriptionObserverHandler:: - WebRtcSetRemoteDescriptionObserverHandler( - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<webrtc::PeerConnectionInterface> pc, - scoped_refptr<WebRtcMediaStreamAdapterMap> stream_adapter_map, - scoped_refptr<WebRtcSetRemoteDescriptionObserver> observer) - : main_thread_(std::move(main_thread)), - pc_(std::move(pc)), - stream_adapter_map_(std::move(stream_adapter_map)), - observer_(std::move(observer)) {} - -WebRtcSetRemoteDescriptionObserverHandler:: - ~WebRtcSetRemoteDescriptionObserverHandler() {} - -void WebRtcSetRemoteDescriptionObserverHandler::OnSetRemoteDescriptionComplete( - webrtc::RTCError error) { - CHECK(!main_thread_->BelongsToCurrentThread()); - - webrtc::RTCErrorOr<WebRtcSetRemoteDescriptionObserver::States> - states_or_error; - if (error.ok()) { - WebRtcSetRemoteDescriptionObserver::States states; - for (const auto& webrtc_receiver : pc_->GetReceivers()) { - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref = - track_adapter_map()->GetOrCreateRemoteTrackAdapter( - webrtc_receiver->track().get()); - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_refs; - for (const auto& stream : webrtc_receiver->streams()) { - stream_refs.push_back( - stream_adapter_map_->GetOrCreateRemoteStreamAdapter(stream.get())); - } - states.receiver_states.push_back(WebRtcReceiverState( - webrtc_receiver.get(), std::move(track_ref), std::move(stream_refs))); - } - states_or_error = std::move(states); - } else { - states_or_error = std::move(error); - } - main_thread_->PostTask( - FROM_HERE, base::BindOnce(&WebRtcSetRemoteDescriptionObserverHandler:: - OnSetRemoteDescriptionCompleteOnMainThread, - this, std::move(states_or_error))); -} - -void WebRtcSetRemoteDescriptionObserverHandler:: - OnSetRemoteDescriptionCompleteOnMainThread( - webrtc::RTCErrorOr<WebRtcSetRemoteDescriptionObserver::States> - states_or_error) { - CHECK(main_thread_->BelongsToCurrentThread()); - observer_->OnSetRemoteDescriptionComplete(std::move(states_or_error)); -} - -} // namespace content diff --git a/chromium/content/renderer/media/webrtc/webrtc_set_remote_description_observer.h b/chromium/content/renderer/media/webrtc/webrtc_set_remote_description_observer.h deleted file mode 100644 index 1102c415990..00000000000 --- a/chromium/content/renderer/media/webrtc/webrtc_set_remote_description_observer.h +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (c) 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_SET_REMOTE_DESCRIPTION_OBSERVER_H_ -#define CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_SET_REMOTE_DESCRIPTION_OBSERVER_H_ - -#include <vector> - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_refptr.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "content/common/content_export.h" -#include "content/renderer/media/webrtc/rtc_peer_connection_handler.h" -#include "content/renderer/media/webrtc/webrtc_media_stream_adapter_map.h" -#include "content/renderer/media/webrtc/webrtc_media_stream_track_adapter.h" -#include "third_party/webrtc/api/rtcerror.h" -#include "third_party/webrtc/api/rtpreceiverinterface.h" -#include "third_party/webrtc/api/setremotedescriptionobserverinterface.h" -#include "third_party/webrtc/rtc_base/refcount.h" -#include "third_party/webrtc/rtc_base/refcountedobject.h" -#include "third_party/webrtc/rtc_base/scoped_ref_ptr.h" - -namespace content { - -// Describes an instance of a receiver at the time the SRD call was completed. -// Because webrtc and content operate on different threads, webrtc objects may -// have been modified by the time we synchronize the receivers on the main -// thread, and members of this class should be inspected rather than members of -// |receiver|. -struct CONTENT_EXPORT WebRtcReceiverState { - WebRtcReceiverState( - scoped_refptr<webrtc::RtpReceiverInterface> receiver, - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref, - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_refs); - WebRtcReceiverState(WebRtcReceiverState&& other); - ~WebRtcReceiverState(); - - WebRtcReceiverState& operator=(WebRtcReceiverState&& other); - - scoped_refptr<webrtc::RtpReceiverInterface> receiver; - // The receiver's track when the SRD occurred. - std::unique_ptr<WebRtcMediaStreamTrackAdapterMap::AdapterRef> track_ref; - // The receiver's associated set of streams when the SRD occurred. - std::vector<std::unique_ptr<WebRtcMediaStreamAdapterMap::AdapterRef>> - stream_refs; - - DISALLOW_COPY_AND_ASSIGN(WebRtcReceiverState); -}; - -// The content layer correspondent of -// webrtc::SetRemoteDescriptionObserverInterface. It's an interface with -// callbacks for handling the result of SetRemoteDescription on the main thread. -// The implementation should process the state changes of the -// SetRemoteDescription by inspecting the updated States. -class CONTENT_EXPORT WebRtcSetRemoteDescriptionObserver - : public base::RefCountedThreadSafe<WebRtcSetRemoteDescriptionObserver> { - public: - // The relevant peer connection states as they were when the - // SetRemoteDescription call completed. This is used instead of inspecting the - // PeerConnection and other webrtc objects directly because they may have been - // modified before we reach the main thread. - struct CONTENT_EXPORT States { - States(); - States(States&& other); - ~States(); - - States& operator=(States&& other); - - // The receivers at the time of the event. - std::vector<WebRtcReceiverState> receiver_states; - // Check that the invariants for this structure hold. - void CheckInvariants() const; - - DISALLOW_COPY_AND_ASSIGN(States); - }; - - WebRtcSetRemoteDescriptionObserver(); - - // Invoked asynchronously on the main thread after the SetRemoteDescription - // completed on the webrtc signaling thread. - virtual void OnSetRemoteDescriptionComplete( - webrtc::RTCErrorOr<States> states_or_error) = 0; - - protected: - friend class base::RefCountedThreadSafe<WebRtcSetRemoteDescriptionObserver>; - virtual ~WebRtcSetRemoteDescriptionObserver(); - - DISALLOW_COPY_AND_ASSIGN(WebRtcSetRemoteDescriptionObserver); -}; - -// The glue between webrtc and content layer observers listening to -// SetRemoteDescription. This observer listens on the webrtc signaling thread -// for the result of SetRemoteDescription, copies any relevant webrtc peer -// connection states such that they can be processed on the main thread, and -// invokes the WebRtcSetRemoteDescriptionObserver on the main thread with the -// state changes. -class CONTENT_EXPORT WebRtcSetRemoteDescriptionObserverHandler - : public webrtc::SetRemoteDescriptionObserverInterface { - public: - static scoped_refptr<WebRtcSetRemoteDescriptionObserverHandler> Create( - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<webrtc::PeerConnectionInterface> pc, - scoped_refptr<WebRtcMediaStreamAdapterMap> stream_adapter_map, - scoped_refptr<WebRtcSetRemoteDescriptionObserver> observer); - - // webrtc::SetRemoteDescriptionObserverInterface implementation. - void OnSetRemoteDescriptionComplete(webrtc::RTCError error) override; - - protected: - WebRtcSetRemoteDescriptionObserverHandler( - scoped_refptr<base::SingleThreadTaskRunner> main_thread, - scoped_refptr<webrtc::PeerConnectionInterface> pc, - scoped_refptr<WebRtcMediaStreamAdapterMap> stream_adapter_map, - scoped_refptr<WebRtcSetRemoteDescriptionObserver> observer); - ~WebRtcSetRemoteDescriptionObserverHandler() override; - - private: - void OnSetRemoteDescriptionCompleteOnMainThread( - webrtc::RTCErrorOr<WebRtcSetRemoteDescriptionObserver::States> - states_or_error); - - scoped_refptr<WebRtcMediaStreamTrackAdapterMap> track_adapter_map() const { - return stream_adapter_map_->track_adapter_map(); - } - - scoped_refptr<base::SingleThreadTaskRunner> main_thread_; - scoped_refptr<webrtc::PeerConnectionInterface> pc_; - scoped_refptr<WebRtcMediaStreamAdapterMap> stream_adapter_map_; - scoped_refptr<WebRtcSetRemoteDescriptionObserver> observer_; - - DISALLOW_COPY_AND_ASSIGN(WebRtcSetRemoteDescriptionObserverHandler); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_SET_REMOTE_DESCRIPTION_OBSERVER_H_ diff --git a/chromium/content/renderer/media/webrtc/webrtc_util.h b/chromium/content/renderer/media/webrtc/webrtc_util.h new file mode 100644 index 00000000000..425c0ec9373 --- /dev/null +++ b/chromium/content/renderer/media/webrtc/webrtc_util.h @@ -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. + +#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_UTIL_H_ +#define CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_UTIL_H_ + +#include "base/optional.h" + +namespace content { + +template <typename OptionalT> +base::Optional<typename OptionalT::value_type> ToBaseOptional( + const OptionalT& optional) { + return optional ? base::make_optional(*optional) : base::nullopt; +} + +template <typename OptionalT> +absl::optional<typename OptionalT::value_type> ToAbslOptional( + const OptionalT& optional) { + return optional ? absl::make_optional(*optional) : absl::nullopt; +} + +template <typename OptionalT1, typename OptionalT2> +bool OptionalEquals(const OptionalT1& lhs, const OptionalT2& rhs) { + if (!lhs) + return !rhs; + if (!rhs) + return false; + return *lhs == *rhs; +} + +} // namespace content + +#endif // CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_UTIL_H_ 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 95357d45e98..57ae21ee241 100644 --- a/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc +++ b/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc @@ -209,7 +209,9 @@ bool WebRtcVideoCapturerAdapter::ShouldAdaptResolution() const { return true; } if (content_hint_ == - blink::WebMediaStreamTrack::ContentHintType::kVideoDetail) { + blink::WebMediaStreamTrack::ContentHintType::kVideoDetail || + content_hint_ == + blink::WebMediaStreamTrack::ContentHintType::kVideoText) { return false; } // Screencast does not adapt by default. diff --git a/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc b/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc index e076b3de238..ce1208152d4 100644 --- a/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc +++ b/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc @@ -117,44 +117,4 @@ TEST_F(WebRtcVideoCapturerAdapterTest, Scale720To640360) { TestSourceCropFrame(1280, 720, 1280, 720, 640, 360); } -TEST_F(WebRtcVideoCapturerAdapterTest, - NonScreencastAdapterDoesNotAdaptContentHintDetail) { - // Non-screenshare adapter should not adapt frames when detail is set. - TestContentHintResolutionAdaptation( - false, blink::WebMediaStreamTrack::ContentHintType::kNone, true, - blink::WebMediaStreamTrack::ContentHintType::kVideoDetail, false); -} - -TEST_F(WebRtcVideoCapturerAdapterTest, - NonScreencastAdapterAdaptsContentHintFluid) { - // Non-screenshare adapter should still adapt frames when motion is set. - TestContentHintResolutionAdaptation( - false, blink::WebMediaStreamTrack::ContentHintType::kNone, true, - blink::WebMediaStreamTrack::ContentHintType::kVideoMotion, true); -} - -TEST_F(WebRtcVideoCapturerAdapterTest, - ScreencastAdapterAdaptsContentHintFluid) { - // Screenshare adapter should adapt frames when motion is set. - TestContentHintResolutionAdaptation( - true, blink::WebMediaStreamTrack::ContentHintType::kNone, false, - blink::WebMediaStreamTrack::ContentHintType::kVideoMotion, true); -} - -TEST_F(WebRtcVideoCapturerAdapterTest, - ScreencastAdapterDoesNotAdaptContentHintDetailed) { - // Screenshare adapter should still not adapt frames when detail is set. - TestContentHintResolutionAdaptation( - true, blink::WebMediaStreamTrack::ContentHintType::kNone, false, - blink::WebMediaStreamTrack::ContentHintType::kVideoDetail, false); -} - -TEST_F(WebRtcVideoCapturerAdapterTest, RespectsConstructionTimeContentHint) { - // Non-screenshare adapter constructed with detail content hint should not - // adapt before SetContentHint is run. - TestContentHintResolutionAdaptation( - false, blink::WebMediaStreamTrack::ContentHintType::kVideoDetail, false, - blink::WebMediaStreamTrack::ContentHintType::kVideoMotion, true); -} - } // namespace content 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 a59e3c693ac..8087bd2db3b 100644 --- a/chromium/content/renderer/media/webrtc_local_audio_source_provider.cc +++ b/chromium/content/renderer/media/webrtc_local_audio_source_provider.cc @@ -8,7 +8,7 @@ #include "base/logging.h" #include "content/public/renderer/render_frame.h" -#include "content/renderer/media/audio_device_factory.h" +#include "content/renderer/media/audio/audio_device_factory.h" #include "media/base/audio_fifo.h" #include "media/base/audio_parameters.h" #include "third_party/blink/public/platform/web_audio_source_provider_client.h" diff --git a/chromium/content/renderer/media_capture_from_element/canvas_capture_handler.cc b/chromium/content/renderer/media_capture_from_element/canvas_capture_handler.cc index c2d9031674a..b6278f3162b 100644 --- a/chromium/content/renderer/media_capture_from_element/canvas_capture_handler.cc +++ b/chromium/content/renderer/media_capture_from_element/canvas_capture_handler.cc @@ -171,7 +171,7 @@ void CanvasCaptureHandler::SendNewFrame( (pixmap.alphaType() == kUnpremul_SkAlphaType || image->isOpaque())) { const base::TimeTicks timestamp = base::TimeTicks::Now(); SendFrame(ConvertToYUVFrame(image->isOpaque(), false, - static_cast<const uint8*>(pixmap.addr(0, 0)), + static_cast<const uint8_t*>(pixmap.addr(0, 0)), gfx::Size(pixmap.width(), pixmap.height()), pixmap.rowBytes(), pixmap.colorType()), timestamp); @@ -402,10 +402,10 @@ scoped_refptr<media::VideoFrame> CanvasCaptureHandler::ConvertToYUVFrame( return nullptr; } - int (*ConvertToI420)(const uint8* src_argb, int src_stride_argb, uint8* dst_y, - int dst_stride_y, uint8* dst_u, int dst_stride_u, - uint8* dst_v, int dst_stride_v, int width, int height) = - nullptr; + int (*ConvertToI420)(const uint8_t* src_argb, int src_stride_argb, + uint8_t* dst_y, int dst_stride_y, uint8_t* dst_u, + int dst_stride_u, uint8_t* dst_v, int dst_stride_v, + int width, int height) = nullptr; switch (source_color_type) { case kRGBA_8888_SkColorType: ConvertToI420 = libyuv::ABGRToI420; diff --git a/chromium/content/renderer/media_capture_from_element/html_video_element_capturer_source.cc b/chromium/content/renderer/media_capture_from_element/html_video_element_capturer_source.cc index de6e209743c..daffde0b484 100644 --- a/chromium/content/renderer/media_capture_from_element/html_video_element_capturer_source.cc +++ b/chromium/content/renderer/media_capture_from_element/html_video_element_capturer_source.cc @@ -151,13 +151,13 @@ void HtmlVideoElementCapturerSource::sendNewFrame() { media::PIXEL_FORMAT_I420, resolution, gfx::Rect(resolution), resolution, current_time - start_capture_time_); - const uint32 source_pixel_format = + const uint32_t source_pixel_format = (kN32_SkColorType == kRGBA_8888_SkColorType) ? libyuv::FOURCC_ABGR : libyuv::FOURCC_ARGB; if (frame && libyuv::ConvertToI420( - static_cast<uint8*>(bitmap_.getPixels()), bitmap_.computeByteSize(), + static_cast<uint8_t*>(bitmap_.getPixels()), bitmap_.computeByteSize(), frame->visible_data(media::VideoFrame::kYPlane), frame->stride(media::VideoFrame::kYPlane), frame->visible_data(media::VideoFrame::kUPlane), 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 528442cfc54..6a05c12fd96 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 @@ -37,7 +37,11 @@ class MockWebMediaPlayer : public blink::WebMediaPlayer, MockWebMediaPlayer() = default; ~MockWebMediaPlayer() override = default; - void Load(LoadType, const blink::WebMediaPlayerSource&, CORSMode) override {} + LoadTiming Load(LoadType, + const blink::WebMediaPlayerSource&, + CORSMode) override { + return LoadTiming::kImmediate; + } void Play() override {} void Pause() override {} void Seek(double seconds) override {} @@ -80,7 +84,7 @@ class MockWebMediaPlayer : public blink::WebMediaPlayer, size_t AudioDecodedByteCount() const override { return 0; } size_t VideoDecodedByteCount() const override { return 0; } - void Paint(blink::WebCanvas* canvas, + void Paint(cc::PaintCanvas* canvas, const blink::WebRect& paint_rectangle, cc::PaintFlags&, int already_uploaded_id, diff --git a/chromium/content/renderer/media_recorder/media_recorder_handler.cc b/chromium/content/renderer/media_recorder/media_recorder_handler.cc index f8e88b898de..8e5f6b142e2 100644 --- a/chromium/content/renderer/media_recorder/media_recorder_handler.cc +++ b/chromium/content/renderer/media_recorder/media_recorder_handler.cc @@ -13,7 +13,6 @@ #include "base/strings/string_tokenizer.h" #include "base/strings/string_util.h" #include "base/sys_info.h" -#include "content/child/scoped_web_callbacks.h" #include "content/renderer/media/stream/media_stream_audio_track.h" #include "content/renderer/media/stream/media_stream_track.h" #include "content/renderer/media/webrtc/webrtc_uma_histograms.h" @@ -27,6 +26,7 @@ #include "media/base/video_frame.h" #include "media/muxers/webm_muxer.h" #include "third_party/blink/public/platform/modules/media_capabilities/web_media_configuration.h" +#include "third_party/blink/public/platform/scoped_web_callbacks.h" #include "third_party/blink/public/platform/web_media_recorder_handler_client.h" #include "third_party/blink/public/platform/web_media_stream_source.h" #include "third_party/blink/public/platform/web_string.h" @@ -123,8 +123,8 @@ MediaRecorderHandler::MediaRecorderHandler( scoped_refptr<base::SingleThreadTaskRunner> task_runner) : video_bits_per_second_(0), audio_bits_per_second_(0), - video_codec_id_(VideoTrackRecorder::CodecId::VP8), - audio_codec_id_(AudioTrackRecorder::CodecId::OPUS), + video_codec_id_(VideoTrackRecorder::CodecId::LAST), + audio_codec_id_(AudioTrackRecorder::CodecId::LAST), recording_(false), client_(nullptr), task_runner_(std::move(task_runner)), @@ -236,8 +236,8 @@ bool MediaRecorderHandler::Start(int timeslice) { timeslice_ = TimeDelta::FromMilliseconds(timeslice); slice_origin_timestamp_ = TimeTicks::Now(); - media_stream_.VideoTracks(video_tracks_); - media_stream_.AudioTracks(audio_tracks_); + video_tracks_ = media_stream_.VideoTracks(); + audio_tracks_ = media_stream_.AudioTracks(); if (video_tracks_.IsEmpty() && audio_tracks_.IsEmpty()) { LOG(WARNING) << __func__ << ": no media tracks."; @@ -350,9 +350,8 @@ void MediaRecorderHandler::EncodingInfo( DCHECK(configuration.video_configuration || configuration.audio_configuration); - ScopedWebCallbacks<WebMediaCapabilitiesQueryCallbacks> scoped_callbacks = - make_scoped_web_callbacks(callbacks.release(), - base::Bind(&OnEncodingInfoError)); + auto scoped_callbacks = blink::MakeScopedWebCallbacks( + std::move(callbacks), base::BindOnce(&OnEncodingInfoError)); std::unique_ptr<blink::WebMediaCapabilitiesInfo> info( new blink::WebMediaCapabilitiesInfo()); @@ -400,6 +399,72 @@ void MediaRecorderHandler::EncodingInfo( scoped_callbacks.PassCallbacks()->OnSuccess(std::move(info)); } +blink::WebString MediaRecorderHandler::ActualMimeType() { + DCHECK(main_render_thread_checker_.CalledOnValidThread()); + DCHECK(client_) << __func__ << " should be called after Initialize()"; + + const bool has_video_tracks = !media_stream_.VideoTracks().empty(); + const bool has_audio_tracks = !media_stream_.AudioTracks().empty(); + if (!has_video_tracks && !has_audio_tracks) + return blink::WebString(); + + std::string mime_type; + if (!has_video_tracks && has_audio_tracks) { + mime_type.append("audio/webm;codecs="); + } else { + switch (video_codec_id_) { + case VideoTrackRecorder::CodecId::VP8: + case VideoTrackRecorder::CodecId::VP9: + mime_type.append("video/webm;codecs="); + break; +#if BUILDFLAG(RTC_USE_H264) + case VideoTrackRecorder::CodecId::H264: + mime_type.append("video/x-matroska;codecs="); + break; +#endif + case VideoTrackRecorder::CodecId::LAST: + // Do nothing. + break; + } + } + if (has_video_tracks) { + switch (video_codec_id_) { + case VideoTrackRecorder::CodecId::VP8: + mime_type.append("vp8"); + break; + case VideoTrackRecorder::CodecId::VP9: + mime_type.append("vp9"); + break; +#if BUILDFLAG(RTC_USE_H264) + case VideoTrackRecorder::CodecId::H264: + mime_type.append("avc1"); + break; +#endif + case VideoTrackRecorder::CodecId::LAST: + DCHECK_NE(audio_codec_id_, AudioTrackRecorder::CodecId::LAST); + } + } + if (has_video_tracks && has_audio_tracks) { + if (video_codec_id_ != VideoTrackRecorder::CodecId::LAST && + audio_codec_id_ != AudioTrackRecorder::CodecId::LAST) { + mime_type.append(","); + } + } + if (has_audio_tracks) { + switch (audio_codec_id_) { + case AudioTrackRecorder::CodecId::OPUS: + mime_type.append("opus"); + break; + case AudioTrackRecorder::CodecId::PCM: + mime_type.append("pcm"); + break; + case AudioTrackRecorder::CodecId::LAST: + DCHECK_NE(video_codec_id_, VideoTrackRecorder::CodecId::LAST); + } + } + return blink::WebString::FromUTF8(mime_type); +} + void MediaRecorderHandler::OnEncodedVideo( const media::WebmMuxer::VideoParameters& params, std::unique_ptr<std::string> encoded_data, @@ -463,8 +528,8 @@ bool MediaRecorderHandler::UpdateTracksAndCheckIfChanged() { DCHECK(main_render_thread_checker_.CalledOnValidThread()); blink::WebVector<blink::WebMediaStreamTrack> video_tracks, audio_tracks; - media_stream_.VideoTracks(video_tracks); - media_stream_.AudioTracks(audio_tracks); + video_tracks = media_stream_.VideoTracks(); + audio_tracks = media_stream_.AudioTracks(); bool video_tracks_changed = video_tracks_.size() != video_tracks.size(); bool audio_tracks_changed = audio_tracks_.size() != audio_tracks.size(); diff --git a/chromium/content/renderer/media_recorder/media_recorder_handler.h b/chromium/content/renderer/media_recorder/media_recorder_handler.h index bffe011b465..59381c54f30 100644 --- a/chromium/content/renderer/media_recorder/media_recorder_handler.h +++ b/chromium/content/renderer/media_recorder/media_recorder_handler.h @@ -67,6 +67,7 @@ class CONTENT_EXPORT MediaRecorderHandler final void EncodingInfo( const blink::WebMediaConfiguration& configuration, std::unique_ptr<blink::WebMediaCapabilitiesQueryCallbacks> cb) override; + blink::WebString ActualMimeType() override; private: friend class MediaRecorderHandlerTest; diff --git a/chromium/content/renderer/media_recorder/media_recorder_handler_unittest.cc b/chromium/content/renderer/media_recorder/media_recorder_handler_unittest.cc index 82975448f1e..06d61dd66bf 100644 --- a/chromium/content/renderer/media_recorder/media_recorder_handler_unittest.cc +++ b/chromium/content/renderer/media_recorder/media_recorder_handler_unittest.cc @@ -65,11 +65,12 @@ static const MediaRecorderTestParams kMediaRecorderTestParams[] = { {true, false, "video/webm", "vp8", true}, {true, false, "video/webm", "vp9", true}, #if BUILDFLAG(RTC_USE_H264) - {true, false, "video/webm", "h264", false}, + {true, false, "video/x-matroska", "avc1", false}, #endif {false, true, "audio/webm", "opus", true}, {false, true, "audio/webm", "", true}, // Should default to opus. {false, true, "audio/webm", "pcm", true}, + {true, true, "video/webm", "vp9,opus", true}, }; class MediaRecorderHandlerTest : public TestWithParam<MediaRecorderTestParams>, @@ -429,6 +430,29 @@ TEST_P(MediaRecorderHandlerTest, WebmMuxerErrorWhileEncoding) { run_loop.Run(); } + // Expect a last call on destruction, with size 0 and |lastInSlice| true. + EXPECT_CALL(*this, WriteData(nullptr, 0, true, _)).Times(1); + media_recorder_handler_.reset(); +} + +// Checks the ActualMimeType() versus the expected. +TEST_P(MediaRecorderHandlerTest, ActualMimeType) { + AddTracks(); + const WebString mime_type(WebString::FromASCII(GetParam().mime_type)); + const WebString codecs(WebString::FromASCII(GetParam().codecs)); + EXPECT_TRUE(media_recorder_handler_->Initialize(this, registry_.test_stream(), + mime_type, codecs, 0, 0)); + + std::string actual_mime_type(GetParam().mime_type); + actual_mime_type.append(";codecs="); + if (strlen(GetParam().codecs) != 0u) + actual_mime_type.append(GetParam().codecs); + else if (GetParam().has_video) + actual_mime_type.append("vp8"); + else if (GetParam().has_audio) + actual_mime_type.append("opus"); + + EXPECT_EQ(media_recorder_handler_->ActualMimeType().Utf8(), actual_mime_type); // Expect a last call on destruction, with size 0 and |lastInSlice| true. EXPECT_CALL(*this, WriteData(nullptr, 0, true, _)).Times(1); diff --git a/chromium/content/renderer/media_recorder/vea_encoder.cc b/chromium/content/renderer/media_recorder/vea_encoder.cc index 6ace838170a..269eabb0069 100644 --- a/chromium/content/renderer/media_recorder/vea_encoder.cc +++ b/chromium/content/renderer/media_recorder/vea_encoder.cc @@ -100,14 +100,14 @@ void VEAEncoder::RequireBitstreamBuffers(unsigned int /*input_count*/, UseOutputBitstreamBufferId(i); } -void VEAEncoder::BitstreamBufferReady(int32_t bitstream_buffer_id, - size_t payload_size, - bool keyframe, - base::TimeDelta timestamp) { +void VEAEncoder::BitstreamBufferReady( + int32_t bitstream_buffer_id, + const media::BitstreamBufferMetadata& metadata) { DVLOG(3) << __func__; DCHECK(encoding_task_runner_->BelongsToCurrentThread()); - num_frames_after_keyframe_ = keyframe ? 0 : num_frames_after_keyframe_ + 1; + num_frames_after_keyframe_ = + metadata.key_frame ? 0 : num_frames_after_keyframe_ + 1; if (num_frames_after_keyframe_ > kMaxKeyframeInterval) { force_next_frame_to_be_keyframe_ = true; num_frames_after_keyframe_ = 0; @@ -116,7 +116,8 @@ void VEAEncoder::BitstreamBufferReady(int32_t bitstream_buffer_id, 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()), payload_size); + data->append(reinterpret_cast<char*>(output_buffer->memory()), + metadata.payload_size_bytes); const auto front_frame = frames_in_encode_.front(); frames_in_encode_.pop(); @@ -124,7 +125,7 @@ void VEAEncoder::BitstreamBufferReady(int32_t bitstream_buffer_id, FROM_HERE, base::BindOnce(OnFrameEncodeCompleted, on_encoded_video_callback_, front_frame.first, std::move(data), nullptr, - front_frame.second, keyframe)); + front_frame.second, metadata.key_frame)); UseOutputBitstreamBufferId(bitstream_buffer_id); } diff --git a/chromium/content/renderer/media_recorder/vea_encoder.h b/chromium/content/renderer/media_recorder/vea_encoder.h index e4b64fa70b7..3d06e593f91 100644 --- a/chromium/content/renderer/media_recorder/vea_encoder.h +++ b/chromium/content/renderer/media_recorder/vea_encoder.h @@ -41,10 +41,9 @@ class VEAEncoder final : public VideoTrackRecorder::Encoder, void RequireBitstreamBuffers(unsigned int input_count, const gfx::Size& input_coded_size, size_t output_buffer_size) override; - void BitstreamBufferReady(int32_t bitstream_buffer_id, - size_t payload_size, - bool key_frame, - base::TimeDelta timestamp) override; + void BitstreamBufferReady( + int32_t bitstream_buffer_id, + const media::BitstreamBufferMetadata& metadata) override; void NotifyError(media::VideoEncodeAccelerator::Error error) override; private: diff --git a/chromium/content/renderer/media_recorder/video_track_recorder.cc b/chromium/content/renderer/media_recorder/video_track_recorder.cc index c1d672c52d6..c2e59536231 100644 --- a/chromium/content/renderer/media_recorder/video_track_recorder.cc +++ b/chromium/content/renderer/media_recorder/video_track_recorder.cc @@ -296,10 +296,10 @@ void VideoTrackRecorder::Encoder::RetrieveFrameOnMainThread( return; } - const uint32 source_pixel_format = + const uint32_t source_pixel_format = (kN32_SkColorType == kRGBA_8888_SkColorType) ? libyuv::FOURCC_ABGR : libyuv::FOURCC_ARGB; - if (libyuv::ConvertToI420(static_cast<uint8*>(pixmap.writable_addr()), + if (libyuv::ConvertToI420(static_cast<uint8_t*>(pixmap.writable_addr()), pixmap.computeByteSize(), frame->visible_data(media::VideoFrame::kYPlane), frame->stride(media::VideoFrame::kYPlane), diff --git a/chromium/content/renderer/mouse_lock_dispatcher_browsertest.cc b/chromium/content/renderer/mouse_lock_dispatcher_browsertest.cc index 8b26b1cf0ce..8e046ca1fd6 100644 --- a/chromium/content/renderer/mouse_lock_dispatcher_browsertest.cc +++ b/chromium/content/renderer/mouse_lock_dispatcher_browsertest.cc @@ -45,7 +45,9 @@ class MouseLockDispatcherTest : public RenderViewTest { protected: RenderViewImpl* view() { return static_cast<RenderViewImpl*>(view_); } RenderWidget* widget() { return view()->GetWidget(); } - MouseLockDispatcher* dispatcher() { return view()->mouse_lock_dispatcher(); } + MouseLockDispatcher* dispatcher() { + return widget()->mouse_lock_dispatcher(); + } int route_id_; MockLockTarget* target_; MockLockTarget* alternate_target_; diff --git a/chromium/content/renderer/mus/BUILD.gn b/chromium/content/renderer/mus/BUILD.gn index 718ad1c98d1..3fbd6316fec 100644 --- a/chromium/content/renderer/mus/BUILD.gn +++ b/chromium/content/renderer/mus/BUILD.gn @@ -18,13 +18,17 @@ static_library("mus") { configs += [ "//content:content_implementation" ] + public_deps = [ + "//content/public/common:common_sources", + ] + deps = [ "//base", "//cc", + "//cc/mojo_embedder", "//components/viz/client", "//content/common", "//content/public/child:child_sources", - "//content/public/common:common_sources", "//media/mojo/interfaces:remoting", "//services/service_manager/public/cpp", "//services/ui/public/cpp", diff --git a/chromium/content/renderer/mus/mus_embedded_frame.cc b/chromium/content/renderer/mus/mus_embedded_frame.cc index 25c6d8d81a8..e0fdd265386 100644 --- a/chromium/content/renderer/mus/mus_embedded_frame.cc +++ b/chromium/content/renderer/mus/mus_embedded_frame.cc @@ -9,7 +9,7 @@ #include "base/command_line.h" #include "base/lazy_instance.h" #include "cc/base/switches.h" -#include "components/viz/client/client_layer_tree_frame_sink.h" +#include "cc/mojo_embedder/async_layer_tree_frame_sink.h" #include "components/viz/client/hit_test_data_provider.h" #include "components/viz/client/local_surface_id_provider.h" #include "content/renderer/mus/renderer_window_tree_client.h" diff --git a/chromium/content/renderer/mus/renderer_window_tree_client.cc b/chromium/content/renderer/mus/renderer_window_tree_client.cc index 77db183fc29..ee2d0c21ea8 100644 --- a/chromium/content/renderer/mus/renderer_window_tree_client.cc +++ b/chromium/content/renderer/mus/renderer_window_tree_client.cc @@ -6,10 +6,11 @@ #include <map> +#include "base/bind_helpers.h" #include "base/command_line.h" #include "base/lazy_instance.h" #include "cc/base/switches.h" -#include "components/viz/client/client_layer_tree_frame_sink.h" +#include "cc/mojo_embedder/async_layer_tree_frame_sink.h" #include "components/viz/client/hit_test_data_provider.h" #include "components/viz/client/hit_test_data_provider_draw_quad.h" #include "components/viz/client/local_surface_id_provider.h" @@ -31,7 +32,7 @@ base::LazyInstance<ConnectionMap>::Leaky g_connections = // static void RendererWindowTreeClient::CreateIfNecessary(int routing_id) { - if (!features::IsMashEnabled() || Get(routing_id)) + if (features::IsAshInBrowserProcess() || Get(routing_id)) return; RendererWindowTreeClient* connection = new RendererWindowTreeClient(routing_id); @@ -90,17 +91,18 @@ void RendererWindowTreeClient::SetVisible(bool visible) { void RendererWindowTreeClient::RequestLayerTreeFrameSink( scoped_refptr<viz::ContextProvider> context_provider, gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, - const LayerTreeFrameSinkCallback& callback) { + LayerTreeFrameSinkCallback callback) { DCHECK(pending_layer_tree_frame_sink_callback_.is_null()); if (tree_) { RequestLayerTreeFrameSinkInternal(std::move(context_provider), - gpu_memory_buffer_manager, callback); + gpu_memory_buffer_manager, + std::move(callback)); return; } pending_context_provider_ = std::move(context_provider); pending_gpu_memory_buffer_manager_ = gpu_memory_buffer_manager; - pending_layer_tree_frame_sink_callback_ = callback; + pending_layer_tree_frame_sink_callback_ = std::move(callback); } std::unique_ptr<MusEmbeddedFrame> @@ -126,14 +128,14 @@ RendererWindowTreeClient::~RendererWindowTreeClient() { void RendererWindowTreeClient::RequestLayerTreeFrameSinkInternal( scoped_refptr<viz::ContextProvider> context_provider, gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, - const LayerTreeFrameSinkCallback& callback) { + LayerTreeFrameSinkCallback callback) { viz::mojom::CompositorFrameSinkPtrInfo sink_info; viz::mojom::CompositorFrameSinkRequest sink_request = mojo::MakeRequest(&sink_info); viz::mojom::CompositorFrameSinkClientPtr client; viz::mojom::CompositorFrameSinkClientRequest client_request = mojo::MakeRequest(&client); - viz::ClientLayerTreeFrameSink::InitParams params; + cc::mojo_embedder::AsyncLayerTreeFrameSink::InitParams params; params.gpu_memory_buffer_manager = gpu_memory_buffer_manager; params.pipes.compositor_frame_sink_info = std::move(sink_info); params.pipes.client_request = std::move(client_request); @@ -145,12 +147,13 @@ void RendererWindowTreeClient::RequestLayerTreeFrameSinkInternal( std::make_unique<viz::HitTestDataProviderDrawQuad>( true /* should_ask_for_child_region */); } - auto frame_sink = std::make_unique<viz::ClientLayerTreeFrameSink>( - std::move(context_provider), nullptr /* worker_context_provider */, - ¶ms); + auto frame_sink = + std::make_unique<cc::mojo_embedder::AsyncLayerTreeFrameSink>( + std::move(context_provider), nullptr /* worker_context_provider */, + ¶ms); tree_->AttachCompositorFrameSink(root_window_id_, std::move(sink_request), std::move(client)); - callback.Run(std::move(frame_sink)); + std::move(callback).Run(std::move(frame_sink)); } void RendererWindowTreeClient::OnEmbeddedFrameDestroyed( @@ -207,9 +210,10 @@ void RendererWindowTreeClient::OnEmbed( } if (!pending_layer_tree_frame_sink_callback_.is_null()) { - RequestLayerTreeFrameSinkInternal(std::move(pending_context_provider_), - pending_gpu_memory_buffer_manager_, - pending_layer_tree_frame_sink_callback_); + RequestLayerTreeFrameSinkInternal( + std::move(pending_context_provider_), + pending_gpu_memory_buffer_manager_, + std::move(pending_layer_tree_frame_sink_callback_)); pending_context_provider_ = nullptr; pending_gpu_memory_buffer_manager_ = nullptr; pending_layer_tree_frame_sink_callback_.Reset(); @@ -233,7 +237,7 @@ void RendererWindowTreeClient::OnFrameSinkIdAllocated( const viz::FrameSinkId& frame_sink_id) { // When mus is not hosting viz FrameSinkIds come from the browser, so we // ignore them here. - if (!base::FeatureList::IsEnabled(features::kMash)) + if (features::IsAshInBrowserProcess()) return; for (MusEmbeddedFrame* embedded_frame : embedded_frames_) { @@ -334,7 +338,7 @@ void RendererWindowTreeClient::OnWindowCursorChanged(ui::Id window_id, void RendererWindowTreeClient::OnWindowSurfaceChanged( ui::Id window_id, const viz::SurfaceInfo& surface_info) { - DCHECK(base::FeatureList::IsEnabled(features::kMash)); + DCHECK(!features::IsAshInBrowserProcess()); for (MusEmbeddedFrame* embedded_frame : embedded_frames_) { if (embedded_frame->window_id_ == window_id) { embedded_frame->delegate_->OnMusEmbeddedFrameSurfaceChanged(surface_info); @@ -389,4 +393,7 @@ void RendererWindowTreeClient::GetWindowManager( NOTREACHED(); } +void RendererWindowTreeClient::GetScreenProviderObserver( + ui::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 a8e4e5d8368..5309e209efd 100644 --- a/chromium/content/renderer/mus/renderer_window_tree_client.h +++ b/chromium/content/renderer/mus/renderer_window_tree_client.h @@ -72,11 +72,11 @@ class RendererWindowTreeClient : public ui::mojom::WindowTreeClient, void SetVisible(bool visible); using LayerTreeFrameSinkCallback = - base::Callback<void(std::unique_ptr<cc::LayerTreeFrameSink>)>; + base::OnceCallback<void(std::unique_ptr<cc::LayerTreeFrameSink>)>; void RequestLayerTreeFrameSink( scoped_refptr<viz::ContextProvider> context_provider, gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, - const LayerTreeFrameSinkCallback& callback); + LayerTreeFrameSinkCallback callback); // Creates a new MusEmbeddedFrame. |token| is an UnguessableToken that was // registered for an embedding with mus (specifically ui::mojom::WindowTree). @@ -93,7 +93,7 @@ class RendererWindowTreeClient : public ui::mojom::WindowTreeClient, void RequestLayerTreeFrameSinkInternal( scoped_refptr<viz::ContextProvider> context_provider, gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager, - const LayerTreeFrameSinkCallback& callback); + LayerTreeFrameSinkCallback callback); // Called from ~MusEmbeddedFrame to cleanup up internall mapping. void OnEmbeddedFrameDestroyed(MusEmbeddedFrame* frame); @@ -210,6 +210,8 @@ class RendererWindowTreeClient : public ui::mojom::WindowTreeClient, void GetWindowManager( mojo::AssociatedInterfaceRequest<ui::mojom::WindowManager> internal) override; + void GetScreenProviderObserver( + ui::mojom::ScreenProviderObserverAssociatedRequest observer) override; const int routing_id_; ui::Id root_window_id_ = 0u; diff --git a/chromium/content/renderer/navigation_client.cc b/chromium/content/renderer/navigation_client.cc new file mode 100644 index 00000000000..209968171ba --- /dev/null +++ b/chromium/content/renderer/navigation_client.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/renderer/navigation_client.h" +#include "content/renderer/render_frame_impl.h" +#include "third_party/blink/public/platform/task_type.h" + +namespace content { + +NavigationClient::NavigationClient(RenderFrameImpl* render_frame) + : navigation_client_binding_(this), render_frame_(render_frame) {} + +NavigationClient::~NavigationClient() {} + +void NavigationClient::CommitNavigation( + const network::ResourceResponseHead& head, + const CommonNavigationParams& common_params, + const RequestNavigationParams& request_params, + network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints, + std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders, + base::Optional<std::vector<::content::mojom::TransferrableURLLoaderPtr>> + subresource_overrides, + mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info, + network::mojom::URLLoaderFactoryPtr prefetch_loader_factory, + const base::UnguessableToken& devtools_navigation_token) { + // 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 + // unexpectedly abort the ongoing navigation. Remove when the races are fixed. + ResetDisconnectionHandler(); + render_frame_->CommitNavigation( + head, common_params, request_params, + std::move(url_loader_client_endpoints), std::move(subresource_loaders), + std::move(subresource_overrides), + std::move(controller_service_worker_info), + std::move(prefetch_loader_factory), devtools_navigation_token, + mojom::FrameNavigationControl::CommitNavigationCallback()); +} + +void NavigationClient::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) { + 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()); +} + +void NavigationClient::Bind(mojom::NavigationClientAssociatedRequest request) { + navigation_client_binding_.Bind( + std::move(request), + render_frame_->GetTaskRunner(blink::TaskType::kInternalIPC)); + SetDisconnectionHandler(); +} + +void NavigationClient::SetDisconnectionHandler() { + navigation_client_binding_.set_connection_error_handler(base::BindOnce( + &NavigationClient::OnDroppedNavigation, base::Unretained(this))); +} + +void NavigationClient::ResetDisconnectionHandler() { + navigation_client_binding_.set_connection_error_handler(base::DoNothing()); +} + +void NavigationClient::OnDroppedNavigation() { + render_frame_->OnDroppedNavigation(); +} + +} // namespace content diff --git a/chromium/content/renderer/navigation_client.h b/chromium/content/renderer/navigation_client.h new file mode 100644 index 00000000000..3f535c5d1e8 --- /dev/null +++ b/chromium/content/renderer/navigation_client.h @@ -0,0 +1,56 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_RENDERER_NAVIGATION_CLIENT_H_ +#define CONTENT_RENDERER_NAVIGATION_CLIENT_H_ + +#include "content/common/navigation_client.mojom.h" +#include "mojo/public/cpp/bindings/associated_binding.h" + +namespace content { + +class RenderFrameImpl; + +class NavigationClient : mojom::NavigationClient { + public: + explicit NavigationClient(RenderFrameImpl* render_frame); + ~NavigationClient() override; + + // mojom::NavigationClient implementation: + void CommitNavigation( + const network::ResourceResponseHead& head, + const CommonNavigationParams& common_params, + const RequestNavigationParams& request_params, + network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints, + std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders, + base::Optional<std::vector<::content::mojom::TransferrableURLLoaderPtr>> + subresource_overrides, + mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info, + network::mojom::URLLoaderFactoryPtr prefetch_loader_factory, + const base::UnguessableToken& devtools_navigation_token) 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; + + void Bind(mojom::NavigationClientAssociatedRequest request); + + private: + // OnDroppedNavigation is bound from BeginNavigation till CommitNavigation. + // During this period, it is called when the interface pipe is closed from the + // browser side, leading to the ongoing navigation cancelation. + void OnDroppedNavigation(); + void SetDisconnectionHandler(); + void ResetDisconnectionHandler(); + + mojo::AssociatedBinding<mojom::NavigationClient> navigation_client_binding_; + RenderFrameImpl* render_frame_; +}; + +} // namespace content + +#endif // CONTENT_RENDERER_NAVIGATION_CLIENT_H_ diff --git a/chromium/content/renderer/navigation_state_impl.cc b/chromium/content/renderer/navigation_state_impl.cc index 597a8ac116c..5b9e23f3d26 100644 --- a/chromium/content/renderer/navigation_state_impl.cc +++ b/chromium/content/renderer/navigation_state_impl.cc @@ -7,20 +7,23 @@ namespace content { NavigationStateImpl::~NavigationStateImpl() { + RunCommitNavigationCallback(blink::mojom::CommitResult::Aborted); } NavigationStateImpl* NavigationStateImpl::CreateBrowserInitiated( const CommonNavigationParams& common_params, const RequestNavigationParams& request_params, - base::TimeTicks time_commit_requested) { + base::TimeTicks time_commit_requested, + mojom::FrameNavigationControl::CommitNavigationCallback callback) { return new NavigationStateImpl(common_params, request_params, - time_commit_requested, false); + time_commit_requested, false, + std::move(callback)); } NavigationStateImpl* NavigationStateImpl::CreateContentInitiated() { - return new NavigationStateImpl(CommonNavigationParams(), - RequestNavigationParams(), base::TimeTicks(), - true); + return new NavigationStateImpl( + CommonNavigationParams(), RequestNavigationParams(), base::TimeTicks(), + true, content::mojom::FrameNavigationControl::CommitNavigationCallback()); } ui::PageTransition NavigationStateImpl::GetTransitionType() { @@ -35,16 +38,25 @@ bool NavigationStateImpl::IsContentInitiated() { return is_content_initiated_; } +void NavigationStateImpl::RunCommitNavigationCallback( + blink::mojom::CommitResult result) { + if (commit_callback_) + std::move(commit_callback_).Run(result); +} + NavigationStateImpl::NavigationStateImpl( const CommonNavigationParams& common_params, const RequestNavigationParams& request_params, base::TimeTicks time_commit_requested, - bool is_content_initiated) + bool is_content_initiated, + mojom::FrameNavigationControl::CommitNavigationCallback callback) : request_committed_(false), was_within_same_document_(false), is_content_initiated_(is_content_initiated), common_params_(common_params), request_params_(request_params), - time_commit_requested_(time_commit_requested) {} + time_commit_requested_(time_commit_requested), + navigation_client_(nullptr), + commit_callback_(std::move(callback)) {} } // namespace content diff --git a/chromium/content/renderer/navigation_state_impl.h b/chromium/content/renderer/navigation_state_impl.h index 8f8f83cd5ce..9b3628b9591 100644 --- a/chromium/content/renderer/navigation_state_impl.h +++ b/chromium/content/renderer/navigation_state_impl.h @@ -8,8 +8,11 @@ #include <string> #include "base/macros.h" +#include "content/common/frame.mojom.h" #include "content/common/navigation_params.h" #include "content/public/renderer/navigation_state.h" +#include "content/renderer/navigation_client.h" +#include "third_party/blink/public/web/commit_result.mojom.h" namespace content { @@ -20,7 +23,8 @@ class CONTENT_EXPORT NavigationStateImpl : public NavigationState { static NavigationStateImpl* CreateBrowserInitiated( const CommonNavigationParams& common_params, const RequestNavigationParams& request_params, - base::TimeTicks time_commit_requested); + base::TimeTicks time_commit_requested, + mojom::FrameNavigationControl::CommitNavigationCallback callback); static NavigationStateImpl* CreateContentInitiated(); @@ -47,11 +51,26 @@ class CONTENT_EXPORT NavigationStateImpl : public NavigationState { return time_commit_requested_; } + // Only used when PerNavigationMojoInterface is enabled. + void set_navigation_client( + std::unique_ptr<NavigationClient> navigation_client_impl) { + navigation_client_ = std::move(navigation_client_impl); + } + + void set_navigation_start(const base::TimeTicks& navigation_start) { + common_params_.navigation_start = navigation_start; + } + + void RunCommitNavigationCallback(blink::mojom::CommitResult result); + private: - NavigationStateImpl(const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, - base::TimeTicks time_commit_requested, - bool is_content_initiated); + NavigationStateImpl( + const CommonNavigationParams& common_params, + const RequestNavigationParams& request_params, + base::TimeTicks time_commit_requested, + bool is_content_initiated, + content::mojom::FrameNavigationControl::CommitNavigationCallback + callback); bool request_committed_; bool was_within_same_document_; @@ -77,6 +96,15 @@ class CONTENT_EXPORT NavigationStateImpl : public NavigationState { // Time when RenderFrameImpl::CommitNavigation() is called. base::TimeTicks time_commit_requested_; + // The NavigationClient interface gives control over the navigation ongoing in + // the browser process. + // Only used when PerNavigationMojoInterface is enabled. + std::unique_ptr<NavigationClient> navigation_client_; + + // Used to notify whether a commit request from the browser process was + // successful or not. + mojom::FrameNavigationControl::CommitNavigationCallback commit_callback_; + DISALLOW_COPY_AND_ASSIGN(NavigationStateImpl); }; diff --git a/chromium/content/renderer/p2p/OWNERS b/chromium/content/renderer/p2p/OWNERS index cff66f72e13..70573c449d9 100644 --- a/chromium/content/renderer/p2p/OWNERS +++ b/chromium/content/renderer/p2p/OWNERS @@ -1,5 +1,4 @@ sergeyu@chromium.org juberti@chromium.org -deadbeef@chromium.org # COMPONENT: Blink>WebRTC diff --git a/chromium/content/renderer/pepper/audio_helper.cc b/chromium/content/renderer/pepper/audio_helper.cc index fd92532840e..81ed67b2d2b 100644 --- a/chromium/content/renderer/pepper/audio_helper.cc +++ b/chromium/content/renderer/pepper/audio_helper.cc @@ -15,7 +15,7 @@ namespace content { // AudioHelper ----------------------------------------------------------------- -AudioHelper::AudioHelper() : shared_memory_size_for_create_callback_(0) {} +AudioHelper::AudioHelper() {} AudioHelper::~AudioHelper() {} @@ -28,26 +28,22 @@ int32_t AudioHelper::GetSyncSocketImpl(int* sync_socket) { return PP_ERROR_FAILED; } -int32_t AudioHelper::GetSharedMemoryImpl(base::SharedMemory** shm, - uint32_t* shm_size) { - if (shared_memory_for_create_callback_) { - *shm = shared_memory_for_create_callback_.get(); - *shm_size = shared_memory_size_for_create_callback_; +int32_t AudioHelper::GetSharedMemoryImpl(base::UnsafeSharedMemoryRegion** shm) { + if (shared_memory_for_create_callback_.IsValid()) { + *shm = &shared_memory_for_create_callback_; return PP_OK; } return PP_ERROR_FAILED; } -void AudioHelper::StreamCreated(base::SharedMemoryHandle shared_memory_handle, - size_t shared_memory_size, - base::SyncSocket::Handle socket_handle) { +void AudioHelper::StreamCreated( + base::UnsafeSharedMemoryRegion shared_memory_region, + base::SyncSocket::Handle socket_handle) { if (TrackedCallback::IsPending(create_callback_)) { // Trusted side of proxy can specify a callback to receive handles. In // this case we don't need to map any data or start the thread since it // will be handled by the proxy. - shared_memory_for_create_callback_.reset( - new base::SharedMemory(shared_memory_handle, false)); - shared_memory_size_for_create_callback_ = shared_memory_size; + shared_memory_for_create_callback_ = std::move(shared_memory_region); socket_for_create_callback_.reset(new base::SyncSocket(socket_handle)); create_callback_->Run(PP_OK); @@ -60,7 +56,7 @@ void AudioHelper::StreamCreated(base::SharedMemoryHandle shared_memory_handle, // the I/O thread and back, but this extra complexity doesn't seem worth it // just to clean up these handles faster. } else { - OnSetStreamInfo(shared_memory_handle, shared_memory_size, socket_handle); + OnSetStreamInfo(std::move(shared_memory_region), socket_handle); } } diff --git a/chromium/content/renderer/pepper/audio_helper.h b/chromium/content/renderer/pepper/audio_helper.h index 1d4a543fdb9..d541169a20f 100644 --- a/chromium/content/renderer/pepper/audio_helper.h +++ b/chromium/content/renderer/pepper/audio_helper.h @@ -11,7 +11,7 @@ #include <memory> #include "base/macros.h" -#include "base/memory/shared_memory.h" +#include "base/memory/unsafe_shared_memory_region.h" #include "base/sync_socket.h" #include "ppapi/c/pp_completion_callback.h" #include "ppapi/shared_impl/resource.h" @@ -26,8 +26,7 @@ class AudioHelper { virtual ~AudioHelper(); // Called when the stream is created. - void StreamCreated(base::SharedMemoryHandle shared_memory_handle, - size_t shared_memory_size_, + void StreamCreated(base::UnsafeSharedMemoryRegion shared_memory_region, base::SyncSocket::Handle socket); void SetCreateCallback(scoped_refptr<ppapi::TrackedCallback> create_callback); @@ -37,12 +36,12 @@ class AudioHelper { // To be called by implementations of |PPB_Audio_API|/|PPB_AudioInput_API|. int32_t GetSyncSocketImpl(int* sync_socket); - int32_t GetSharedMemoryImpl(base::SharedMemory** shm, uint32_t* shm_size); + int32_t GetSharedMemoryImpl(base::UnsafeSharedMemoryRegion** shm); // To be implemented by subclasses to call their |SetStreamInfo()|. - virtual void OnSetStreamInfo(base::SharedMemoryHandle shared_memory_handle, - size_t shared_memory_size, - base::SyncSocket::Handle socket_handle) = 0; + virtual void OnSetStreamInfo( + base::UnsafeSharedMemoryRegion shared_memory_region, + base::SyncSocket::Handle socket_handle) = 0; private: scoped_refptr<ppapi::TrackedCallback> create_callback_; @@ -51,8 +50,7 @@ class AudioHelper { // querying from the callback. The proxy uses this to get the handles to the // other process instead of mapping them in the renderer. These will be // invalid all other times. - std::unique_ptr<base::SharedMemory> shared_memory_for_create_callback_; - size_t shared_memory_size_for_create_callback_; + base::UnsafeSharedMemoryRegion shared_memory_for_create_callback_; std::unique_ptr<base::SyncSocket> socket_for_create_callback_; DISALLOW_COPY_AND_ASSIGN(AudioHelper); diff --git a/chromium/content/renderer/pepper/mock_renderer_ppapi_host.cc b/chromium/content/renderer/pepper/mock_renderer_ppapi_host.cc index ad9a0df001e..80e59655486 100644 --- a/chromium/content/renderer/pepper/mock_renderer_ppapi_host.cc +++ b/chromium/content/renderer/pepper/mock_renderer_ppapi_host.cc @@ -85,6 +85,20 @@ MockRendererPpapiHost::ShareSharedMemoryHandleWithRemote( return base::SharedMemoryHandle(); } +base::UnsafeSharedMemoryRegion +MockRendererPpapiHost::ShareUnsafeSharedMemoryRegionWithRemote( + const base::UnsafeSharedMemoryRegion& region) { + NOTIMPLEMENTED(); + return base::UnsafeSharedMemoryRegion(); +} + +base::ReadOnlySharedMemoryRegion +MockRendererPpapiHost::ShareReadOnlySharedMemoryRegionWithRemote( + const base::ReadOnlySharedMemoryRegion& region) { + NOTIMPLEMENTED(); + return base::ReadOnlySharedMemoryRegion(); +} + bool MockRendererPpapiHost::IsRunningInProcess() const { return false; } std::string MockRendererPpapiHost::GetPluginName() const { diff --git a/chromium/content/renderer/pepper/mock_renderer_ppapi_host.h b/chromium/content/renderer/pepper/mock_renderer_ppapi_host.h index 375c2127a3f..fedbf7c9e86 100644 --- a/chromium/content/renderer/pepper/mock_renderer_ppapi_host.h +++ b/chromium/content/renderer/pepper/mock_renderer_ppapi_host.h @@ -48,6 +48,10 @@ class MockRendererPpapiHost : public RendererPpapiHost { bool should_close_source) override; base::SharedMemoryHandle ShareSharedMemoryHandleWithRemote( const base::SharedMemoryHandle& handle) override; + base::UnsafeSharedMemoryRegion ShareUnsafeSharedMemoryRegionWithRemote( + const base::UnsafeSharedMemoryRegion& region) override; + base::ReadOnlySharedMemoryRegion ShareReadOnlySharedMemoryRegionWithRemote( + const base::ReadOnlySharedMemoryRegion& region) override; bool IsRunningInProcess() const override; std::string GetPluginName() const override; void SetToExternalPluginHost() override; diff --git a/chromium/content/renderer/pepper/pepper_audio_input_host.cc b/chromium/content/renderer/pepper/pepper_audio_input_host.cc index a722013fb17..08f47d7ce5d 100644 --- a/chromium/content/renderer/pepper/pepper_audio_input_host.cc +++ b/chromium/content/renderer/pepper/pepper_audio_input_host.cc @@ -52,14 +52,13 @@ int32_t PepperAudioInputHost::OnResourceMessageReceived( } void PepperAudioInputHost::StreamCreated( - base::SharedMemoryHandle shared_memory_handle, - size_t shared_memory_size, + base::ReadOnlySharedMemoryRegion shared_memory_region, base::SyncSocket::Handle socket) { - OnOpenComplete(PP_OK, shared_memory_handle, shared_memory_size, socket); + OnOpenComplete(PP_OK, std::move(shared_memory_region), socket); } void PepperAudioInputHost::StreamCreationFailed() { - OnOpenComplete(PP_ERROR_FAILED, base::SharedMemoryHandle(), 0, + OnOpenComplete(PP_ERROR_FAILED, base::ReadOnlySharedMemoryRegion(), base::SyncSocket::kInvalidHandle); } @@ -113,12 +112,10 @@ int32_t PepperAudioInputHost::OnClose( void PepperAudioInputHost::OnOpenComplete( int32_t result, - base::SharedMemoryHandle shared_memory_handle, - size_t shared_memory_size, + base::ReadOnlySharedMemoryRegion shared_memory_region, base::SyncSocket::Handle socket_handle) { // Make sure the handles are cleaned up. base::SyncSocket scoped_socket(socket_handle); - base::SharedMemory scoped_shared_memory(shared_memory_handle, false); if (!open_context_.is_valid()) { NOTREACHED(); @@ -128,17 +125,19 @@ void PepperAudioInputHost::OnOpenComplete( ppapi::proxy::SerializedHandle serialized_socket_handle( ppapi::proxy::SerializedHandle::SOCKET); ppapi::proxy::SerializedHandle serialized_shared_memory_handle( - ppapi::proxy::SerializedHandle::SHARED_MEMORY); + ppapi::proxy::SerializedHandle::SHARED_MEMORY_REGION); if (result == PP_OK) { IPC::PlatformFileForTransit temp_socket = IPC::InvalidPlatformFileForTransit(); - base::SharedMemoryHandle temp_shmem; - result = GetRemoteHandles( - scoped_socket, scoped_shared_memory, &temp_socket, &temp_shmem); + base::ReadOnlySharedMemoryRegion temp_shmem; + result = GetRemoteHandles(scoped_socket, shared_memory_region, &temp_socket, + &temp_shmem); serialized_socket_handle.set_socket(temp_socket); - serialized_shared_memory_handle.set_shmem(temp_shmem, shared_memory_size); + serialized_shared_memory_handle.set_shmem_region( + base::ReadOnlySharedMemoryRegion::TakeHandleForSerialization( + std::move(temp_shmem))); } // Send all the values, even on error. This simplifies some of our cleanup @@ -146,25 +145,25 @@ void PepperAudioInputHost::OnOpenComplete( // inconvenient to clean up. Our IPC code will automatically handle this for // us, as long as the remote side always closes the handles it receives, even // in the failure case. - open_context_.params.AppendHandle(serialized_socket_handle); - open_context_.params.AppendHandle(serialized_shared_memory_handle); + open_context_.params.AppendHandle(std::move(serialized_socket_handle)); + open_context_.params.AppendHandle(std::move(serialized_shared_memory_handle)); SendOpenReply(result); } int32_t PepperAudioInputHost::GetRemoteHandles( const base::SyncSocket& socket, - const base::SharedMemory& shared_memory, + const base::ReadOnlySharedMemoryRegion& shared_memory_region, IPC::PlatformFileForTransit* remote_socket_handle, - base::SharedMemoryHandle* remote_shared_memory_handle) { + base::ReadOnlySharedMemoryRegion* remote_shared_memory_region) { *remote_socket_handle = renderer_ppapi_host_->ShareHandleWithRemote(socket.handle(), false); if (*remote_socket_handle == IPC::InvalidPlatformFileForTransit()) return PP_ERROR_FAILED; - *remote_shared_memory_handle = - renderer_ppapi_host_->ShareSharedMemoryHandleWithRemote( - shared_memory.handle()); - if (!base::SharedMemory::IsHandleValid(*remote_shared_memory_handle)) + *remote_shared_memory_region = + renderer_ppapi_host_->ShareReadOnlySharedMemoryRegionWithRemote( + shared_memory_region); + if (!remote_shared_memory_region->IsValid()) return PP_ERROR_FAILED; return PP_OK; diff --git a/chromium/content/renderer/pepper/pepper_audio_input_host.h b/chromium/content/renderer/pepper/pepper_audio_input_host.h index 084ce33ea67..366d94a1b07 100644 --- a/chromium/content/renderer/pepper/pepper_audio_input_host.h +++ b/chromium/content/renderer/pepper/pepper_audio_input_host.h @@ -13,7 +13,7 @@ #include "base/compiler_specific.h" #include "base/macros.h" -#include "base/memory/shared_memory.h" +#include "base/memory/read_only_shared_memory_region.h" #include "base/sync_socket.h" #include "content/renderer/pepper/pepper_device_enumeration_host_helper.h" #include "ipc/ipc_platform_file.h" @@ -37,8 +37,7 @@ class PepperAudioInputHost : public ppapi::host::ResourceHost { ppapi::host::HostMessageContext* context) override; // Called when the stream is created. - void StreamCreated(base::SharedMemoryHandle shared_memory_handle, - size_t shared_memory_size, + void StreamCreated(base::ReadOnlySharedMemoryRegion shared_memory_region, base::SyncSocket::Handle socket); void StreamCreationFailed(); @@ -51,15 +50,14 @@ class PepperAudioInputHost : public ppapi::host::ResourceHost { int32_t OnClose(ppapi::host::HostMessageContext* context); void OnOpenComplete(int32_t result, - base::SharedMemoryHandle shared_memory_handle, - size_t shared_memory_size, + base::ReadOnlySharedMemoryRegion shared_memory_region, base::SyncSocket::Handle socket_handle); int32_t GetRemoteHandles( const base::SyncSocket& socket, - const base::SharedMemory& shared_memory, + const base::ReadOnlySharedMemoryRegion& shared_memory_region, IPC::PlatformFileForTransit* remote_socket_handle, - base::SharedMemoryHandle* remote_shared_memory_handle); + base::ReadOnlySharedMemoryRegion* remote_shared_memory_region); void Close(); diff --git a/chromium/content/renderer/pepper/pepper_audio_output_host.cc b/chromium/content/renderer/pepper/pepper_audio_output_host.cc index 9322bd0cc5f..49a4bb62c54 100644 --- a/chromium/content/renderer/pepper/pepper_audio_output_host.cc +++ b/chromium/content/renderer/pepper/pepper_audio_output_host.cc @@ -71,14 +71,13 @@ int32_t PepperAudioOutputHost::OnResourceMessageReceived( } void PepperAudioOutputHost::StreamCreated( - base::SharedMemoryHandle shared_memory_handle, - size_t shared_memory_size, + base::UnsafeSharedMemoryRegion shared_memory_region, base::SyncSocket::Handle socket) { - OnOpenComplete(PP_OK, shared_memory_handle, shared_memory_size, socket); + OnOpenComplete(PP_OK, std::move(shared_memory_region), socket); } void PepperAudioOutputHost::StreamCreationFailed() { - OnOpenComplete(PP_ERROR_FAILED, base::SharedMemoryHandle(), 0, + OnOpenComplete(PP_ERROR_FAILED, base::UnsafeSharedMemoryRegion(), base::SyncSocket::kInvalidHandle); } @@ -150,12 +149,10 @@ int32_t PepperAudioOutputHost::OnClose( void PepperAudioOutputHost::OnOpenComplete( int32_t result, - base::SharedMemoryHandle shared_memory_handle, - size_t shared_memory_size, + base::UnsafeSharedMemoryRegion shared_memory_region, base::SyncSocket::Handle socket_handle) { // Make sure the handles are cleaned up. base::SyncSocket scoped_socket(socket_handle); - base::SharedMemory scoped_shared_memory(shared_memory_handle, false); if (!open_context_.is_valid()) { NOTREACHED(); @@ -165,17 +162,19 @@ void PepperAudioOutputHost::OnOpenComplete( ppapi::proxy::SerializedHandle serialized_socket_handle( ppapi::proxy::SerializedHandle::SOCKET); ppapi::proxy::SerializedHandle serialized_shared_memory_handle( - ppapi::proxy::SerializedHandle::SHARED_MEMORY); + ppapi::proxy::SerializedHandle::SHARED_MEMORY_REGION); if (result == PP_OK) { IPC::PlatformFileForTransit temp_socket = IPC::InvalidPlatformFileForTransit(); - base::SharedMemoryHandle temp_shmem; - result = GetRemoteHandles(scoped_socket, scoped_shared_memory, &temp_socket, + base::UnsafeSharedMemoryRegion temp_shmem; + result = GetRemoteHandles(scoped_socket, shared_memory_region, &temp_socket, &temp_shmem); serialized_socket_handle.set_socket(temp_socket); - serialized_shared_memory_handle.set_shmem(temp_shmem, shared_memory_size); + serialized_shared_memory_handle.set_shmem_region( + base::UnsafeSharedMemoryRegion::TakeHandleForSerialization( + std::move(temp_shmem))); } // Send all the values, even on error. This simplifies some of our cleanup @@ -183,25 +182,25 @@ void PepperAudioOutputHost::OnOpenComplete( // inconvenient to clean up. Our IPC code will automatically handle this for // us, as long as the remote side always closes the handles it receives, even // in the failure case. - open_context_.params.AppendHandle(serialized_socket_handle); - open_context_.params.AppendHandle(serialized_shared_memory_handle); + open_context_.params.AppendHandle(std::move(serialized_socket_handle)); + open_context_.params.AppendHandle(std::move(serialized_shared_memory_handle)); SendOpenReply(result); } int32_t PepperAudioOutputHost::GetRemoteHandles( const base::SyncSocket& socket, - const base::SharedMemory& shared_memory, + const base::UnsafeSharedMemoryRegion& shared_memory_region, IPC::PlatformFileForTransit* remote_socket_handle, - base::SharedMemoryHandle* remote_shared_memory_handle) { + base::UnsafeSharedMemoryRegion* remote_shared_memory_region) { *remote_socket_handle = renderer_ppapi_host_->ShareHandleWithRemote(socket.handle(), false); if (*remote_socket_handle == IPC::InvalidPlatformFileForTransit()) return PP_ERROR_FAILED; - *remote_shared_memory_handle = - renderer_ppapi_host_->ShareSharedMemoryHandleWithRemote( - shared_memory.handle()); - if (!base::SharedMemory::IsHandleValid(*remote_shared_memory_handle)) + *remote_shared_memory_region = + renderer_ppapi_host_->ShareUnsafeSharedMemoryRegionWithRemote( + shared_memory_region); + if (!remote_shared_memory_region->IsValid()) return PP_ERROR_FAILED; return PP_OK; diff --git a/chromium/content/renderer/pepper/pepper_audio_output_host.h b/chromium/content/renderer/pepper/pepper_audio_output_host.h index e8ea573ffa7..ea2602ad24a 100644 --- a/chromium/content/renderer/pepper/pepper_audio_output_host.h +++ b/chromium/content/renderer/pepper/pepper_audio_output_host.h @@ -13,7 +13,7 @@ #include "base/compiler_specific.h" #include "base/macros.h" -#include "base/memory/shared_memory.h" +#include "base/memory/unsafe_shared_memory_region.h" #include "base/sync_socket.h" #include "content/public/renderer/plugin_instance_throttler.h" #include "content/renderer/pepper/pepper_device_enumeration_host_helper.h" @@ -39,8 +39,7 @@ class PepperAudioOutputHost : public ppapi::host::ResourceHost, ppapi::host::HostMessageContext* context) override; // Called when the stream is created. - void StreamCreated(base::SharedMemoryHandle shared_memory_handle, - size_t shared_memory_size, + void StreamCreated(base::UnsafeSharedMemoryRegion shared_memory_region, base::SyncSocket::Handle socket); void StreamCreationFailed(); void SetVolume(double volume); @@ -55,15 +54,14 @@ class PepperAudioOutputHost : public ppapi::host::ResourceHost, int32_t OnClose(ppapi::host::HostMessageContext* context); void OnOpenComplete(int32_t result, - base::SharedMemoryHandle shared_memory_handle, - size_t shared_memory_size, + base::UnsafeSharedMemoryRegion shared_memory_region, base::SyncSocket::Handle socket_handle); int32_t GetRemoteHandles( const base::SyncSocket& socket, - const base::SharedMemory& shared_memory, + const base::UnsafeSharedMemoryRegion& shared_memory_region, IPC::PlatformFileForTransit* remote_socket_handle, - base::SharedMemoryHandle* remote_shared_memory_handle); + base::UnsafeSharedMemoryRegion* remote_shared_memory_region); void Close(); diff --git a/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc b/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc index b5c5bc9d90a..5110e1478a8 100644 --- a/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc +++ b/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc @@ -19,9 +19,9 @@ #include "cc/paint/paint_flags.h" #include "cc/resources/cross_thread_shared_bitmap.h" #include "components/viz/common/gpu/context_provider.h" -#include "components/viz/common/quads/shared_bitmap.h" #include "components/viz/common/resources/bitmap_allocation.h" #include "components/viz/common/resources/resource_sizes.h" +#include "components/viz/common/resources/shared_bitmap.h" #include "content/public/renderer/render_thread.h" #include "content/public/renderer/renderer_ppapi_host.h" #include "content/renderer/pepper/gfx_conversion.h" @@ -338,7 +338,7 @@ bool PepperGraphics2DHost::BindToInstance( // The |backing_bitmap| must be clipped to the |plugin_rect| to avoid painting // outside the plugin area. This can happen if the plugin has been resized since // PaintImageData verified the image is within the plugin size. -void PepperGraphics2DHost::Paint(blink::WebCanvas* canvas, +void PepperGraphics2DHost::Paint(cc::PaintCanvas* canvas, const gfx::Rect& plugin_rect, const gfx::Rect& paint_rect) { TRACE_EVENT0("pepper", "PepperGraphics2DHost::Paint"); @@ -387,8 +387,10 @@ void PepperGraphics2DHost::Paint(blink::WebCanvas* canvas, canvas->scale(scale_, scale_); pixel_origin.scale(1.0f / scale_); } - canvas->drawBitmap(backing_bitmap, pixel_origin.x(), pixel_origin.y(), - &flags); + // TODO(khushalsagar): Can this be cached on image_data_, and invalidated when + // the bitmap changes? + canvas->drawImage(cc::PaintImage::CreateFromBitmap(std::move(backing_bitmap)), + pixel_origin.x(), pixel_origin.y(), &flags); } void PepperGraphics2DHost::ViewInitiatedPaint() { @@ -713,7 +715,6 @@ bool PepperGraphics2DHost::PrepareTransferableResource( 0, format, GL_UNSIGNED_BYTE, nullptr); } - gl->GenMailboxCHROMIUM(gpu_mailbox.name); gl->ProduceTextureDirectCHROMIUM(texture_id, gpu_mailbox.name); } diff --git a/chromium/content/renderer/pepper/pepper_graphics_2d_host.h b/chromium/content/renderer/pepper/pepper_graphics_2d_host.h index 069a60c5a94..4c93d109936 100644 --- a/chromium/content/renderer/pepper/pepper_graphics_2d_host.h +++ b/chromium/content/renderer/pepper/pepper_graphics_2d_host.h @@ -12,13 +12,13 @@ #include "base/compiler_specific.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "cc/paint/paint_canvas.h" #include "cc/resources/shared_bitmap_id_registrar.h" #include "content/common/content_export.h" #include "gpu/command_buffer/common/mailbox.h" #include "ppapi/c/ppb_graphics_2d.h" #include "ppapi/host/host_message_context.h" #include "ppapi/host/resource_host.h" -#include "third_party/blink/public/platform/web_canvas.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/size.h" @@ -74,7 +74,7 @@ class CONTENT_EXPORT PepperGraphics2DHost // is already bound to a different instance, and nothing will happen. bool BindToInstance(PepperPluginInstanceImpl* new_instance); // Paints the current backing store to the web page. - void Paint(blink::WebCanvas* canvas, + void Paint(cc::PaintCanvas* canvas, const gfx::Rect& plugin_rect, const gfx::Rect& paint_rect); diff --git a/chromium/content/renderer/pepper/pepper_media_stream_track_host_base.cc b/chromium/content/renderer/pepper/pepper_media_stream_track_host_base.cc index 947f8468b3a..a4304ad66a0 100644 --- a/chromium/content/renderer/pepper/pepper_media_stream_track_host_base.cc +++ b/chromium/content/renderer/pepper/pepper_media_stream_track_host_base.cc @@ -67,13 +67,13 @@ bool PepperMediaStreamTrackHostBase::InitBuffers(int32_t number_of_buffers, SerializedHandle handle(host_->ShareSharedMemoryHandleWithRemote(shm_handle), size.ValueOrDie()); bool readonly = (track_type == kRead); + std::vector<SerializedHandle> handles; + handles.push_back(std::move(handle)); host()->SendUnsolicitedReplyWithHandles( pp_resource(), PpapiPluginMsg_MediaStreamTrack_InitBuffers( - number_of_buffers, - buffer_size_aligned.ValueOrDie(), - readonly), - std::vector<SerializedHandle>(1, handle)); + number_of_buffers, buffer_size_aligned.ValueOrDie(), readonly), + &handles); return true; } diff --git a/chromium/content/renderer/pepper/pepper_platform_audio_input.cc b/chromium/content/renderer/pepper/pepper_platform_audio_input.cc index 1d8fb3ff295..97629b7c3c7 100644 --- a/chromium/content/renderer/pepper/pepper_platform_audio_input.cc +++ b/chromium/content/renderer/pepper/pepper_platform_audio_input.cc @@ -11,7 +11,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "content/child/child_process.h" -#include "content/renderer/media/audio_input_ipc_factory.h" +#include "content/renderer/media/audio/audio_input_ipc_factory.h" #include "content/renderer/pepper/pepper_audio_input_host.h" #include "content/renderer/pepper/pepper_media_device_manager.h" #include "content/renderer/render_frame_impl.h" @@ -76,34 +76,32 @@ void PepperPlatformAudioInput::ShutDown() { } void PepperPlatformAudioInput::OnStreamCreated( - base::SharedMemoryHandle handle, + base::ReadOnlySharedMemoryRegion shared_memory_region, base::SyncSocket::Handle socket_handle, bool initially_muted) { + DCHECK(shared_memory_region.IsValid()); #if defined(OS_WIN) - DCHECK(handle.IsValid()); DCHECK(socket_handle); #else - DCHECK(base::SharedMemory::IsHandleValid(handle)); DCHECK_NE(-1, socket_handle); #endif - DCHECK(handle.GetSize()); + DCHECK_GT(shared_memory_region.GetSize(), 0u); if (base::ThreadTaskRunnerHandle::Get().get() != main_task_runner_.get()) { // If shutdown has occurred, |client_| will be NULL and the handles will be // cleaned up on the main thread. main_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&PepperPlatformAudioInput::OnStreamCreated, this, handle, - socket_handle, initially_muted)); + FROM_HERE, base::BindOnce(&PepperPlatformAudioInput::OnStreamCreated, + this, std::move(shared_memory_region), + socket_handle, initially_muted)); } else { // Must dereference the client only on the main thread. Shutdown may have // occurred while the request was in-flight, so we need to NULL check. if (client_) { - client_->StreamCreated(handle, handle.GetSize(), socket_handle); + client_->StreamCreated(std::move(shared_memory_region), socket_handle); } else { - // Clean up the handles. + // Clean up the handle. base::SyncSocket temp_socket(socket_handle); - base::SharedMemory temp_shared_memory(handle, false); } } } diff --git a/chromium/content/renderer/pepper/pepper_platform_audio_input.h b/chromium/content/renderer/pepper/pepper_platform_audio_input.h index d7f69bbd6f0..0d83fb4355e 100644 --- a/chromium/content/renderer/pepper/pepper_platform_audio_input.h +++ b/chromium/content/renderer/pepper/pepper_platform_audio_input.h @@ -55,7 +55,7 @@ class PepperPlatformAudioInput void ShutDown(); // media::AudioInputIPCDelegate. - void OnStreamCreated(base::SharedMemoryHandle handle, + void OnStreamCreated(base::ReadOnlySharedMemoryRegion shared_memory_region, base::SyncSocket::Handle socket_handle, bool initially_muted) override; void OnError() override; diff --git a/chromium/content/renderer/pepper/pepper_platform_audio_output.cc b/chromium/content/renderer/pepper/pepper_platform_audio_output.cc index 267fe95c276..fcc69c75eae 100644 --- a/chromium/content/renderer/pepper/pepper_platform_audio_output.cc +++ b/chromium/content/renderer/pepper/pepper_platform_audio_output.cc @@ -11,7 +11,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "content/child/child_process.h" -#include "content/renderer/media/audio_output_ipc_factory.h" +#include "content/renderer/media/audio/audio_output_ipc_factory.h" #include "content/renderer/pepper/audio_helper.h" #include "ppapi/shared_impl/ppb_audio_config_shared.h" @@ -89,27 +89,27 @@ void PepperPlatformAudioOutput::OnDeviceAuthorized( } void PepperPlatformAudioOutput::OnStreamCreated( - base::SharedMemoryHandle handle, + base::UnsafeSharedMemoryRegion shared_memory_region, base::SyncSocket::Handle socket_handle, bool playing_automatically) { - DCHECK(handle.IsValid()); + DCHECK(shared_memory_region.IsValid()); #if defined(OS_WIN) DCHECK(socket_handle); #else DCHECK_NE(-1, socket_handle); #endif - DCHECK(handle.GetSize()); + DCHECK_GT(shared_memory_region.GetSize(), 0u); if (base::ThreadTaskRunnerHandle::Get().get() == main_task_runner_.get()) { // Must dereference the client only on the main thread. Shutdown may have // occurred while the request was in-flight, so we need to NULL check. if (client_) - client_->StreamCreated(handle, handle.GetSize(), socket_handle); + client_->StreamCreated(std::move(shared_memory_region), socket_handle); } else { main_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&PepperPlatformAudioOutput::OnStreamCreated, this, - handle, socket_handle, playing_automatically)); + FROM_HERE, base::BindOnce(&PepperPlatformAudioOutput::OnStreamCreated, + this, std::move(shared_memory_region), + socket_handle, playing_automatically)); } } diff --git a/chromium/content/renderer/pepper/pepper_platform_audio_output.h b/chromium/content/renderer/pepper/pepper_platform_audio_output.h index 43be22d0076..fb0559ddb51 100644 --- a/chromium/content/renderer/pepper/pepper_platform_audio_output.h +++ b/chromium/content/renderer/pepper/pepper_platform_audio_output.h @@ -57,7 +57,7 @@ class PepperPlatformAudioOutput void OnDeviceAuthorized(media::OutputDeviceStatus device_status, const media::AudioParameters& output_params, const std::string& matched_device_id) override; - void OnStreamCreated(base::SharedMemoryHandle handle, + void OnStreamCreated(base::UnsafeSharedMemoryRegion shared_memory_region, base::SyncSocket::Handle socket_handle, bool playing_automatically) override; void OnIPCClosed() override; 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 c4f75ab84a7..7c7f53aab6e 100644 --- a/chromium/content/renderer/pepper/pepper_platform_audio_output_dev.cc +++ b/chromium/content/renderer/pepper/pepper_platform_audio_output_dev.cc @@ -14,7 +14,7 @@ #include "build/build_config.h" #include "content/child/child_process.h" #include "content/common/content_constants_internal.h" -#include "content/renderer/media/audio_output_ipc_factory.h" +#include "content/renderer/media/audio/audio_output_ipc_factory.h" #include "content/renderer/pepper/audio_helper.h" #include "content/renderer/pepper/pepper_audio_output_host.h" #include "content/renderer/pepper/pepper_media_device_manager.h" @@ -180,22 +180,22 @@ void PepperPlatformAudioOutputDev::OnDeviceAuthorized( } void PepperPlatformAudioOutputDev::OnStreamCreated( - base::SharedMemoryHandle handle, + base::UnsafeSharedMemoryRegion shared_memory_region, base::SyncSocket::Handle socket_handle, bool playing_automatically) { - DCHECK(handle.IsValid()); + DCHECK(shared_memory_region.IsValid()); #if defined(OS_WIN) DCHECK(socket_handle); #else DCHECK_NE(-1, socket_handle); #endif - DCHECK(handle.GetSize()); + DCHECK_GT(shared_memory_region.GetSize(), 0u); if (base::ThreadTaskRunnerHandle::Get().get() == main_task_runner_.get()) { // Must dereference the client only on the main thread. Shutdown may have // occurred while the request was in-flight, so we need to NULL check. if (client_) - client_->StreamCreated(handle, handle.GetSize(), socket_handle); + client_->StreamCreated(std::move(shared_memory_region), socket_handle); } else { DCHECK(io_task_runner_->BelongsToCurrentThread()); if (state_ != CREATING_STREAM) @@ -208,7 +208,8 @@ void PepperPlatformAudioOutputDev::OnStreamCreated( main_task_runner_->PostTask( FROM_HERE, base::BindOnce(&PepperPlatformAudioOutputDev::OnStreamCreated, this, - handle, socket_handle, playing_automatically)); + std::move(shared_memory_region), socket_handle, + playing_automatically)); } } diff --git a/chromium/content/renderer/pepper/pepper_platform_audio_output_dev.h b/chromium/content/renderer/pepper/pepper_platform_audio_output_dev.h index 71ca14500f7..dbb23a45feb 100644 --- a/chromium/content/renderer/pepper/pepper_platform_audio_output_dev.h +++ b/chromium/content/renderer/pepper/pepper_platform_audio_output_dev.h @@ -62,7 +62,7 @@ class PepperPlatformAudioOutputDev void OnDeviceAuthorized(media::OutputDeviceStatus device_status, const media::AudioParameters& output_params, const std::string& matched_device_id) override; - void OnStreamCreated(base::SharedMemoryHandle handle, + void OnStreamCreated(base::UnsafeSharedMemoryRegion shared_memory_region, base::SyncSocket::Handle socket_handle, bool playing_automatically) override; void OnIPCClosed() override; diff --git a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc index 931e2e7408a..8e7653afc9d 100644 --- a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc +++ b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc @@ -27,7 +27,7 @@ #include "content/common/frame_messages.h" #include "content/public/common/content_constants.h" #include "content/public/renderer/content_renderer_client.h" -#include "content/renderer/media/audio_device_factory.h" +#include "content/renderer/media/audio/audio_device_factory.h" #include "content/renderer/pepper/event_conversion.h" #include "content/renderer/pepper/fullscreen_container.h" #include "content/renderer/pepper/gfx_conversion.h" @@ -168,7 +168,6 @@ using ppapi::thunk::PPB_ImageData_API; using ppapi::Var; using ppapi::ArrayBufferVar; using ppapi::ViewData; -using blink::WebCanvas; using blink::WebCursorInfo; using blink::WebDocument; using blink::WebElement; @@ -537,7 +536,6 @@ PepperPluginInstanceImpl::PepperPluginInstanceImpl( flash_fullscreen_(false), desired_fullscreen_state_(false), message_channel_(nullptr), - sad_plugin_(nullptr), input_event_mask_(0), filtered_input_event_mask_(0), text_input_type_(kPluginDefaultTextInputType), @@ -710,16 +708,21 @@ void PepperPluginInstanceImpl::Delete() { bool PepperPluginInstanceImpl::is_deleted() const { return is_deleted_; } -void PepperPluginInstanceImpl::Paint(WebCanvas* canvas, +void PepperPluginInstanceImpl::Paint(cc::PaintCanvas* canvas, const gfx::Rect& plugin_rect, const gfx::Rect& paint_rect) { TRACE_EVENT0("ppapi", "PluginInstance::Paint"); if (module()->is_crashed()) { // Crashed plugin painting. - if (!sad_plugin_) // Lazily initialize bitmap. - sad_plugin_ = GetContentClient()->renderer()->GetSadPluginBitmap(); - if (sad_plugin_) - PaintSadPlugin(canvas, plugin_rect, *sad_plugin_); + if (!sad_plugin_image_) { // Lazily initialize bitmap. + if (SkBitmap* bitmap = + GetContentClient()->renderer()->GetSadPluginBitmap()) { + DCHECK(bitmap->isImmutable()); + sad_plugin_image_ = cc::PaintImage::CreateFromBitmap(*bitmap); + } + } + if (sad_plugin_image_) + PaintSadPlugin(canvas, plugin_rect, sad_plugin_image_); return; } @@ -914,7 +917,7 @@ bool PepperPluginInstanceImpl::HandleDocumentLoad( return true; } - if (module()->is_crashed()) { + if (module()->is_crashed() || !render_frame_) { // Don't create a resource for a crashed plugin. container()->GetDocument().GetFrame()->StopLoading(); return false; @@ -939,14 +942,13 @@ bool PepperPluginInstanceImpl::HandleDocumentLoad( std::unique_ptr<ppapi::host::ResourceHost>(std::move(loader_host))); DCHECK(pending_host_id); - DataFromWebURLResponse( - host_impl, - pp_instance(), - response, - base::Bind(&PepperPluginInstanceImpl::DidDataFromWebURLResponse, - weak_factory_.GetWeakPtr(), - response, - pending_host_id)); + render_frame() + ->GetTaskRunner(blink::TaskType::kInternalLoading) + ->PostTask( + FROM_HERE, + base::BindOnce(&PepperPluginInstanceImpl::DidDataFromWebURLResponse, + weak_factory_.GetWeakPtr(), response, pending_host_id, + DataFromWebURLResponse(response))); // If the load was not abandoned, document_loader_ will now be set. It's // possible that the load was canceled by now and document_loader_ was @@ -1979,7 +1981,7 @@ int PepperPluginInstanceImpl::PrintBegin(const WebPrintParams& print_params) { if (LoadPdfInterface()) { PP_PdfPrintSettings_Dev pdf_print_settings; - pdf_print_settings.num_pages_per_sheet = print_params.num_pages_per_sheet; + pdf_print_settings.pages_per_sheet = print_params.pages_per_sheet; pdf_print_settings.scale_factor = print_params.scale_factor; num_pages = plugin_pdf_interface_->PrintBegin( @@ -1998,7 +2000,7 @@ int PepperPluginInstanceImpl::PrintBegin(const WebPrintParams& print_params) { } void PepperPluginInstanceImpl::PrintPage(int page_number, - blink::WebCanvas* canvas) { + cc::PaintCanvas* canvas) { #if BUILDFLAG(ENABLE_PRINTING) DCHECK(plugin_print_interface_); @@ -2815,7 +2817,7 @@ PP_Bool PepperPluginInstanceImpl::SetCursor(PP_Instance instance, SkBitmap bitmap(image_data->GetMappedBitmap()); // Make a deep copy, so that the cursor remains valid even after the original // image data gets freed. - SkBitmap& dst = custom_cursor->custom_image.GetSkBitmap(); + SkBitmap& dst = custom_cursor->custom_image; if (!dst.tryAllocPixels(bitmap.info()) || !bitmap.readPixels(dst.info(), dst.getPixels(), dst.rowBytes(), 0, 0)) { return PP_FALSE; @@ -3376,7 +3378,7 @@ MouseLockDispatcher* PepperPluginInstanceImpl::GetMouseLockDispatcher() { return container->mouse_lock_dispatcher(); } if (render_frame_) - return render_frame_->render_view()->mouse_lock_dispatcher(); + return render_frame_->render_view()->GetWidget()->mouse_lock_dispatcher(); return nullptr; } diff --git a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h index 6d554119935..757177607ca 100644 --- a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h +++ b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h @@ -26,6 +26,7 @@ #include "cc/layers/content_layer_client.h" #include "cc/layers/layer.h" #include "cc/layers/texture_layer_client.h" +#include "cc/paint/paint_canvas.h" #include "components/viz/common/resources/transferable_resource.h" #include "content/common/content_export.h" #include "content/public/renderer/pepper_plugin_instance.h" @@ -56,7 +57,6 @@ #include "ppapi/shared_impl/tracked_callback.h" #include "ppapi/thunk/ppb_gamepad_api.h" #include "ppapi/thunk/resource_creation_api.h" -#include "third_party/blink/public/platform/web_canvas.h" #include "third_party/blink/public/platform/web_string.h" #include "third_party/blink/public/platform/web_url_response.h" #include "third_party/blink/public/web/web_associated_url_loader_client.h" @@ -69,8 +69,6 @@ struct PP_Point; -class SkBitmap; - namespace blink { class WebCoalescedInputEvent; class WebInputEvent; @@ -183,7 +181,7 @@ class CONTENT_EXPORT PepperPluginInstanceImpl GURL document_url() const { return document_url_; } // Paints the current backing store to the web page. - void Paint(blink::WebCanvas* canvas, + void Paint(cc::PaintCanvas* canvas, const gfx::Rect& plugin_rect, const gfx::Rect& paint_rect); @@ -276,7 +274,7 @@ class CONTENT_EXPORT PepperPluginInstanceImpl bool SupportsPrintInterface(); bool IsPrintScalingDisabled(); int PrintBegin(const blink::WebPrintParams& print_params); - void PrintPage(int page_number, blink::WebCanvas* canvas); + void PrintPage(int page_number, cc::PaintCanvas* canvas); void PrintEnd(); bool GetPrintPresetOptionsFromDocument( blink::WebPrintPresetOptions* preset_options); @@ -850,8 +848,8 @@ class CONTENT_EXPORT PepperPluginInstanceImpl // only valid as long as |message_channel_object_| is alive. MessageChannel* message_channel_; - // Bitmap for crashed plugin. Lazily initialized, non-owning pointer. - SkBitmap* sad_plugin_; + // Bitmap for crashed plugin. Lazily initialized. + cc::PaintImage sad_plugin_image_; typedef std::set<PluginObject*> PluginObjectSet; PluginObjectSet live_plugin_objects_; diff --git a/chromium/content/renderer/pepper/pepper_proxy_channel_delegate_impl.cc b/chromium/content/renderer/pepper/pepper_proxy_channel_delegate_impl.cc index c97d6a5c56a..e026b2fef3d 100644 --- a/chromium/content/renderer/pepper/pepper_proxy_channel_delegate_impl.cc +++ b/chromium/content/renderer/pepper/pepper_proxy_channel_delegate_impl.cc @@ -39,4 +39,18 @@ PepperProxyChannelDelegateImpl::ShareSharedMemoryHandleWithRemote( return base::SharedMemory::DuplicateHandle(handle); } +base::UnsafeSharedMemoryRegion +PepperProxyChannelDelegateImpl::ShareUnsafeSharedMemoryRegionWithRemote( + const base::UnsafeSharedMemoryRegion& region, + base::ProcessId remote_pid) { + return region.Duplicate(); +} + +base::ReadOnlySharedMemoryRegion +PepperProxyChannelDelegateImpl::ShareReadOnlySharedMemoryRegionWithRemote( + const base::ReadOnlySharedMemoryRegion& region, + base::ProcessId remote_pid) { + return region.Duplicate(); +} + } // namespace content diff --git a/chromium/content/renderer/pepper/pepper_proxy_channel_delegate_impl.h b/chromium/content/renderer/pepper/pepper_proxy_channel_delegate_impl.h index 6bfd2a1b6bb..147c68cc9f8 100644 --- a/chromium/content/renderer/pepper/pepper_proxy_channel_delegate_impl.h +++ b/chromium/content/renderer/pepper/pepper_proxy_channel_delegate_impl.h @@ -25,6 +25,12 @@ class PepperProxyChannelDelegateImpl base::SharedMemoryHandle ShareSharedMemoryHandleWithRemote( const base::SharedMemoryHandle& handle, base::ProcessId remote_pid) override; + base::UnsafeSharedMemoryRegion ShareUnsafeSharedMemoryRegionWithRemote( + const base::UnsafeSharedMemoryRegion& region, + base::ProcessId remote_pid) override; + base::ReadOnlySharedMemoryRegion ShareReadOnlySharedMemoryRegionWithRemote( + const base::ReadOnlySharedMemoryRegion& region, + base::ProcessId remote_pid) override; }; } // namespace content diff --git a/chromium/content/renderer/pepper/pepper_url_loader_host.cc b/chromium/content/renderer/pepper/pepper_url_loader_host.cc index 3d2914bfb7d..681130e7db9 100644 --- a/chromium/content/renderer/pepper/pepper_url_loader_host.cc +++ b/chromium/content/renderer/pepper/pepper_url_loader_host.cc @@ -57,8 +57,7 @@ PepperURLLoaderHost::PepperURLLoaderHost(RendererPpapiHostImpl* host, total_bytes_to_be_sent_(-1), bytes_received_(0), total_bytes_to_be_received_(-1), - pending_response_(false), - weak_factory_(this) { + pending_response_(false) { DCHECK((main_document_loader && !resource) || (!main_document_loader && resource)); } @@ -405,21 +404,12 @@ void PepperURLLoaderHost::SaveResponse(const WebURLResponse& response) { DCHECK(!pending_response_); pending_response_ = true; - DataFromWebURLResponse( - renderer_ppapi_host_, - pp_instance(), - response, - base::Bind(&PepperURLLoaderHost::DidDataFromWebURLResponse, - weak_factory_.GetWeakPtr())); + SendUpdateToPlugin( + std::make_unique<PpapiPluginMsg_URLLoader_ReceivedResponse>( + DataFromWebURLResponse(response))); } } -void PepperURLLoaderHost::DidDataFromWebURLResponse( - const ppapi::URLResponseInfoData& data) { - SendUpdateToPlugin( - std::make_unique<PpapiPluginMsg_URLLoader_ReceivedResponse>(data)); -} - void PepperURLLoaderHost::UpdateProgress() { bool record_download = request_data_.record_download_progress; bool record_upload = request_data_.record_upload_progress; diff --git a/chromium/content/renderer/pepper/pepper_url_loader_host.h b/chromium/content/renderer/pepper/pepper_url_loader_host.h index 1f3510907d3..f5ff3d7eff1 100644 --- a/chromium/content/renderer/pepper/pepper_url_loader_host.h +++ b/chromium/content/renderer/pepper/pepper_url_loader_host.h @@ -11,7 +11,6 @@ #include <vector> #include "base/macros.h" -#include "base/memory/weak_ptr.h" #include "content/common/content_export.h" #include "ppapi/host/resource_host.h" #include "ppapi/proxy/resource_message_params.h" @@ -96,7 +95,6 @@ class PepperURLLoaderHost : public ppapi::host::ResourceHost, // Converts a WebURLResponse to a URLResponseInfo and saves it. void SaveResponse(const blink::WebURLResponse& response); - void DidDataFromWebURLResponse(const ppapi::URLResponseInfoData& data); // Sends the UpdateProgress message (if necessary) to the plugin. void UpdateProgress(); @@ -139,8 +137,6 @@ class PepperURLLoaderHost : public ppapi::host::ResourceHost, // ordering constraints on following messages to the plugin. bool pending_response_; - base::WeakPtrFactory<PepperURLLoaderHost> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(PepperURLLoaderHost); }; diff --git a/chromium/content/renderer/pepper/pepper_url_request_unittest.cc b/chromium/content/renderer/pepper/pepper_url_request_unittest.cc index 845aca9a3ef..b091332f7a6 100644 --- a/chromium/content/renderer/pepper/pepper_url_request_unittest.cc +++ b/chromium/content/renderer/pepper/pepper_url_request_unittest.cc @@ -14,8 +14,8 @@ #include "ppapi/thunk/thunk.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/platform/web_url_request.h" -#include "third_party/blink/public/web/web_frame_client.h" #include "third_party/blink/public/web/web_local_frame.h" +#include "third_party/blink/public/web/web_local_frame_client.h" #include "third_party/blink/public/web/web_view.h" // This test is a end-to-end test from the resource to the WebKit request @@ -23,7 +23,7 @@ // test it by making sure the conversion routines actually work at the same // time. -using blink::WebFrameClient; +using blink::WebLocalFrameClient; using blink::WebString; using blink::WebView; using blink::WebURL; @@ -32,7 +32,7 @@ using blink::WebURLRequest; namespace { // The base class destructor is protected, so derive. -class TestWebFrameClient : public WebFrameClient {}; +class TestWebFrameClient : public WebLocalFrameClient {}; } // namespace @@ -61,14 +61,6 @@ class URLRequestInfoTest : public RenderViewTest { RenderViewTest::TearDown(); } - bool GetDownloadToFile() { - WebURLRequest web_request; - URLRequestInfoData data = info_->GetData(); - if (!CreateWebURLRequest(pp_instance_, &data, GetMainFrame(), &web_request)) - return false; - return web_request.DownloadToFile(); - } - WebString GetURL() { WebURLRequest web_request; URLRequestInfoData data = info_->GetData(); @@ -129,13 +121,8 @@ TEST_F(URLRequestInfoTest, AsURLRequestInfo) { TEST_F(URLRequestInfoTest, StreamToFile) { SetStringProperty(PP_URLREQUESTPROPERTY_URL, "http://www.google.com"); - EXPECT_FALSE(GetDownloadToFile()); - EXPECT_FALSE(SetBooleanProperty(PP_URLREQUESTPROPERTY_STREAMTOFILE, true)); - EXPECT_FALSE(GetDownloadToFile()); - EXPECT_FALSE(SetBooleanProperty(PP_URLREQUESTPROPERTY_STREAMTOFILE, false)); - EXPECT_FALSE(GetDownloadToFile()); } TEST_F(URLRequestInfoTest, FollowRedirects) { diff --git a/chromium/content/renderer/pepper/pepper_video_decoder_host.cc b/chromium/content/renderer/pepper/pepper_video_decoder_host.cc index d3fb411d87c..5201b8dc049 100644 --- a/chromium/content/renderer/pepper/pepper_video_decoder_host.cc +++ b/chromium/content/renderer/pepper/pepper_video_decoder_host.cc @@ -215,7 +215,7 @@ int32_t PepperVideoDecoderHost::OnHostMsgGetShm( shm_size); ppapi::host::ReplyMessageContext reply_context = context->MakeReplyMessageContext(); - reply_context.params.AppendHandle(handle); + reply_context.params.AppendHandle(std::move(handle)); host()->SendReply(reply_context, PpapiPluginMsg_VideoDecoder_GetShmReply(shm_size)); @@ -256,9 +256,12 @@ int32_t PepperVideoDecoderHost::OnHostMsgDecode( int32_t PepperVideoDecoderHost::OnHostMsgAssignTextures( ppapi::host::HostMessageContext* context, const PP_Size& size, - const std::vector<uint32_t>& texture_ids) { + const std::vector<uint32_t>& texture_ids, + const std::vector<gpu::Mailbox>& mailboxes) { if (!initialized_) return PP_ERROR_FAILED; + if (texture_ids.size() != mailboxes.size()) + return PP_ERROR_FAILED; DCHECK(decoder_); pending_texture_requests_--; @@ -304,6 +307,7 @@ int32_t PepperVideoDecoderHost::OnHostMsgAssignTextures( gfx::Size(size.width, size.height), ids); picture_buffers.push_back(buffer); } + texture_mailboxes_ = mailboxes; decoder_->AssignPictureBuffers(picture_buffers); return PP_OK; } @@ -375,10 +379,12 @@ void PepperVideoDecoderHost::ProvidePictureBuffers( const gfx::Size& dimensions, uint32_t texture_target) { DCHECK_EQ(1u, textures_per_buffer); - RequestTextures(std::max(min_picture_count_, requested_num_of_buffers), - dimensions, - texture_target, - std::vector<gpu::Mailbox>()); + pending_texture_requests_++; + host()->SendUnsolicitedReply( + pp_resource(), PpapiPluginMsg_VideoDecoder_RequestTextures( + std::max(min_picture_count_, requested_num_of_buffers), + PP_MakeSize(dimensions.width(), dimensions.height()), + texture_target)); } void PepperVideoDecoderHost::PictureReady(const media::Picture& picture) { @@ -476,21 +482,6 @@ const uint8_t* PepperVideoDecoderHost::DecodeIdToAddress(uint32_t decode_id) { return static_cast<uint8_t*>(shm_buffers_[shm_id]->memory()); } -void PepperVideoDecoderHost::RequestTextures( - uint32_t requested_num_of_buffers, - const gfx::Size& dimensions, - uint32_t texture_target, - const std::vector<gpu::Mailbox>& mailboxes) { - pending_texture_requests_++; - host()->SendUnsolicitedReply( - pp_resource(), - PpapiPluginMsg_VideoDecoder_RequestTextures( - requested_num_of_buffers, - PP_MakeSize(dimensions.width(), dimensions.height()), - texture_target, - mailboxes)); -} - bool PepperVideoDecoderHost::TryFallbackToSoftwareDecoder() { #if defined(OS_ANDROID) return false; diff --git a/chromium/content/renderer/pepper/pepper_video_decoder_host.h b/chromium/content/renderer/pepper/pepper_video_decoder_host.h index e58aa1e9862..2983f48853e 100644 --- a/chromium/content/renderer/pepper/pepper_video_decoder_host.h +++ b/chromium/content/renderer/pepper/pepper_video_decoder_host.h @@ -16,6 +16,7 @@ #include "base/containers/hash_tables.h" #include "base/macros.h" #include "content/common/content_export.h" +#include "gpu/command_buffer/common/mailbox.h" #include "media/video/video_decode_accelerator.h" #include "ppapi/c/pp_codecs.h" #include "ppapi/host/host_message_context.h" @@ -95,7 +96,8 @@ class CONTENT_EXPORT PepperVideoDecoderHost int32_t decode_id); int32_t OnHostMsgAssignTextures(ppapi::host::HostMessageContext* context, const PP_Size& size, - const std::vector<uint32_t>& texture_ids); + const std::vector<uint32_t>& texture_ids, + const std::vector<gpu::Mailbox>& mailboxes); int32_t OnHostMsgRecyclePicture(ppapi::host::HostMessageContext* context, uint32_t picture_id); int32_t OnHostMsgFlush(ppapi::host::HostMessageContext* context); @@ -104,10 +106,9 @@ class CONTENT_EXPORT PepperVideoDecoderHost // These methods are needed by VideoDecodeShim, to look like a // VideoDecodeAccelerator. const uint8_t* DecodeIdToAddress(uint32_t decode_id); - void RequestTextures(uint32_t requested_num_of_buffers, - const gfx::Size& dimensions, - uint32_t texture_target, - const std::vector<gpu::Mailbox>& mailboxes); + std::vector<gpu::Mailbox> TakeMailboxes() { + return std::move(texture_mailboxes_); + } // Tries to initialize software decoder. Returns true on success. bool TryFallbackToSoftwareDecoder(); @@ -143,6 +144,10 @@ class CONTENT_EXPORT PepperVideoDecoderHost typedef std::map<uint32_t, PictureBufferState> PictureBufferMap; PictureBufferMap picture_buffer_map_; + // Mailboxes corresponding to textures given to AssignPictureBuffers, to allow + // VideoDecoderShim to use them from another context. + std::vector<gpu::Mailbox> texture_mailboxes_; + // Keeps list of pending decodes. PendingDecodeList pending_decodes_; diff --git a/chromium/content/renderer/pepper/pepper_video_encoder_host.cc b/chromium/content/renderer/pepper/pepper_video_encoder_host.cc index 913820c20f3..8c3565b2b23 100644 --- a/chromium/content/renderer/pepper/pepper_video_encoder_host.cc +++ b/chromium/content/renderer/pepper/pepper_video_encoder_host.cc @@ -375,9 +375,10 @@ void PepperVideoEncoderHost::RequireBitstreamBuffers( } host()->SendUnsolicitedReplyWithHandles( - pp_resource(), PpapiPluginMsg_VideoEncoder_BitstreamBuffers( - static_cast<uint32_t>(output_buffer_size)), - handles); + pp_resource(), + PpapiPluginMsg_VideoEncoder_BitstreamBuffers( + static_cast<uint32_t>(output_buffer_size)), + &handles); if (!initialized_) { // Tell the plugin that initialization has been successful if we @@ -400,10 +401,9 @@ void PepperVideoEncoderHost::RequireBitstreamBuffers( AllocateVideoFrames(); } -void PepperVideoEncoderHost::BitstreamBufferReady(int32_t buffer_id, - size_t payload_size, - bool key_frame, - base::TimeDelta /* timestamp */) { +void PepperVideoEncoderHost::BitstreamBufferReady( + int32_t buffer_id, + const media::BitstreamBufferMetadata& metadata) { DCHECK(RenderThreadImpl::current()); DCHECK(shm_buffers_[buffer_id]->in_use); @@ -412,7 +412,8 @@ void PepperVideoEncoderHost::BitstreamBufferReady(int32_t buffer_id, host()->SendUnsolicitedReply( pp_resource(), PpapiPluginMsg_VideoEncoder_BitstreamBufferReady( - buffer_id, static_cast<uint32_t>(payload_size), key_frame)); + buffer_id, base::checked_cast<uint32_t>(metadata.payload_size_bytes), + metadata.key_frame)); } void PepperVideoEncoderHost::NotifyError( diff --git a/chromium/content/renderer/pepper/pepper_video_encoder_host.h b/chromium/content/renderer/pepper/pepper_video_encoder_host.h index 264c668cdc8..cbf01cf672f 100644 --- a/chromium/content/renderer/pepper/pepper_video_encoder_host.h +++ b/chromium/content/renderer/pepper/pepper_video_encoder_host.h @@ -27,6 +27,10 @@ namespace gpu { class CommandBufferProxyImpl; } +namespace media { +struct BitstreamBufferMetadata; +} // namespace media + namespace content { class RendererPpapiHost; @@ -63,10 +67,9 @@ class CONTENT_EXPORT PepperVideoEncoderHost void RequireBitstreamBuffers(unsigned int input_count, const gfx::Size& input_coded_size, size_t output_buffer_size) override; - void BitstreamBufferReady(int32_t bitstream_buffer_id, - size_t payload_size, - bool key_frame, - base::TimeDelta timestamp) override; + void BitstreamBufferReady( + int32_t bitstream_buffer_id, + const media::BitstreamBufferMetadata& metadata) override; void NotifyError(media::VideoEncodeAccelerator::Error error) override; // ResourceHost implementation. diff --git a/chromium/content/renderer/pepper/pepper_video_source_host.cc b/chromium/content/renderer/pepper/pepper_video_source_host.cc index 1de7bbf7168..48047137deb 100644 --- a/chromium/content/renderer/pepper/pepper_video_source_host.cc +++ b/chromium/content/renderer/pepper/pepper_video_source_host.cc @@ -291,7 +291,7 @@ void PepperVideoSourceHost::SendGetFrameReply() { ppapi::proxy::SerializedHandle serialized_handle; serialized_handle.set_shmem(image_handle, byte_count); - reply_context_.params.AppendHandle(serialized_handle); + reply_context_.params.AppendHandle(std::move(serialized_handle)); host()->SendReply(reply_context_, PpapiPluginMsg_VideoSource_GetFrameReply( diff --git a/chromium/content/renderer/pepper/pepper_webplugin_impl.cc b/chromium/content/renderer/pepper/pepper_webplugin_impl.cc index a2701cacf15..ed9dd9bcee9 100644 --- a/chromium/content/renderer/pepper/pepper_webplugin_impl.cc +++ b/chromium/content/renderer/pepper/pepper_webplugin_impl.cc @@ -41,7 +41,6 @@ #include "url/gurl.h" using ppapi::V8ObjectVar; -using blink::WebCanvas; using blink::WebPlugin; using blink::WebPluginContainer; using blink::WebPluginParams; @@ -190,7 +189,7 @@ v8::Local<v8::Object> PepperWebPluginImpl::V8ScriptableObject( return result; } -void PepperWebPluginImpl::Paint(WebCanvas* canvas, const WebRect& rect) { +void PepperWebPluginImpl::Paint(cc::PaintCanvas* canvas, const WebRect& rect) { // Re-entrancy may cause JS to try to execute script on the plugin before it // is fully initialized. See: crbug.com/715747. if (instance_ && !instance_->FlashIsFullscreenOrPending()) @@ -441,7 +440,7 @@ int PepperWebPluginImpl::PrintBegin(const WebPrintParams& print_params) { return instance_->PrintBegin(print_params); } -void PepperWebPluginImpl::PrintPage(int page_number, blink::WebCanvas* canvas) { +void PepperWebPluginImpl::PrintPage(int page_number, cc::PaintCanvas* canvas) { // Re-entrancy may cause JS to try to execute script on the plugin before it // is fully initialized. See: crbug.com/715747. if (instance_) diff --git a/chromium/content/renderer/pepper/pepper_webplugin_impl.h b/chromium/content/renderer/pepper/pepper_webplugin_impl.h index 64e09efce8f..fb0a58b0d9e 100644 --- a/chromium/content/renderer/pepper/pepper_webplugin_impl.h +++ b/chromium/content/renderer/pepper/pepper_webplugin_impl.h @@ -44,7 +44,7 @@ class PepperWebPluginImpl : public blink::WebPlugin { void Destroy() override; v8::Local<v8::Object> V8ScriptableObject(v8::Isolate* isolate) override; void UpdateAllLifecyclePhases() override {} - void Paint(blink::WebCanvas* canvas, const blink::WebRect& rect) override; + void Paint(cc::PaintCanvas* canvas, const blink::WebRect& rect) override; void UpdateGeometry(const blink::WebRect& window_rect, const blink::WebRect& clip_rect, const blink::WebRect& unobscured_rect, @@ -80,7 +80,7 @@ class PepperWebPluginImpl : public blink::WebPlugin { bool IsPrintScalingDisabled() override; int PrintBegin(const blink::WebPrintParams& print_params) override; - void PrintPage(int page_number, blink::WebCanvas* canvas) override; + void PrintPage(int page_number, cc::PaintCanvas* canvas) override; void PrintEnd() override; bool CanRotateView() override; diff --git a/chromium/content/renderer/pepper/ppb_audio_impl.cc b/chromium/content/renderer/pepper/ppb_audio_impl.cc index 21d939262aa..98f3a272a36 100644 --- a/chromium/content/renderer/pepper/ppb_audio_impl.cc +++ b/chromium/content/renderer/pepper/ppb_audio_impl.cc @@ -152,20 +152,15 @@ int32_t PPB_Audio_Impl::GetSyncSocket(int* sync_socket) { return GetSyncSocketImpl(sync_socket); } -int32_t PPB_Audio_Impl::GetSharedMemory(base::SharedMemory** shm, - uint32_t* shm_size) { - return GetSharedMemoryImpl(shm, shm_size); +int32_t PPB_Audio_Impl::GetSharedMemory(base::UnsafeSharedMemoryRegion** shm) { + return GetSharedMemoryImpl(shm); } void PPB_Audio_Impl::OnSetStreamInfo( - base::SharedMemoryHandle shared_memory_handle, - size_t shared_memory_size, + base::UnsafeSharedMemoryRegion shared_memory_region, base::SyncSocket::Handle socket_handle) { EnterResourceNoLock<PPB_AudioConfig_API> enter(config_, true); - SetStreamInfo(pp_instance(), - shared_memory_handle, - shared_memory_size, - socket_handle, + SetStreamInfo(pp_instance(), std::move(shared_memory_region), socket_handle, enter.object()->GetSampleRate(), enter.object()->GetSampleFrameCount()); } diff --git a/chromium/content/renderer/pepper/ppb_audio_impl.h b/chromium/content/renderer/pepper/ppb_audio_impl.h index e0618ffb29d..abcd04b08a4 100644 --- a/chromium/content/renderer/pepper/ppb_audio_impl.h +++ b/chromium/content/renderer/pepper/ppb_audio_impl.h @@ -10,7 +10,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/memory/shared_memory.h" +#include "base/memory/unsafe_shared_memory_region.h" #include "base/sync_socket.h" #include "content/public/renderer/plugin_instance_throttler.h" #include "content/renderer/pepper/audio_helper.h" @@ -47,8 +47,7 @@ class PPB_Audio_Impl : public ppapi::Resource, int32_t Open(PP_Resource config_id, scoped_refptr<ppapi::TrackedCallback> create_callback) override; int32_t GetSyncSocket(int* sync_socket) override; - int32_t GetSharedMemory(base::SharedMemory** shm, - uint32_t* shm_size) override; + int32_t GetSharedMemory(base::UnsafeSharedMemoryRegion** shm) override; void SetVolume(double volume); @@ -56,8 +55,7 @@ class PPB_Audio_Impl : public ppapi::Resource, ~PPB_Audio_Impl() override; // AudioHelper implementation. - void OnSetStreamInfo(base::SharedMemoryHandle shared_memory_handle, - size_t shared_memory_size_, + void OnSetStreamInfo(base::UnsafeSharedMemoryRegion shared_memory_region, base::SyncSocket::Handle socket) override; // PluginInstanceThrottler::Observer implementation. diff --git a/chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc b/chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc index 50f971cd3d4..4e2717ba4b3 100644 --- a/chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc +++ b/chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc @@ -68,7 +68,7 @@ PP_Resource PPB_Graphics3D_Impl::CreateRaw( PP_Resource share_context, const gpu::ContextCreationAttribs& attrib_helper, gpu::Capabilities* capabilities, - base::SharedMemoryHandle* shared_state_handle, + const base::UnsafeSharedMemoryRegion** shared_state_region, gpu::CommandBufferId* command_buffer_id) { PPB_Graphics3D_API* share_api = nullptr; if (share_context) { @@ -80,7 +80,7 @@ PP_Resource PPB_Graphics3D_Impl::CreateRaw( scoped_refptr<PPB_Graphics3D_Impl> graphics_3d( new PPB_Graphics3D_Impl(instance)); if (!graphics_3d->InitRaw(share_api, attrib_helper, capabilities, - shared_state_handle, command_buffer_id)) + shared_state_region, command_buffer_id)) return 0; return graphics_3d->GetReference(); } @@ -125,11 +125,6 @@ void PPB_Graphics3D_Impl::EnsureWorkVisible() { } void PPB_Graphics3D_Impl::TakeFrontBuffer() { - if (!taken_front_buffer_.IsZero()) { - DLOG(ERROR) - << "TakeFrontBuffer should only be called once before DoSwapBuffers"; - return; - } taken_front_buffer_ = GenerateMailbox(); command_buffer_->TakeFrontBuffer(taken_front_buffer_); } @@ -195,7 +190,6 @@ int32_t PPB_Graphics3D_Impl::DoSwapBuffers(const gpu::SyncToken& sync_token, viz::TransferableResource::MakeGLOverlay(taken_front_buffer_, GL_LINEAR, target, sync_token, size, is_overlay_candidate); - taken_front_buffer_.SetZero(); HostGlobals::Get() ->GetInstance(pp_instance()) ->CommitTransferableResource(resource); @@ -214,7 +208,7 @@ bool PPB_Graphics3D_Impl::InitRaw( PPB_Graphics3D_API* share_context, const gpu::ContextCreationAttribs& requested_attribs, gpu::Capabilities* capabilities, - base::SharedMemoryHandle* shared_state_handle, + const base::UnsafeSharedMemoryRegion** shared_state_region, gpu::CommandBufferId* command_buffer_id) { PepperPluginInstanceImpl* plugin_instance = HostGlobals::Get()->GetInstance(pp_instance()); @@ -279,8 +273,8 @@ bool PPB_Graphics3D_Impl::InitRaw( command_buffer_->SetGpuControlClient(this); - if (shared_state_handle) - *shared_state_handle = command_buffer_->GetSharedStateHandle(); + if (shared_state_region) + *shared_state_region = &command_buffer_->GetSharedStateRegion(); if (capabilities) *capabilities = command_buffer_->GetCapabilities(); if (command_buffer_id) diff --git a/chromium/content/renderer/pepper/ppb_graphics_3d_impl.h b/chromium/content/renderer/pepper/ppb_graphics_3d_impl.h index 396faa7e1aa..389d2912861 100644 --- a/chromium/content/renderer/pepper/ppb_graphics_3d_impl.h +++ b/chromium/content/renderer/pepper/ppb_graphics_3d_impl.h @@ -10,7 +10,7 @@ #include <memory> #include "base/macros.h" -#include "base/memory/shared_memory.h" +#include "base/memory/unsafe_shared_memory_region.h" #include "base/memory/weak_ptr.h" #include "gpu/command_buffer/client/gpu_control_client.h" #include "gpu/command_buffer/common/command_buffer_id.h" @@ -30,12 +30,13 @@ namespace content { class PPB_Graphics3D_Impl : public ppapi::PPB_Graphics3D_Shared, public gpu::GpuControlClient { public: - static PP_Resource CreateRaw(PP_Instance instance, - PP_Resource share_context, - const gpu::ContextCreationAttribs& attrib_helper, - gpu::Capabilities* capabilities, - base::SharedMemoryHandle* shared_state_handle, - gpu::CommandBufferId* command_buffer_id); + static PP_Resource CreateRaw( + PP_Instance instance, + PP_Resource share_context, + const gpu::ContextCreationAttribs& attrib_helper, + gpu::Capabilities* capabilities, + const base::UnsafeSharedMemoryRegion** shared_state_region, + gpu::CommandBufferId* command_buffer_id); // PPB_Graphics3D_API trusted implementation. PP_Bool SetGetBuffer(int32_t transfer_buffer_id) override; @@ -82,7 +83,7 @@ class PPB_Graphics3D_Impl : public ppapi::PPB_Graphics3D_Shared, bool InitRaw(PPB_Graphics3D_API* share_context, const gpu::ContextCreationAttribs& requested_attribs, gpu::Capabilities* capabilities, - base::SharedMemoryHandle* shared_state_handle, + const base::UnsafeSharedMemoryRegion** shared_state_region, gpu::CommandBufferId* command_buffer_id); // GpuControlClient implementation. diff --git a/chromium/content/renderer/pepper/renderer_ppapi_host_impl.cc b/chromium/content/renderer/pepper/renderer_ppapi_host_impl.cc index 2e9658abdbf..9568688db4f 100644 --- a/chromium/content/renderer/pepper/renderer_ppapi_host_impl.cc +++ b/chromium/content/renderer/pepper/renderer_ppapi_host_impl.cc @@ -237,6 +237,26 @@ RendererPpapiHostImpl::ShareSharedMemoryHandleWithRemote( return dispatcher_->ShareSharedMemoryHandleWithRemote(handle); } +base::UnsafeSharedMemoryRegion +RendererPpapiHostImpl::ShareUnsafeSharedMemoryRegionWithRemote( + const base::UnsafeSharedMemoryRegion& region) { + if (!dispatcher_) { + DCHECK(is_running_in_process_); + return region.Duplicate(); + } + return dispatcher_->ShareUnsafeSharedMemoryRegionWithRemote(region); +} + +base::ReadOnlySharedMemoryRegion +RendererPpapiHostImpl::ShareReadOnlySharedMemoryRegionWithRemote( + const base::ReadOnlySharedMemoryRegion& region) { + if (!dispatcher_) { + DCHECK(is_running_in_process_); + return region.Duplicate(); + } + return dispatcher_->ShareReadOnlySharedMemoryRegionWithRemote(region); +} + bool RendererPpapiHostImpl::IsRunningInProcess() const { return is_running_in_process_; } diff --git a/chromium/content/renderer/pepper/renderer_ppapi_host_impl.h b/chromium/content/renderer/pepper/renderer_ppapi_host_impl.h index d8d6eddaf93..a94ef56ae66 100644 --- a/chromium/content/renderer/pepper/renderer_ppapi_host_impl.h +++ b/chromium/content/renderer/pepper/renderer_ppapi_host_impl.h @@ -89,6 +89,10 @@ class RendererPpapiHostImpl : public RendererPpapiHost { bool should_close_source) override; base::SharedMemoryHandle ShareSharedMemoryHandleWithRemote( const base::SharedMemoryHandle& handle) override; + base::UnsafeSharedMemoryRegion ShareUnsafeSharedMemoryRegionWithRemote( + const base::UnsafeSharedMemoryRegion& region) override; + base::ReadOnlySharedMemoryRegion ShareReadOnlySharedMemoryRegionWithRemote( + const base::ReadOnlySharedMemoryRegion& region) override; bool IsRunningInProcess() const override; std::string GetPluginName() const override; void SetToExternalPluginHost() override; diff --git a/chromium/content/renderer/pepper/resource_creation_impl.cc b/chromium/content/renderer/pepper/resource_creation_impl.cc index 64c9d9dbaa5..418806ab0db 100644 --- a/chromium/content/renderer/pepper/resource_creation_impl.cc +++ b/chromium/content/renderer/pepper/resource_creation_impl.cc @@ -128,7 +128,7 @@ PP_Resource ResourceCreationImpl::CreateGraphics3DRaw( PP_Resource share_context, const gpu::ContextCreationAttribs& attrib_helper, gpu::Capabilities* capabilities, - base::SharedMemoryHandle* shared_state, + const base::UnsafeSharedMemoryRegion** shared_state, gpu::CommandBufferId* command_buffer_id) { return PPB_Graphics3D_Impl::CreateRaw(instance, share_context, attrib_helper, capabilities, shared_state, diff --git a/chromium/content/renderer/pepper/resource_creation_impl.h b/chromium/content/renderer/pepper/resource_creation_impl.h index df4c1fc07b5..d89ded28eac 100644 --- a/chromium/content/renderer/pepper/resource_creation_impl.h +++ b/chromium/content/renderer/pepper/resource_creation_impl.h @@ -60,7 +60,7 @@ class ResourceCreationImpl : public ppapi::thunk::ResourceCreationAPI { PP_Resource share_context, const gpu::ContextCreationAttribs& attrib_helper, gpu::Capabilities* capabilities, - base::SharedMemoryHandle* shared_state, + const base::UnsafeSharedMemoryRegion** shared_state, gpu::CommandBufferId* command_buffer_id) override; PP_Resource CreateHostResolver(PP_Instance instance) override; PP_Resource CreateHostResolverPrivate(PP_Instance instance) override; diff --git a/chromium/content/renderer/pepper/url_request_info_util.cc b/chromium/content/renderer/pepper/url_request_info_util.cc index dd7047665c1..f5b4028d7fa 100644 --- a/chromium/content/renderer/pepper/url_request_info_util.cc +++ b/chromium/content/renderer/pepper/url_request_info_util.cc @@ -171,14 +171,8 @@ bool CreateWebURLRequest(PP_Instance instance, dest->SetURL( frame->GetDocument().CompleteURL(WebString::FromUTF8(data->url))); - dest->SetDownloadToFile(data->stream_to_file); dest->SetReportUploadProgress(data->record_upload_progress); - if (data->stream_to_file) { - frame->BlinkFeatureUsageReport({static_cast<int>( - blink::mojom::WebFeature::kPPAPIURLRequestStreamToFile)}); - } - if (!data->method.empty()) dest->SetHTTPMethod(WebString::FromUTF8(data->method)); diff --git a/chromium/content/renderer/pepper/url_response_info_util.cc b/chromium/content/renderer/pepper/url_response_info_util.cc index e2e23fb308c..d7539ce56c0 100644 --- a/chromium/content/renderer/pepper/url_response_info_util.cc +++ b/chromium/content/renderer/pepper/url_response_info_util.cc @@ -6,18 +6,7 @@ #include <stdint.h> -#include "base/bind.h" -#include "base/files/file_path.h" -#include "base/location.h" -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "content/public/renderer/renderer_ppapi_host.h" -#include "content/renderer/pepper/pepper_file_ref_renderer_host.h" -#include "content/renderer/pepper/renderer_ppapi_host_impl.h" -#include "ipc/ipc_message.h" -#include "ppapi/proxy/ppapi_messages.h" #include "ppapi/shared_impl/url_response_info_data.h" -#include "third_party/blink/public/platform/file_path_conversion.h" #include "third_party/blink/public/platform/web_http_header_visitor.h" #include "third_party/blink/public/platform/web_string.h" #include "third_party/blink/public/platform/web_url.h" @@ -52,33 +41,10 @@ class HeadersToString : public WebHTTPHeaderVisitor { bool IsRedirect(int32_t status) { return status >= 300 && status <= 399; } -void DidCreateResourceHosts(const ppapi::URLResponseInfoData& in_data, - const base::FilePath& external_path, - int renderer_pending_host_id, - const DataFromWebURLResponseCallback& callback, - const std::vector<int>& browser_pending_host_ids) { - DCHECK_EQ(1U, browser_pending_host_ids.size()); - int browser_pending_host_id = 0; - - if (browser_pending_host_ids.size() == 1) - browser_pending_host_id = browser_pending_host_ids[0]; - - ppapi::URLResponseInfoData data = in_data; - - data.body_as_file_ref = - ppapi::MakeExternalFileRefCreateInfo(external_path, - std::string(), - browser_pending_host_id, - renderer_pending_host_id); - callback.Run(data); -} - } // namespace -void DataFromWebURLResponse(RendererPpapiHostImpl* host_impl, - PP_Instance pp_instance, - const WebURLResponse& response, - const DataFromWebURLResponseCallback& callback) { +ppapi::URLResponseInfoData DataFromWebURLResponse( + const WebURLResponse& response) { ppapi::URLResponseInfoData data; data.url = response.Url().GetString().Utf8(); data.status_code = response.HttpStatusCode(); @@ -91,31 +57,7 @@ void DataFromWebURLResponse(RendererPpapiHostImpl* host_impl, HeadersToString headers_to_string; response.VisitHTTPHeaderFields(&headers_to_string); data.headers = headers_to_string.buffer(); - - WebString file_path = response.DownloadFilePath(); - if (!file_path.IsEmpty()) { - base::FilePath external_path = blink::WebStringToFilePath(file_path); - // TODO(teravest): Write a utility function to create resource hosts in the - // renderer and browser. - PepperFileRefRendererHost* renderer_host = - new PepperFileRefRendererHost(host_impl, pp_instance, 0, external_path); - int renderer_pending_host_id = - host_impl->GetPpapiHost()->AddPendingResourceHost( - std::unique_ptr<ppapi::host::ResourceHost>(renderer_host)); - - std::vector<IPC::Message> create_msgs; - create_msgs.push_back(PpapiHostMsg_FileRef_CreateForRawFS(external_path)); - host_impl->CreateBrowserResourceHosts(pp_instance, - create_msgs, - base::Bind(&DidCreateResourceHosts, - data, - external_path, - renderer_pending_host_id, - callback)); - } else { - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(callback, data)); - } + return data; } } // namespace content diff --git a/chromium/content/renderer/pepper/url_response_info_util.h b/chromium/content/renderer/pepper/url_response_info_util.h index d7570627ed0..a4996086e40 100644 --- a/chromium/content/renderer/pepper/url_response_info_util.h +++ b/chromium/content/renderer/pepper/url_response_info_util.h @@ -5,8 +5,6 @@ #ifndef CONTENT_RENDERER_PEPPER_URL_RESPONSE_INFO_UTIL_H_ #define CONTENT_RENDERER_PEPPER_URL_RESPONSE_INFO_UTIL_H_ -#include "base/callback.h" -#include "ppapi/c/pp_instance.h" #include "ppapi/shared_impl/url_response_info_data.h" namespace blink { @@ -14,18 +12,9 @@ class WebURLResponse; } namespace content { -class RendererPpapiHostImpl; -typedef base::Callback<void(const ppapi::URLResponseInfoData&)> - DataFromWebURLResponseCallback; - -// The returned object will have one plugin reference to the "body_as_file_ref" -// if it's non-null. It's expected that the result of this function will be -// passed to the plugin. -void DataFromWebURLResponse(RendererPpapiHostImpl* host_impl, - PP_Instance pp_instance, - const blink::WebURLResponse& response, - const DataFromWebURLResponseCallback& callback); +ppapi::URLResponseInfoData DataFromWebURLResponse( + const blink::WebURLResponse& response); } // namespace content diff --git a/chromium/content/renderer/pepper/video_decoder_shim.cc b/chromium/content/renderer/pepper/video_decoder_shim.cc index 231a4f63044..ca39cdef7d7 100644 --- a/chromium/content/renderer/pepper/video_decoder_shim.cc +++ b/chromium/content/renderer/pepper/video_decoder_shim.cc @@ -929,20 +929,20 @@ void VideoDecoderShim::AssignPictureBuffers( NOTREACHED(); return; } - DCHECK_EQ(buffers.size(), pending_texture_mailboxes_.size()); + std::vector<gpu::Mailbox> mailboxes = host_->TakeMailboxes(); + DCHECK_EQ(buffers.size(), mailboxes.size()); GLuint num_textures = base::checked_cast<GLuint>(buffers.size()); std::vector<uint32_t> local_texture_ids(num_textures); gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL(); for (uint32_t i = 0; i < num_textures; i++) { DCHECK_EQ(1u, buffers[i].client_texture_ids().size()); - local_texture_ids[i] = gles2->CreateAndConsumeTextureCHROMIUM( - pending_texture_mailboxes_[i].name); + local_texture_ids[i] = + gles2->CreateAndConsumeTextureCHROMIUM(mailboxes[i].name); // Map the plugin texture id to the local texture id. uint32_t plugin_texture_id = buffers[i].client_texture_ids()[0]; texture_id_map_[plugin_texture_id] = local_texture_ids[i]; available_textures_.insert(plugin_texture_id); } - pending_texture_mailboxes_.clear(); SendPictures(); } @@ -1026,13 +1026,9 @@ void VideoDecoderShim::OnOutputComplete(std::unique_ptr<PendingFrame> frame) { available_textures_.clear(); FlushCommandBuffer(); - DCHECK(pending_texture_mailboxes_.empty()); - for (uint32_t i = 0; i < texture_pool_size_; i++) - pending_texture_mailboxes_.push_back(gpu::Mailbox::Generate()); - - host_->RequestTextures(texture_pool_size_, - frame->video_frame->coded_size(), GL_TEXTURE_2D, - pending_texture_mailboxes_); + host_->ProvidePictureBuffers(texture_pool_size_, media::PIXEL_FORMAT_ARGB, + 1, frame->video_frame->coded_size(), + GL_TEXTURE_2D); texture_size_ = frame->video_frame->coded_size(); } diff --git a/chromium/content/renderer/pepper/video_decoder_shim.h b/chromium/content/renderer/pepper/video_decoder_shim.h index 16e93d716ff..44a1b6d4f00 100644 --- a/chromium/content/renderer/pepper/video_decoder_shim.h +++ b/chromium/content/renderer/pepper/video_decoder_shim.h @@ -14,7 +14,6 @@ #include "base/containers/queue.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "gpu/command_buffer/common/mailbox.h" #include "media/base/video_decoder_config.h" #include "media/video/video_decode_accelerator.h" #include "ppapi/c/pp_codecs.h" @@ -92,8 +91,6 @@ class VideoDecoderShim : public media::VideoDecodeAccelerator { TextureIdSet available_textures_; // Track textures that are no longer needed (these are plugin ids.) TextureIdSet textures_to_dismiss_; - // Mailboxes for pending texture requests, to write to plugin's textures. - std::vector<gpu::Mailbox> pending_texture_mailboxes_; // Queue of completed decode ids, for notifying the host. using CompletedDecodeQueue = base::queue<uint32_t>; diff --git a/chromium/content/renderer/pepper/video_encoder_shim.cc b/chromium/content/renderer/pepper/video_encoder_shim.cc index 58d4391f145..a8ce1b77691 100644 --- a/chromium/content/renderer/pepper/video_encoder_shim.cc +++ b/chromium/content/renderer/pepper/video_encoder_shim.cc @@ -487,8 +487,9 @@ void VideoEncoderShim::OnBitstreamBufferReady( bool key_frame) { DCHECK(RenderThreadImpl::current()); - host_->BitstreamBufferReady(bitstream_buffer_id, payload_size, key_frame, - frame->timestamp()); + host_->BitstreamBufferReady(bitstream_buffer_id, + media::BitstreamBufferMetadata( + payload_size, key_frame, frame->timestamp())); } void VideoEncoderShim::OnNotifyError( diff --git a/chromium/content/renderer/push_messaging/push_messaging_client.cc b/chromium/content/renderer/push_messaging/push_messaging_client.cc index 9fc24d41d5d..512d3e23f06 100644 --- a/chromium/content/renderer/push_messaging/push_messaging_client.cc +++ b/chromium/content/renderer/push_messaging/push_messaging_client.cc @@ -21,7 +21,7 @@ #include "third_party/blink/public/platform/modules/push_messaging/web_push_error.h" #include "third_party/blink/public/platform/modules/push_messaging/web_push_subscription.h" #include "third_party/blink/public/platform/modules/push_messaging/web_push_subscription_options.h" -#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_registration.h" +#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_registration.h" #include "third_party/blink/public/platform/web_string.h" #include "third_party/blink/public/web/web_console_message.h" #include "third_party/blink/public/web/web_local_frame.h" diff --git a/chromium/content/renderer/render_frame_impl.cc b/chromium/content/renderer/render_frame_impl.cc index c027c4df342..f6adabc683c 100644 --- a/chromium/content/renderer/render_frame_impl.cc +++ b/chromium/content/renderer/render_frame_impl.cc @@ -35,6 +35,8 @@ #include "base/stl_util.h" #include "base/strings/string16.h" #include "base/strings/string_piece.h" +#include "base/strings/string_split.h" +#include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/task_runner_util.h" #include "base/task_scheduler/post_task.h" @@ -61,12 +63,12 @@ #include "content/common/renderer_host.mojom.h" #include "content/common/savable_subframe.h" #include "content/common/service_worker/service_worker_types.h" -#include "content/common/service_worker/service_worker_utils.h" #include "content/common/swapped_out_messages.h" #include "content/common/view_messages.h" #include "content/public/common/appcache_info.h" #include "content/public/common/bind_interface_helpers.h" #include "content/public/common/bindings_policy.h" +#include "content/public/common/browser_side_navigation_policy.h" #include "content/public/common/content_constants.h" #include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" @@ -101,7 +103,7 @@ #include "content/renderer/external_popup_menu.h" #include "content/renderer/frame_owner_properties.h" #include "content/renderer/gpu/gpu_benchmarking_extension.h" -#include "content/renderer/gpu/render_widget_compositor.h" +#include "content/renderer/gpu/layer_tree_view.h" #include "content/renderer/history_entry.h" #include "content/renderer/history_serialization.h" #include "content/renderer/image_downloader/image_downloader_impl.h" @@ -115,17 +117,20 @@ #include "content/renderer/loader/tracked_child_url_loader_factory_bundle.h" #include "content/renderer/loader/web_url_loader_impl.h" #include "content/renderer/loader/web_url_request_util.h" +#include "content/renderer/loader/web_worker_fetch_context_impl.h" #include "content/renderer/loader/weburlresponse_extradata_impl.h" +#include "content/renderer/low_memory_mode_controller.h" #include "content/renderer/manifest/manifest_change_notifier.h" #include "content/renderer/manifest/manifest_manager.h" -#include "content/renderer/media/audio_device_factory.h" -#include "content/renderer/media/audio_output_ipc_factory.h" -#include "content/renderer/media/audio_renderer_sink_cache.h" +#include "content/renderer/media/audio/audio_device_factory.h" +#include "content/renderer/media/audio/audio_output_ipc_factory.h" +#include "content/renderer/media/audio/audio_renderer_sink_cache.h" #include "content/renderer/media/media_permission_dispatcher.h" #include "content/renderer/media/stream/media_stream_device_observer.h" #include "content/renderer/media/stream/user_media_client_impl.h" #include "content/renderer/media/webrtc/rtc_peer_connection_handler.h" #include "content/renderer/mojo/blink_interface_registry_impl.h" +#include "content/renderer/navigation_client.h" #include "content/renderer/navigation_state_impl.h" #include "content/renderer/pepper/pepper_audio_controller.h" #include "content/renderer/pepper/plugin_instance_throttler_impl.h" @@ -142,13 +147,10 @@ #include "content/renderer/service_worker/service_worker_network_provider.h" #include "content/renderer/service_worker/service_worker_provider_context.h" #include "content/renderer/service_worker/web_service_worker_provider_impl.h" -#include "content/renderer/service_worker/worker_fetch_context_impl.h" #include "content/renderer/shared_worker/shared_worker_repository.h" #include "content/renderer/skia_benchmarking_extension.h" -#include "content/renderer/speech_recognition_dispatcher.h" #include "content/renderer/stats_collection_controller.h" #include "content/renderer/v8_value_converter_impl.h" -#include "content/renderer/web_frame_utils.h" #include "content/renderer/web_ui_extension.h" #include "content/renderer/web_ui_extension_data.h" #include "crypto/sha2.h" @@ -161,6 +163,7 @@ #include "net/http/http_util.h" #include "ppapi/buildflags/buildflags.h" #include "services/network/public/cpp/features.h" +#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" #include "services/network/public/mojom/request_context_frame_type.mojom.h" #include "services/service_manager/public/cpp/connector.h" #include "services/service_manager/public/cpp/interface_provider.h" @@ -168,15 +171,18 @@ #include "services/ui/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" +#include "third_party/blink/public/common/service_worker/service_worker_utils.h" #include "third_party/blink/public/mojom/page/page_visibility_state.mojom.h" #include "third_party/blink/public/platform/file_path_conversion.h" #include "third_party/blink/public/platform/interface_provider.h" #include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom-shared.h" #include "third_party/blink/public/platform/modules/permissions/permission.mojom.h" -#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_network_provider.h" +#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h" #include "third_party/blink/public/platform/url_conversion.h" #include "third_party/blink/public/platform/web_data.h" #include "third_party/blink/public/platform/web_focus_type.h" +#include "third_party/blink/public/platform/web_http_body.h" #include "third_party/blink/public/platform/web_keyboard_event.h" #include "third_party/blink/public/platform/web_media_player.h" #include "third_party/blink/public/platform/web_media_player_source.h" @@ -202,6 +208,7 @@ #include "third_party/blink/public/web/web_local_frame.h" #include "third_party/blink/public/web/web_media_stream_registry.h" #include "third_party/blink/public/web/web_navigation_policy.h" +#include "third_party/blink/public/web/web_navigation_timings.h" #include "third_party/blink/public/web/web_plugin.h" #include "third_party/blink/public/web/web_plugin_container.h" #include "third_party/blink/public/web/web_plugin_document.h" @@ -231,6 +238,12 @@ #include "content/renderer/pepper/plugin_module.h" #endif +#if defined(OS_WIN) +#include "base/process/kill.h" +#elif defined(OS_POSIX) +#include <signal.h> +#endif + #if defined(OS_ANDROID) #include <cpu-features.h> @@ -301,12 +314,16 @@ namespace content { // Helper struct keeping track in one place of all the parameters the browser // provided to the renderer to commit a navigation. struct PendingNavigationParams { - PendingNavigationParams(const CommonNavigationParams& common_params, - const RequestNavigationParams& request_params, - base::TimeTicks time_commit_requested) + PendingNavigationParams( + const CommonNavigationParams& common_params, + const RequestNavigationParams& request_params, + base::TimeTicks time_commit_requested, + content::mojom::FrameNavigationControl::CommitNavigationCallback + commit_callback) : common_params(common_params), request_params(request_params), - time_commit_requested(time_commit_requested) {} + time_commit_requested(time_commit_requested), + commit_callback_(std::move(commit_callback)) {} ~PendingNavigationParams() = default; CommonNavigationParams common_params; @@ -314,13 +331,13 @@ struct PendingNavigationParams { // Time when RenderFrameImpl::CommitNavigation() is called. base::TimeTicks time_commit_requested; + + content::mojom::FrameNavigationControl::CommitNavigationCallback + commit_callback_; }; namespace { -const base::Feature kConsumeGestureOnNavigation = { - "ConsumeGestureOnNavigation", base::FEATURE_ENABLED_BY_DEFAULT}; - const int kExtraCharsBeforeAndAfterSelection = 100; // Maximum number of burst download requests allowed. @@ -422,8 +439,7 @@ WebURLRequest CreateURLRequestForNavigation( const CommonNavigationParams& common_params, const RequestNavigationParams& request_params, std::unique_ptr<NavigationResponseOverrideParameters> response_override, - bool is_view_source_mode_enabled, - bool is_same_document_navigation) { + bool is_view_source_mode_enabled) { // Use the original navigation url to construct the WebURLRequest. The // WebURLloaderImpl will replay the redirects afterwards and will eventually // commit the final url. @@ -456,10 +472,11 @@ WebURLRequest CreateURLRequestForNavigation( request.SetHTTPReferrer(web_referrer, common_params.referrer.policy); } - request.SetIsSameDocumentNavigation(is_same_document_navigation); request.SetPreviewsState( static_cast<WebURLRequest::PreviewsState>(common_params.previews_state)); + request.SetOriginPolicy(WebString::FromUTF8(common_params.origin_policy)); + auto extra_data = std::make_unique<RequestExtraData>(); extra_data->set_navigation_response_override(std::move(response_override)); extra_data->set_navigation_initiated_by_renderer( @@ -467,56 +484,17 @@ WebURLRequest CreateURLRequestForNavigation( request.SetExtraData(std::move(extra_data)); request.SetWasDiscarded(request_params.was_discarded); - // Set the ui timestamp for this navigation. Currently the timestamp here is - // only non empty when the navigation was triggered by an Android intent. The - // timestamp is converted to a double version supported by blink. It will be - // passed back to the browser in the DidCommitProvisionalLoad and the - // DocumentLoadComplete IPCs. - base::TimeDelta ui_timestamp = common_params.ui_timestamp - base::TimeTicks(); - request.SetUiStartTime(ui_timestamp.InSecondsF()); - request.SetInputPerfMetricReportPolicy( - static_cast<WebURLRequest::InputToLoadPerfMetricReportPolicy>( - common_params.report_type)); return request; } -// Sanitizes the navigation_start timestamp for browser-initiated navigations, -// where the browser possibly has a better notion of start time than the -// renderer. In the case of cross-process navigations, this carries over the -// time of finishing the onbeforeunload handler of the previous page. -// TimeTicks is sometimes not monotonic across processes, and because -// |browser_navigation_start| is likely before this process existed, -// InterProcessTimeTicksConverter won't help. The timestamp is sanitized by -// clamping it to renderer_navigation_start, initialized earlier in the call -// stack. -base::TimeTicks SanitizeNavigationTiming( - const base::TimeTicks& browser_navigation_start, - const base::TimeTicks& renderer_navigation_start) { - DCHECK(!browser_navigation_start.is_null()); - return std::min(browser_navigation_start, renderer_navigation_start); -} - CommonNavigationParams MakeCommonNavigationParams( - const blink::WebFrameClient::NavigationPolicyInfo& info, + const blink::WebLocalFrameClient::NavigationPolicyInfo& info, int load_flags) { Referrer referrer( GURL(info.url_request.HttpHeaderField(WebString::FromUTF8("Referer")) .Latin1()), info.url_request.GetReferrerPolicy()); - // Set the ui timestamp for this navigation. Currently the timestamp here is - // only non empty when the navigation was triggered by an Android intent, or - // by the user clicking on a link. The timestamp is converted from a double - // version supported by blink. It will be passed back to the renderer in the - // CommitNavigation IPC, and then back to the browser again in the - // DidCommitProvisionalLoad and the DocumentLoadComplete IPCs. - base::TimeTicks ui_timestamp = - base::TimeTicks() + - base::TimeDelta::FromSecondsD(info.url_request.UiStartTime()); - FrameMsg_UILoadMetricsReportType::Value report_type = - static_cast<FrameMsg_UILoadMetricsReportType::Value>( - info.url_request.InputPerfMetricReportPolicy()); - // No history-navigation is expected to happen. DCHECK(info.navigation_type != blink::kWebNavigationTypeBackForward); @@ -549,8 +527,7 @@ CommonNavigationParams MakeCommonNavigationParams( DCHECK(extra_data); return CommonNavigationParams( info.url_request.Url(), referrer, extra_data->transition_type(), - navigation_type, true, info.replaces_current_history_item, ui_timestamp, - report_type, GURL(), GURL(), + navigation_type, true, info.replaces_current_history_item, GURL(), GURL(), static_cast<PreviewsState>(info.url_request.GetPreviewsState()), base::TimeTicks::Now(), info.url_request.HttpMethod().Latin1(), GetRequestBodyForWebURLRequest(info.url_request), source_location, @@ -816,6 +793,139 @@ blink::mojom::BlobURLTokenPtrInfo CloneBlobURLToken( return result; } +// Creates a fully functional DocumentState in the case where we do not have +// pending_navigation_params_ available in the RenderFrameImpl. +std::unique_ptr<DocumentState> BuildDocumentState() { + std::unique_ptr<DocumentState> document_state = + std::make_unique<DocumentState>(); + document_state->set_navigation_state( + NavigationStateImpl::CreateContentInitiated()); + return document_state; +} + +// Creates a fully functional DocumentState in the case where we have +// pending_navigation_params_ available in the RenderFrameImpl. +// TODO(ahemery): This currently removes the callback from the pending params +// which is a bit counterintuitive. We would like to leave +// 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) { + std::unique_ptr<DocumentState> document_state(new DocumentState()); + InternalDocumentStateData* internal_data = + InternalDocumentStateData::FromDocumentState(document_state.get()); + + const CommonNavigationParams& common_params = + pending_navigation_params->common_params; + const RequestNavigationParams& request_params = + pending_navigation_params->request_params; + + DCHECK(!common_params.navigation_start.is_null()); + DCHECK(!common_params.url.SchemeIs(url::kJavaScriptScheme)); + + if (common_params.navigation_type == FrameMsg_Navigate_Type::RESTORE) { + // We're doing a load of a page that was restored from the last session. + // By default this prefers the cache over loading + // (LOAD_SKIP_CACHE_VALIDATION) which can result in stale data for pages + // that are set to expire. We explicitly override that by setting the + // policy here so that as necessary we load from the network. + // + // TODO(davidben): Remove this in favor of passing a cache policy to the + // loadHistoryItem call in OnNavigate. That requires not overloading + // UseProtocolCachePolicy to mean both "normal load" and "determine cache + // policy based on load type, etc". + internal_data->set_cache_policy_override( + blink::mojom::FetchCacheMode::kDefault); + } + + internal_data->set_is_overriding_user_agent( + request_params.is_overriding_user_agent); + internal_data->set_must_reset_scroll_and_scale_state( + common_params.navigation_type == + FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL); + document_state->set_can_load_local_resources( + request_params.can_load_local_resources); + + 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); + document_state->set_was_load_data_with_base_url_request(load_data); + if (load_data) + document_state->set_data_url(common_params.url); + + document_state->set_navigation_state( + NavigationStateImpl::CreateBrowserInitiated( + pending_navigation_params->common_params, + pending_navigation_params->request_params, + pending_navigation_params->time_commit_requested, + std::move(pending_navigation_params->commit_callback_))); + return document_state; +} + +void ApplyFilePathAlias(blink::WebURLRequest* request) { + const base::CommandLine::StringType file_url_path_alias = + base::CommandLine::ForCurrentProcess()->GetSwitchValueNative( + switches::kFileUrlPathAlias); + if (file_url_path_alias.empty()) + return; + + const auto alias_mapping = + base::SplitString(file_url_path_alias, FILE_PATH_LITERAL("="), + base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + if (alias_mapping.size() != 2) { + LOG(ERROR) << "Invalid file path alias format."; + return; + } + +#if defined(OS_WIN) + base::string16 path = request->Url().GetString().Utf16(); + const base::string16 file_prefix = + base::ASCIIToUTF16(url::kFileScheme) + + base::ASCIIToUTF16(url::kStandardSchemeSeparator); +#else + std::string path = request->Url().GetString().Utf8(); + const std::string file_prefix = + std::string(url::kFileScheme) + url::kStandardSchemeSeparator; +#endif + if (!base::StartsWith(path, file_prefix + alias_mapping[0], + base::CompareCase::SENSITIVE)) { + return; + } + + base::ReplaceFirstSubstringAfterOffset(&path, 0, alias_mapping[0], + alias_mapping[1]); + request->SetURL(blink::WebURL(GURL(path))); +} + +// 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) { + blink::WebNavigationTimings renderer_navigation_timings; + + // Sanitizes the navigation_start timestamp for browser-initiated navigations, + // where the browser possibly has a better notion of start time than the + // renderer. In the case of cross-process navigations, this carries over the + // time of finishing the onbeforeunload handler of the previous page. + // TimeTicks is sometimes not monotonic across processes, and because + // |browser_navigation_start| is likely before this process existed, + // InterProcessTimeTicksConverter won't help. The timestamp is sanitized by + // clamping it to now. + DCHECK(!navigation_start.is_null()); + renderer_navigation_timings.navigation_start = + std::min(navigation_start, base::TimeTicks::Now()); + + renderer_navigation_timings.redirect_start = + browser_navigation_timings.redirect_start; + renderer_navigation_timings.redirect_end = + browser_navigation_timings.redirect_end; + renderer_navigation_timings.fetch_start = + browser_navigation_timings.fetch_start; + + return renderer_navigation_timings; +} + } // namespace class RenderFrameImpl::FrameURLLoaderFactory @@ -828,7 +938,8 @@ class RenderFrameImpl::FrameURLLoaderFactory std::unique_ptr<blink::WebURLLoader> CreateURLLoader( const WebURLRequest& request, - scoped_refptr<base::SingleThreadTaskRunner> task_runner) override { + std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle> + task_runner_handle) override { // This should not be called if the frame is detached. DCHECK(frame_); @@ -837,9 +948,18 @@ class RenderFrameImpl::FrameURLLoaderFactory frame_->GetFrameHost()->IssueKeepAliveHandle( mojo::MakeRequest(&keep_alive_handle)); } + scoped_refptr<network::SharedURLLoaderFactory> loader_factory = + frame_->GetLoaderFactoryBundle(); + if (request.GetRequestContext() == WebURLRequest::kRequestContextPrefetch && + frame_->prefetch_loader_factory_) { + // The frame should be alive when this factory is used. + loader_factory = + base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( + frame_->prefetch_loader_factory_.get()); + } return std::make_unique<WebURLLoaderImpl>( RenderThreadImpl::current()->resource_dispatcher(), - std::move(task_runner), frame_->GetLoaderFactoryBundle(), + std::move(task_runner_handle), std::move(loader_factory), std::move(keep_alive_handle)); } @@ -908,11 +1028,20 @@ void HandleChromeDebugURL(const GURL& url) { // base::debug::SetDumpWithoutCrashingFunction. Refer to the documentation // of base::debug::DumpWithoutCrashing for more details. base::debug::DumpWithoutCrashing(); +#if defined(OS_WIN) || defined(OS_POSIX) } else if (url == kChromeUIKillURL) { LOG(ERROR) << "Intentionally terminating current process because user" " navigated to " << url.spec(); - base::Process::TerminateCurrentProcessImmediately(1); + // Simulate termination such that the base::GetTerminationStatus() API will + // return TERMINATION_STATUS_PROCESS_WAS_KILLED. +#if defined(OS_WIN) + base::Process::TerminateCurrentProcessImmediately( + base::win::kProcessKilledExitCode); +#elif defined(OS_POSIX) + PCHECK(kill(base::Process::Current().Pid(), SIGTERM) == 0); +#endif +#endif // defined(OS_WIN) || defined(OS_POSIX) } else if (url == kChromeUIHangURL) { LOG(ERROR) << "Intentionally hanging ourselves with sleep infinite loop" << " because user navigated to " << url.spec(); @@ -1334,6 +1463,7 @@ RenderFrameImpl::RenderFrameImpl(CreateParams params) frame_bindings_control_binding_(this), frame_navigation_control_binding_(this), fullscreen_binding_(this), + navigation_client_impl_(nullptr), has_accessed_initial_document_(false), media_factory_(this, base::Bind(&RenderFrameImpl::RequestOverlayRoutingToken, @@ -1369,6 +1499,9 @@ RenderFrameImpl::RenderFrameImpl(CreateParams params) #endif manifest_manager_ = std::make_unique<ManifestManager>(this); + // TODO(ajwong): This always returns true as is_main_frame_ gets initialized + // later in RenderFrameImpl::Initialize(). Should the conditional be in + // RenderFrameImpl::Initialize()? https://crbug.com/840533 if (IsMainFrame()) { // Manages its own lifetime. new ManifestChangeNotifier(this); @@ -1401,6 +1534,12 @@ RenderFrameImpl::~RenderFrameImpl() { if (auto* factory = AudioOutputIPCFactory::get()) factory->MaybeDeregisterRemoteFactory(GetRoutingID()); + // |thread| may be null in tests. + if (auto* thread = RenderThreadImpl::current()) { + if (auto* controller = thread->low_memory_mode_controller()) + controller->OnFrameDestroyed(IsMainFrame()); + } + if (is_main_frame_) { // Ensure the RenderView doesn't point to this object, once it is destroyed. // TODO(nasko): Add a check that the |main_render_frame_| of |render_view_| @@ -1436,6 +1575,12 @@ void RenderFrameImpl::Initialize() { "parent", parent_id); } + // |thread| may be null in tests. + if (auto* thread = RenderThreadImpl::current()) { + if (auto* controller = thread->low_memory_mode_controller()) + controller->OnFrameCreated(IsMainFrame()); + } + #if BUILDFLAG(ENABLE_PLUGINS) new PepperBrowserConnection(this); #endif @@ -1562,14 +1707,14 @@ RenderWidgetFullscreenPepper* RenderFrameImpl::CreatePepperFullscreenContainer( // Synchronous IPC to obtain a routing id for the fullscreen widget. int32_t fullscreen_widget_routing_id = MSG_ROUTING_NONE; if (!RenderThreadImpl::current_render_message_filter() - ->CreateFullscreenWidget(render_view()->routing_id(), + ->CreateFullscreenWidget(render_view()->GetRoutingID(), std::move(widget_channel), &fullscreen_widget_routing_id)) { return nullptr; } RenderWidget::ShowCallback show_callback = - base::Bind(&RenderViewImpl::ShowCreatedFullscreenWidget, - render_view()->GetWeakPtr()); + base::BindOnce(&RenderViewImpl::ShowCreatedFullscreenWidget, + render_view()->GetWeakPtr()); // TODO(fsamuel): It's not clear if we should be passing in the // web ScreenInfo or the original ScreenInfo here. @@ -1778,6 +1923,7 @@ bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg) { IPC_MESSAGE_HANDLER(FrameMsg_SetOverlayRoutingToken, OnSetOverlayRoutingToken) IPC_MESSAGE_HANDLER(FrameMsg_NotifyUserActivation, OnNotifyUserActivation) + IPC_MESSAGE_HANDLER(FrameMsg_MediaPlayerActionAt, OnMediaPlayerActionAt) #if BUILDFLAG(USE_EXTERNAL_POPUP_MENU) #if defined(OS_MACOSX) @@ -1837,6 +1983,12 @@ void RenderFrameImpl::BindFrameNavigationControl( std::move(request), GetTaskRunner(blink::TaskType::kInternalIPC)); } +void RenderFrameImpl::BindNavigationClient( + mojom::NavigationClientAssociatedRequest request) { + navigation_client_impl_ = std::make_unique<NavigationClient>(this); + navigation_client_impl_->Bind(std::move(request)); +} + blink::mojom::ManifestManager& RenderFrameImpl::GetManifestManager() { return *manifest_manager_; } @@ -1897,6 +2049,12 @@ void RenderFrameImpl::OnSwapOut( bool is_main_frame = is_main_frame_; int routing_id = GetRoutingID(); + // Before |this| is destroyed, grab the TaskRunner to be used for sending the + // SwapOut ACK. This will be used to schedule SwapOut ACK to be sent after + // any postMessage IPCs scheduled from the unload event above. + scoped_refptr<base::SingleThreadTaskRunner> task_runner = + GetTaskRunner(blink::TaskType::kPostedMessage); + // Now that all of the cleanup is complete and the browser side is notified, // start using the RenderFrameProxy. // @@ -1931,15 +2089,23 @@ void RenderFrameImpl::OnSwapOut( // process that is now rendering the frame. proxy->SetReplicatedState(replicated_frame_state); - // Safe to exit if no one else is using the process. - // TODO(nasko): Remove the dependency on RenderViewImpl here and ref count - // the process based on the lifetime of this RenderFrameImpl object. - if (is_main_frame) - render_view->WasSwappedOut(); - // Notify the browser that this frame was swapped. Use the RenderThread - // directly because |this| is deleted. - RenderThread::Get()->Send(new FrameHostMsg_SwapOut_ACK(routing_id)); + // directly because |this| is deleted. Post a task to send the ACK, so that + // any postMessage IPCs scheduled from the unload handler are sent before + // the ACK (see https://crbug.com/857274). + auto send_swapout_ack = base::BindOnce( + [](int routing_id, bool is_main_frame) { + RenderThread::Get()->Send(new FrameHostMsg_SwapOut_ACK(routing_id)); + // Now that the unload handler, and any postMessages posted from it, + // have finished, and we've sent the swapout ACK, it's safe to exit if + // no one else is using the process. Release the process if we've + // swapped the main frame out, and hence transitioned the + // RenderView/Widget to swapped out state. + if (is_main_frame) + RenderProcess::current()->ReleaseProcess(); + }, + routing_id, is_main_frame); + task_runner->PostTask(FROM_HERE, std::move(send_swapout_ack)); } void RenderFrameImpl::OnSwapIn() { @@ -2311,8 +2477,8 @@ void RenderFrameImpl::OnPostMessageEvent( } void RenderFrameImpl::OnReload(bool bypass_cache) { - frame_->Reload(bypass_cache ? WebFrameLoadType::kReloadBypassingCache - : WebFrameLoadType::kReload); + frame_->StartReload(bypass_cache ? WebFrameLoadType::kReloadBypassingCache + : WebFrameLoadType::kReload); } void RenderFrameImpl::OnReloadLoFiImages() { @@ -2356,13 +2522,22 @@ bool RenderFrameImpl::RunJavaScriptDialog(JavaScriptDialogType type, message_length); } + if (is_main_frame_) + UMA_HISTOGRAM_COUNTS("JSDialogs.CharacterCount.MainFrame", message_length); + else + UMA_HISTOGRAM_COUNTS("JSDialogs.CharacterCount.Subframe", message_length); + + // 10k ought to be enough for anyone. + const base::string16::size_type kMaxMessageSize = 10 * 1024; + base::string16 truncated_message = message.substr(0, kMaxMessageSize); + bool success = false; base::string16 result_temp; if (!result) result = &result_temp; - Send(new FrameHostMsg_RunJavaScriptDialog(routing_id_, message, default_value, - type, &success, result)); + Send(new FrameHostMsg_RunJavaScriptDialog( + routing_id_, truncated_message, default_value, type, &success, result)); return success; } @@ -2426,10 +2601,8 @@ void RenderFrameImpl::DidFailProvisionalLoadInternal( // Make sure we never show errors in view source mode. frame_->EnableViewSourceMode(false); - DocumentState* document_state = - DocumentState::FromDocumentLoader(document_loader); - NavigationStateImpl* navigation_state = - static_cast<NavigationStateImpl*>(document_state->navigation_state()); + NavigationStateImpl* navigation_state = static_cast<NavigationStateImpl*>( + DocumentState::FromDocumentLoader(document_loader)->navigation_state()); // If this is a failed back/forward/reload navigation, then we need to do a // 'replace' load. This is necessary to avoid messing up session history. @@ -2442,13 +2615,23 @@ void RenderFrameImpl::DidFailProvisionalLoadInternal( if (!navigation_state->IsContentInitiated()) { pending_navigation_params_.reset(new PendingNavigationParams( navigation_state->common_params(), navigation_state->request_params(), - base::TimeTicks() // not used for failed navigation. - )); + base::TimeTicks(), // not used for failed navigation. + CommitNavigationCallback())); } - // Load an error page. + 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()); + LoadNavigationErrorPage(failed_request, error, replace, nullptr, - error_page_content); + error_page_content, std::move(document_state)); } void RenderFrameImpl::LoadNavigationErrorPage( @@ -2456,7 +2639,8 @@ void RenderFrameImpl::LoadNavigationErrorPage( const WebURLError& error, bool replace, HistoryEntry* entry, - const base::Optional<std::string>& error_page_content) { + const base::Optional<std::string>& error_page_content, + std::unique_ptr<blink::WebDocumentLoader::ExtraData> navigation_data) { blink::WebFrameLoadType frame_load_type = entry ? blink::WebFrameLoadType::kBackForward : blink::WebFrameLoadType::kStandard; @@ -2475,7 +2659,8 @@ void RenderFrameImpl::LoadNavigationErrorPage( 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); + frame_load_type, blank_history_item, + std::move(navigation_data)); return; } @@ -2490,7 +2675,7 @@ void RenderFrameImpl::LoadNavigationErrorPage( } LoadNavigationErrorPageInternal(error_html, GURL(kUnreachableWebDataURL), error.url(), replace, frame_load_type, - history_item); + history_item, std::move(navigation_data)); } void RenderFrameImpl::LoadNavigationErrorPageForHttpStatusError( @@ -2498,7 +2683,8 @@ void RenderFrameImpl::LoadNavigationErrorPageForHttpStatusError( const GURL& unreachable_url, int http_status, bool replace, - HistoryEntry* entry) { + HistoryEntry* entry, + std::unique_ptr<blink::WebDocumentLoader::ExtraData> navigation_data) { blink::WebFrameLoadType frame_load_type = entry ? blink::WebFrameLoadType::kBackForward : blink::WebFrameLoadType::kStandard; @@ -2508,9 +2694,10 @@ void RenderFrameImpl::LoadNavigationErrorPageForHttpStatusError( 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); + history_item, std::move(document_state)); } void RenderFrameImpl::LoadNavigationErrorPageInternal( @@ -2519,11 +2706,13 @@ void RenderFrameImpl::LoadNavigationErrorPageInternal( const GURL& error_url, bool replace, blink::WebFrameLoadType frame_load_type, - const blink::WebHistoryItem& history_item) { - frame_->LoadData(error_html, WebString::FromUTF8("text/html"), - WebString::FromUTF8("UTF-8"), error_page_url, error_url, - replace, frame_load_type, history_item, - blink::kWebHistoryDifferentDocumentLoad, false); + 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()); } void RenderFrameImpl::DidMeaningfulLayout( @@ -2646,11 +2835,11 @@ void RenderFrameImpl::LoadErrorPage(int reason) { this, frame_->GetDocumentLoader()->GetRequest(), error, &error_html, nullptr); - frame_->LoadData(error_html, WebString::FromUTF8("text/html"), - WebString::FromUTF8("UTF-8"), GURL(kUnreachableWebDataURL), - error.url(), true, blink::WebFrameLoadType::kStandard, - blink::WebHistoryItem(), - blink::kWebHistoryDifferentDocumentLoad, true); + 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()); } void RenderFrameImpl::ExecuteJavaScript(const base::string16& javascript) { @@ -2746,6 +2935,14 @@ void RenderFrameImpl::SetSelectedText(const base::string16& selection_text, static_cast<uint32_t>(offset), range)); } +void RenderFrameImpl::SetZoomLevel(double zoom_level) { + render_view_->UpdateZoomLevel(zoom_level); +} + +double RenderFrameImpl::GetZoomLevel() const { + return render_view_->page_zoom_level(); +} + void RenderFrameImpl::AddMessageToConsole(ConsoleMessageLevel level, const std::string& message) { blink::WebConsoleMessage::Level target_level = @@ -2868,7 +3065,9 @@ void RenderFrameImpl::CommitNavigation( base::Optional<std::vector<mojom::TransferrableURLLoaderPtr>> subresource_overrides, mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info, - const base::UnguessableToken& devtools_navigation_token) { + network::mojom::URLLoaderFactoryPtr prefetch_loader_factory, + const base::UnguessableToken& devtools_navigation_token, + CommitNavigationCallback callback) { DCHECK(!IsRendererDebugURL(common_params.url)); DCHECK( !FrameMsg_Navigate_Type::IsSameDocument(common_params.navigation_type)); @@ -2879,10 +3078,12 @@ void RenderFrameImpl::CommitNavigation( browser_side_navigation_pending_url_ == request_params.original_url && request_params.nav_entry_id == 0) { browser_side_navigation_pending_url_ = GURL(); + std::move(callback).Run(blink::mojom::CommitResult::Aborted); return; } controller_service_worker_info_ = std::move(controller_service_worker_info); + prefetch_loader_factory_ = std::move(prefetch_loader_factory); // 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. @@ -2908,9 +3109,12 @@ void RenderFrameImpl::CommitNavigation( if (request_params.is_view_source) frame_->EnableViewSourceMode(true); - pending_navigation_params_.reset(new PendingNavigationParams( - common_params, request_params, base::TimeTicks::Now())); - PrepareFrameForCommit(); + pending_navigation_params_.reset( + 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())); blink::WebFrameLoadType load_type = NavigationTypeToLoadType( common_params.navigation_type, common_params.should_replace_current_entry, @@ -2946,16 +3150,17 @@ void RenderFrameImpl::CommitNavigation( #endif if (is_main_frame_ && should_load_data_url) { LoadDataURL(common_params, request_params, frame_, load_type, - item_for_history_navigation, - blink::kWebHistoryDifferentDocumentLoad, is_client_redirect); + item_for_history_navigation, is_client_redirect, + std::move(document_state)); } else { WebURLRequest request = CreateURLRequestForCommit( common_params, request_params, std::move(url_loader_client_endpoints), head); - - frame_->CommitNavigation(request, load_type, item_for_history_navigation, - blink::kWebHistoryDifferentDocumentLoad, - is_client_redirect, devtools_navigation_token); + 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)); // 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, @@ -2999,7 +3204,8 @@ void RenderFrameImpl::CommitFailedNavigation( bool has_stale_copy_in_cache, int error_code, const base::Optional<std::string>& error_page_content, - std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories) { + std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loader_factories, + CommitFailedNavigationCallback callback) { DCHECK( !FrameMsg_Navigate_Type::IsSameDocument(common_params.navigation_type)); bool is_reload = @@ -3024,8 +3230,8 @@ void RenderFrameImpl::CommitFailedNavigation( pending_navigation_params_.reset(new PendingNavigationParams( common_params, request_params, - base::TimeTicks() // Not used for failed navigation. - )); + base::TimeTicks(), // Not used for failed navigation. + std::move(callback))); // Send the provisional load failure. WebURLError error( @@ -3035,12 +3241,14 @@ void RenderFrameImpl::CommitFailedNavigation( WebURLError::IsWebSecurityViolation::kFalse, common_params.url); WebURLRequest failed_request = CreateURLRequestForNavigation( common_params, request_params, - /*response_override=*/nullptr, frame_->IsViewSourceModeEnabled(), - false); // is_same_document_navigation + /*response_override=*/nullptr, frame_->IsViewSourceModeEnabled()); if (!ShouldDisplayErrorPageForFailedLoad(error_code, common_params.url)) { // The browser expects this frame to be loading an error page. Inform it // that the load stopped. + std::move(pending_navigation_params_->commit_callback_) + .Run(blink::mojom::CommitResult::Aborted); + pending_navigation_params_.reset(); Send(new FrameHostMsg_DidStopLoading(routing_id_)); browser_side_navigation_pending_ = false; browser_side_navigation_pending_url_ = GURL(); @@ -3058,6 +3266,9 @@ void RenderFrameImpl::CommitFailedNavigation( // either, as the frame has already been populated with something // unrelated to this navigation failure. In that case, just send a stop // IPC to the browser to unwind its state, and leave the frame as-is. + std::move(pending_navigation_params_->commit_callback_) + .Run(blink::mojom::CommitResult::Aborted); + pending_navigation_params_.reset(); Send(new FrameHostMsg_DidStopLoading(routing_id_)); } browser_side_navigation_pending_ = false; @@ -3109,8 +3320,10 @@ void RenderFrameImpl::CommitFailedNavigation( // 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())); LoadNavigationErrorPage(failed_request, error, replace, history_entry.get(), - error_page_content); + error_page_content, std::move(document_state)); if (!weak_this) return; } @@ -3134,11 +3347,14 @@ void RenderFrameImpl::CommitSameDocumentNavigation( common_params.has_user_gesture ? new blink::WebScopedUserGesture(frame_) : nullptr); + // TODO(ahemery): |pending_navigation_params_| below is solely used by + // IsBrowserInitiated() in DecidePolicyForNavigation. Try and find a a way to + // avoid having to create the entire structure just for this. pending_navigation_params_.reset(new PendingNavigationParams( common_params, request_params, - base::TimeTicks() // Not used for same-document navigation. - )); - PrepareFrameForCommit(); + base::TimeTicks(), // Not used for same-document navigation. + CommitNavigationCallback())); + PrepareFrameForCommit(common_params.url, request_params); blink::WebFrameLoadType load_type = NavigationTypeToLoadType( common_params.navigation_type, common_params.should_replace_current_entry, @@ -3231,7 +3447,8 @@ void RenderFrameImpl::SetHostZoomLevel(const GURL& url, double zoom_level) { #endif } -// blink::WebFrameClient implementation ---------------------------------------- +// blink::WebLocalFrameClient implementation +// ---------------------------------------- blink::WebPlugin* RenderFrameImpl::CreatePlugin( const blink::WebPluginParams& params) { @@ -3277,7 +3494,7 @@ blink::WebMediaPlayer* RenderFrameImpl::CreateMediaPlayer( const blink::WebString& sink_id, blink::WebLayerTreeView* layer_tree_view) { const cc::LayerTreeSettings& settings = - GetRenderWidget()->compositor()->GetLayerTreeSettings(); + GetRenderWidget()->layer_tree_view()->GetLayerTreeSettings(); return media_factory_.CreateMediaPlayer(source, client, encrypted_client, initial_cdm, sink_id, layer_tree_view, settings); @@ -3321,36 +3538,44 @@ RenderFrameImpl::CreateWorkerFetchContext() { ServiceWorkerNetworkProvider::FromWebServiceWorkerNetworkProvider( web_provider); mojom::ServiceWorkerWorkerClientRequest service_worker_client_request; + mojom::ServiceWorkerWorkerClientRegistryPtrInfo + service_worker_worker_client_registry_ptr_info; mojom::ServiceWorkerContainerHostPtrInfo container_host_ptr_info; ServiceWorkerProviderContext* provider_context = provider->context(); // Some sandboxed iframes are not allowed to use service worker so don't have // a real service worker provider, so the provider context is null. if (provider_context) { - service_worker_client_request = - provider_context->CreateWorkerClientRequest(); + provider_context->CloneWorkerClientRegistry( + mojo::MakeRequest(&service_worker_worker_client_registry_ptr_info)); + + mojom::ServiceWorkerWorkerClientPtr worker_client_ptr; + service_worker_client_request = mojo::MakeRequest(&worker_client_ptr); + provider_context->RegisterWorkerClient(std::move(worker_client_ptr)); + // TODO(horo): Use this host pointer also when S13nServiceWorker is not // enabled once we support navigator.serviceWorker on dedicated workers: // crbug.com/371690. Currently we use this only to call // GetControllerServiceWorker() from the worker thread if S13nServiceWorker // is enabled. - if (ServiceWorkerUtils::IsServicificationEnabled()) + if (blink::ServiceWorkerUtils::IsServicificationEnabled()) container_host_ptr_info = provider_context->CloneContainerHostPtrInfo(); } - std::unique_ptr<WorkerFetchContextImpl> worker_fetch_context = - std::make_unique<WorkerFetchContextImpl>( - std::move(service_worker_client_request), - std::move(container_host_ptr_info), GetLoaderFactoryBundle()->Clone(), - GetLoaderFactoryBundle()->CloneWithoutDefaultFactory(), - GetContentClient()->renderer()->CreateURLLoaderThrottleProvider( - URLLoaderThrottleProviderType::kWorker), - GetContentClient() - ->renderer() - ->CreateWebSocketHandshakeThrottleProvider(), - ChildThreadImpl::current()->thread_safe_sender(), - RenderThreadImpl::current()->GetIOTaskRunner()); - - worker_fetch_context->set_parent_frame_id(routing_id_); + auto worker_fetch_context = std::make_unique<WebWorkerFetchContextImpl>( + render_view_->renderer_preferences(), + std::move(service_worker_client_request), + std::move(service_worker_worker_client_registry_ptr_info), + std::move(container_host_ptr_info), GetLoaderFactoryBundle()->Clone(), + GetLoaderFactoryBundle()->CloneWithoutDefaultFactory(), + GetContentClient()->renderer()->CreateURLLoaderThrottleProvider( + URLLoaderThrottleProviderType::kWorker), + GetContentClient() + ->renderer() + ->CreateWebSocketHandshakeThrottleProvider(), + ChildThreadImpl::current()->thread_safe_sender(), + ChildThreadImpl::current()->GetConnector()->Clone()); + + worker_fetch_context->set_ancestor_frame_id(routing_id_); worker_fetch_context->set_site_for_cookies( frame_->GetDocument().SiteForCookies()); worker_fetch_context->set_is_secure_context( @@ -3687,8 +3912,9 @@ void RenderFrameImpl::DidMatchCSS( observer.DidMatchCSS(newly_matching_selectors, stopped_matching_selectors); } -void RenderFrameImpl::SetHasReceivedUserGesture() { - Send(new FrameHostMsg_SetHasReceivedUserGesture(routing_id_)); +void RenderFrameImpl::UpdateUserActivationState( + blink::UserActivationUpdateType update_type) { + Send(new FrameHostMsg_UpdateUserActivationState(routing_id_, update_type)); } void RenderFrameImpl::SetHasReceivedUserGestureBeforeNavigation(bool value) { @@ -3744,6 +3970,7 @@ void RenderFrameImpl::DidAddMessageToConsole( void RenderFrameImpl::DownloadURL( const blink::WebURLRequest& request, + CrossOriginRedirects cross_origin_redirect_behavior, mojo::ScopedMessagePipeHandle blob_url_token) { if (ShouldThrottleDownload()) return; @@ -3756,6 +3983,8 @@ void RenderFrameImpl::DownloadURL( params.initiator_origin = request.RequestorOrigin(); if (request.GetSuggestedFilename().has_value()) params.suggested_name = request.GetSuggestedFilename()->Utf16(); + params.follow_cross_origin_redirects = + (cross_origin_redirect_behavior == CrossOriginRedirects::kFollow); params.blob_url_token = blob_url_token.release(); Send(new FrameHostMsg_DownloadUrl(params)); @@ -3791,95 +4020,55 @@ void RenderFrameImpl::WillSubmitForm(const blink::WebFormElement& form) { void RenderFrameImpl::DidCreateDocumentLoader( blink::WebDocumentLoader* document_loader) { - bool content_initiated = !pending_navigation_params_.get(); + // 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(); DocumentState* document_state = DocumentState::FromDocumentLoader(document_loader); if (!document_state) { - document_state = new DocumentState; - document_loader->SetExtraData(document_state); - if (!content_initiated) - PopulateDocumentStateFromPending(document_state); - } - - // Carry over the user agent override flag, if it exists. - // TODO(lukasza): https://crbug.com/426555: Need OOPIF support for propagating - // user agent overrides. - blink::WebView* webview = render_view_->webview(); - if (content_initiated && webview && webview->MainFrame() && - webview->MainFrame()->IsWebLocalFrame() && - webview->MainFrame()->ToWebLocalFrame()->GetDocumentLoader()) { - DocumentState* old_document_state = DocumentState::FromDocumentLoader( - webview->MainFrame()->ToWebLocalFrame()->GetDocumentLoader()); - if (old_document_state) { - InternalDocumentStateData* internal_data = - InternalDocumentStateData::FromDocumentState(document_state); - InternalDocumentStateData* old_internal_data = - InternalDocumentStateData::FromDocumentState(old_document_state); - internal_data->set_is_overriding_user_agent( - old_internal_data->is_overriding_user_agent()); - } + // This is either a placeholder document loader or an initial empty + // document. + document_loader->SetExtraData(BuildDocumentState()); } - // The rest of RenderView assumes that a WebDocumentLoader will always have a - // non-null NavigationState. - UpdateNavigationState(document_state, false /* was_within_same_document */, - content_initiated); - - NavigationStateImpl* navigation_state = static_cast<NavigationStateImpl*>( - document_state->navigation_state()); - - // Set the navigation start time in blink. - document_loader->SetNavigationStartTime( - navigation_state->common_params().navigation_start); + // 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 an actual navigation took place, inform the document loader of what - // happened in the browser. - if (!navigation_state->request_params() - .navigation_timing.fetch_start.is_null()) { - // Set timing of several events that happened during navigation. - // They will be used in blink for the Navigation Timing API. - base::TimeTicks redirect_start = - navigation_state->request_params().navigation_timing.redirect_start; - base::TimeTicks redirect_end = - navigation_state->request_params().navigation_timing.redirect_end; - base::TimeTicks fetch_start = - navigation_state->request_params().navigation_timing.fetch_start; + if (!has_pending_params) + return; - document_loader->UpdateNavigation( - redirect_start, redirect_end, fetch_start, - !navigation_state->request_params().redirects.empty()); - } + 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 (navigation_state->common_params().source_location.has_value()) { + if (pending_navigation_params->common_params.source_location.has_value()) { blink::WebSourceLocation source_location; - source_location.url = WebString::FromLatin1( - navigation_state->common_params().source_location->url); - source_location.line_number = - navigation_state->common_params().source_location->line_number; + source_location.url = + WebString::FromLatin1(common_params.source_location->url); + source_location.line_number = common_params.source_location->line_number; source_location.column_number = - navigation_state->common_params().source_location->column_number; + common_params.source_location->column_number; document_loader->SetSourceLocation(source_location); } - if (navigation_state->request_params().was_activated) + if (request_params.was_activated) document_loader->SetUserActivated(); - - // Create the serviceworker's per-document network observing object if it - // does not exist (When navigation happens within a page, the provider already - // exists). - if (document_loader->GetServiceWorkerNetworkProvider()) - return; - - scoped_refptr<network::SharedURLLoaderFactory> fallback_factory = - network::SharedURLLoaderFactory::Create( - GetLoaderFactoryBundle()->CloneWithoutDefaultFactory()); - document_loader->SetServiceWorkerNetworkProvider( - ServiceWorkerNetworkProvider::CreateForNavigation( - routing_id_, navigation_state->request_params(), frame_, - content_initiated, std::move(controller_service_worker_info_), - std::move(fallback_factory))); } void RenderFrameImpl::DidStartProvisionalLoad( @@ -3945,19 +4134,11 @@ void RenderFrameImpl::DidStartProvisionalLoad( std::vector<GURL> redirect_chain; GetRedirectChain(document_loader, &redirect_chain); - if (ConsumeGestureOnNavigation()) - WebUserGestureIndicator::ConsumeUserGesture(frame_); - Send(new FrameHostMsg_DidStartProvisionalLoad( routing_id_, document_loader->GetRequest().Url(), redirect_chain, navigation_start)); } -void RenderFrameImpl::DidReceiveServerRedirectForProvisionalLoad() { - // TODO(creis): Determine if this can be removed or if we need to clear any - // local state here to fix https://crbug.com/671276. -} - void RenderFrameImpl::DidFailProvisionalLoad( const WebURLError& error, blink::WebHistoryCommitType commit_type) { @@ -4052,8 +4233,8 @@ void RenderFrameImpl::DidCommitProvisionalLoad( // URL. // Note that this is only done for the main frame since the metrics for all // frames are keyed to the main frame's URL. - if (GetRenderWidget()->compositor()) - GetRenderWidget()->compositor()->SetURLForUkm(GetLoadingUrl()); + if (GetRenderWidget()->layer_tree_view()) + GetRenderWidget()->layer_tree_view()->SetURLForUkm(GetLoadingUrl()); } service_manager::mojom::InterfaceProviderRequest @@ -4103,6 +4284,7 @@ void RenderFrameImpl::DidCommitProvisionalLoad( if (media_permission_dispatcher_) media_permission_dispatcher_->OnNavigation(); + navigation_state->RunCommitNavigationCallback(blink::mojom::CommitResult::Ok); DidCommitNavigationInternal(item, commit_type, false /* was_within_same_document */, std::move(remote_interface_provider_request)); @@ -4276,9 +4458,10 @@ void RenderFrameImpl::RunScriptsAtDocumentReady(bool document_is_empty) { int http_status_code = internal_data->http_status_code(); 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()); LoadNavigationErrorPageForHttpStatusError( frame_->GetDocumentLoader()->GetRequest(), frame_->GetDocument().Url(), - http_status_code, true, nullptr); + http_status_code, true, nullptr, std::move(document_state)); } // Do not use |this| or |frame_| here without checking |weak_self|. } @@ -4290,18 +4473,7 @@ void RenderFrameImpl::RunScriptsAtDocumentIdle() { void RenderFrameImpl::DidHandleOnloadEvents() { if (!frame_->Parent()) { - FrameMsg_UILoadMetricsReportType::Value report_type = - static_cast<FrameMsg_UILoadMetricsReportType::Value>( - frame_->GetDocumentLoader() - ->GetRequest() - .InputPerfMetricReportPolicy()); - base::TimeTicks ui_timestamp = - base::TimeTicks() + - base::TimeDelta::FromSecondsD( - frame_->GetDocumentLoader()->GetRequest().UiStartTime()); - - Send(new FrameHostMsg_DocumentOnLoadCompleted( - routing_id_, report_type, ui_timestamp)); + Send(new FrameHostMsg_DocumentOnLoadCompleted(routing_id_)); } } @@ -4346,10 +4518,6 @@ void RenderFrameImpl::DidFinishLoad() { return; RecordSuffixedRendererMemoryMetrics(memory_metrics, ".MainFrameDidFinishLoad"); - if (!IsControlledByServiceWorker()) - return; - RecordSuffixedRendererMemoryMetrics( - memory_metrics, ".ServiceWorkerControlledMainFrameDidFinishLoad"); } void RenderFrameImpl::DidFinishSameDocumentNavigation( @@ -4361,8 +4529,21 @@ void RenderFrameImpl::DidFinishSameDocumentNavigation( routing_id_); DocumentState* document_state = DocumentState::FromDocumentLoader(frame_->GetDocumentLoader()); - UpdateNavigationState(document_state, true /* was_within_same_document */, - content_initiated); + + // If this was a browser-initiated navigation, then there could be pending + // navigation params, so use them. Otherwise, just reset the document state + // here, since if pending navigation params exist they are for some other + // navigation <https://crbug.com/597239>. + if (!pending_navigation_params_ || content_initiated) { + document_state->set_navigation_state( + NavigationStateImpl::CreateContentInitiated()); + } else { + DCHECK( + !pending_navigation_params_->common_params.navigation_start.is_null()); + document_state->set_navigation_state(CreateNavigationStateFromPending()); + pending_navigation_params_.reset(); + } + static_cast<NavigationStateImpl*>(document_state->navigation_state()) ->set_was_within_same_document(true); @@ -4424,7 +4605,8 @@ base::UnguessableToken RenderFrameImpl::GetDevToolsFrameToken() { void RenderFrameImpl::AbortClientNavigation() { browser_side_navigation_pending_ = false; - Send(new FrameHostMsg_AbortNavigation(routing_id_)); + if (!IsPerNavigationMojoInterfaceEnabled()) + Send(new FrameHostMsg_AbortNavigation(routing_id_)); } void RenderFrameImpl::DidChangeSelection(bool is_empty_selection) { @@ -4605,6 +4787,7 @@ void RenderFrameImpl::WillSendRequest(blink::WebURLRequest& request) { transition_type | ui::PAGE_TRANSITION_CLIENT_REDIRECT); } + ApplyFilePathAlias(&request); GURL new_url; bool attach_same_site_cookies = false; base::Optional<url::Origin> initiator_origin = @@ -4788,6 +4971,33 @@ void RenderFrameImpl::DidLoadResourceFromMemoryCache( response.MimeType().Utf8(), WebURLRequestToResourceType(request))); } +void RenderFrameImpl::DidStartResponse( + int request_id, + const network::ResourceResponseHead& response_head, + content::ResourceType resource_type) { + for (auto& observer : observers_) + observer.DidStartResponse(request_id, response_head, resource_type); +} + +void RenderFrameImpl::DidCompleteResponse( + int request_id, + const network::URLLoaderCompletionStatus& status) { + for (auto& observer : observers_) + observer.DidCompleteResponse(request_id, status); +} + +void RenderFrameImpl::DidCancelResponse(int request_id) { + for (auto& observer : observers_) + observer.DidCancelResponse(request_id); +} + +void RenderFrameImpl::DidReceiveTransferSizeUpdate(int resource_id, + int received_data_length) { + for (auto& observer : observers_) { + observer.DidReceiveTransferSizeUpdate(resource_id, received_data_length); + } +} + void RenderFrameImpl::DidDisplayInsecureContent() { Send(new FrameHostMsg_DidDisplayInsecureContent(routing_id_)); } @@ -4920,7 +5130,7 @@ bool RenderFrameImpl::ShouldTrackUseCounter(const blink::WebURL& url) { void RenderFrameImpl::DidCreateScriptContext(v8::Local<v8::Context> context, int world_id) { - if ((enabled_bindings_ & BINDINGS_POLICY_WEB_UI) && IsMainFrame() && + if ((enabled_bindings_ & BINDINGS_POLICY_MOJO_WEB_UI) && IsMainFrame() && world_id == ISOLATED_WORLD_ID_GLOBAL) { // We only allow these bindings to be installed when creating the main // world context of the main frame. @@ -4944,11 +5154,6 @@ void RenderFrameImpl::DidChangeScrollOffset() { observer.DidChangeScrollOffset(); } -void RenderFrameImpl::WillInsertBody() { - Send(new FrameHostMsg_WillInsertBody(routing_id_, - render_view_->GetRoutingID())); -} - void RenderFrameImpl::ReportFindInPageMatchCount(int request_id, int count, bool final_update) { @@ -5088,6 +5293,10 @@ void RenderFrameImpl::ExitFullscreen() { Send(new FrameHostMsg_ExitFullscreen(routing_id_)); } +void RenderFrameImpl::FullscreenStateChanged(bool is_fullscreen) { + GetFrameHost()->FullscreenStateChanged(is_fullscreen); +} + void RenderFrameImpl::SuddenTerminationDisablerChanged( bool present, blink::WebSuddenTerminationDisablerType disabler_type) { @@ -5334,15 +5543,6 @@ RenderFrameImpl::MakeDidCommitProvisionalLoadParams( params->history_list_was_cleared = navigation_state->request_params().should_clear_history_list; - - params->report_type = static_cast<FrameMsg_UILoadMetricsReportType::Value>( - frame_->GetDocumentLoader() - ->GetRequest() - .InputPerfMetricReportPolicy()); - params->ui_timestamp = - base::TimeTicks() + - base::TimeDelta::FromSecondsD( - frame_->GetDocumentLoader()->GetRequest().UiStartTime()); } else { // Subframe navigation: the type depends on whether this navigation // generated a new session history entry. When they do generate a session @@ -5355,7 +5555,6 @@ RenderFrameImpl::MakeDidCommitProvisionalLoadParams( DCHECK(!navigation_state->request_params().should_clear_history_list); params->history_list_was_cleared = false; - params->report_type = FrameMsg_UILoadMetricsReportType::NO_REPORT; } // Standard URLs must match the reported origin, when it is not unique. @@ -5552,27 +5751,16 @@ void RenderFrameImpl::DidCommitNavigationInternal( } } -void RenderFrameImpl::PrepareFrameForCommit() { +void RenderFrameImpl::PrepareFrameForCommit( + const GURL& url, + const RequestNavigationParams& request_params) { browser_side_navigation_pending_ = false; browser_side_navigation_pending_url_ = GURL(); GetContentClient()->SetActiveURL( - pending_navigation_params_->common_params.url, - frame_->Top()->GetSecurityOrigin().ToString().Utf8()); - - RenderFrameImpl::PrepareRenderViewForNavigation( - pending_navigation_params_->common_params.url, - pending_navigation_params_->request_params); - - // Lower bound for browser initiated navigation start time. - base::TimeTicks renderer_navigation_start = base::TimeTicks::Now(); + url, frame_->Top()->GetSecurityOrigin().ToString().Utf8()); - // Sanitize navigation start and store in |pending_navigation_params_|. - // It will be picked up in UpdateNavigationState. - pending_navigation_params_->common_params.navigation_start = - SanitizeNavigationTiming( - pending_navigation_params_->common_params.navigation_start, - renderer_navigation_start); + RenderFrameImpl::PrepareRenderViewForNavigation(url, request_params); } blink::mojom::CommitResult RenderFrameImpl::PrepareForHistoryNavigationCommit( @@ -5595,9 +5783,7 @@ blink::mojom::CommitResult RenderFrameImpl::PrepareForHistoryNavigationCommit( // store the relevant frame's WebHistoryItem in the root of the // PageState. *item_for_history_navigation = entry->root(); - *load_type = request_params.is_history_navigation_in_new_child - ? blink::WebFrameLoadType::kInitialHistoryLoad - : blink::WebFrameLoadType::kBackForward; + *load_type = blink::WebFrameLoadType::kBackForward; // Keep track of which subframes the browser process has history items // for during a history navigation. @@ -5659,13 +5845,18 @@ bool RenderFrameImpl::SwapIn() { in_frame_tree_ = true; // If this is the main frame going from a remote frame to a local frame, - // it needs to set RenderViewImpl's pointer for the main frame to itself - // and ensure RenderWidget is no longer in swapped out mode. + // it needs to set RenderViewImpl's pointer for the main frame to itself, + // ensure RenderWidget is no longer in swapped out mode, and call + // AddRefProcess() to prevent the process from exiting. A matching + // ReleaseProcess() call will be made if the RenderWidget ever becomes + // swapped out again - see OnSwapOut(). if (is_main_frame_) { CHECK(!render_view_->main_render_frame_); render_view_->main_render_frame_ = this; - if (render_view_->is_swapped_out()) + if (render_view_->is_swapped_out()) { render_view_->SetSwappedOut(false); + RenderProcess::current()->AddRefProcess(); + } render_view_->UpdateWebViewWithDeviceScaleFactor(); } @@ -5753,6 +5944,13 @@ WebNavigationPolicy RenderFrameImpl::DecidePolicyForNavigation( ->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 is fine normally, except if we're showing UI from one security @@ -5898,11 +6096,10 @@ WebNavigationPolicy RenderFrameImpl::DecidePolicyForNavigation( bool is_initial_navigation = render_view_->history_list_length_ == 0; bool should_fork = HasWebUIScheme(url) || HasWebUIScheme(old_url) || - (cumulative_bindings & BINDINGS_POLICY_WEB_UI) || + (cumulative_bindings & kWebUIBindingsPolicyMask) || url.SchemeIs(kViewSourceScheme) || (frame_->IsViewSourceModeEnabled() && info.navigation_type != blink::kWebNavigationTypeReload); - if (!should_fork && url.SchemeIs(url::kFileScheme)) { // Fork non-file to file opens. Note that this may fork unnecessarily if // another tab (hosting a file or not) targeted this one before its @@ -5977,7 +6174,9 @@ WebNavigationPolicy RenderFrameImpl::DecidePolicyForNavigation( if (info.default_policy == blink::kWebNavigationPolicyDownload) { blink::mojom::BlobURLTokenPtrInfo blob_url_token = CloneBlobURLToken(info.blob_url_token.get()); - DownloadURL(info.url_request, blob_url_token.PassHandle()); + DownloadURL(info.url_request, + blink::WebLocalFrameClient::CrossOriginRedirects::kFollow, + blob_url_token.PassHandle()); } else { OpenURL(info, /*send_referrer=*/true, /*is_history_navigation_in_new_child=*/false); @@ -6249,6 +6448,15 @@ void RenderFrameImpl::OnNotifyUserActivation() { frame_->NotifyUserActivation(); } +void RenderFrameImpl::OnMediaPlayerActionAt( + const gfx::PointF& location, + const blink::WebMediaPlayerAction& action) { + blink::WebFloatRect viewport_position(location.x(), location.y(), 0, 0); + GetRenderWidget()->ConvertWindowToViewport(&viewport_position); + frame_->PerformMediaPlayerAction( + WebPoint(viewport_position.x, viewport_position.y), action); +} + #if BUILDFLAG(USE_EXTERNAL_POPUP_MENU) #if defined(OS_MACOSX) void RenderFrameImpl::OnSelectPopupMenuItem(int selected_index) { @@ -6311,8 +6519,7 @@ void RenderFrameImpl::OpenURL(const NavigationPolicyInfo& info, if (GetContentClient()->renderer()->AllowPopup()) params.user_gesture = true; - if (ConsumeGestureOnNavigation() || - policy == blink::kWebNavigationPolicyNewBackgroundTab || + if (is_main_frame_ || policy == blink::kWebNavigationPolicyNewBackgroundTab || policy == blink::kWebNavigationPolicyNewForegroundTab || policy == blink::kWebNavigationPolicyNewWindow || policy == blink::kWebNavigationPolicyNewPopup) { @@ -6343,7 +6550,7 @@ WebURLRequest RenderFrameImpl::CreateURLRequestForCommit( WebURLRequest request = CreateURLRequestForNavigation( common_params, request_params, std::move(response_override), - frame_->IsViewSourceModeEnabled(), false /* is_same_document */); + frame_->IsViewSourceModeEnabled()); request.SetFrameType(IsTopLevelNavigation(frame_) ? network::mojom::RequestContextFrameType::kTopLevel : network::mojom::RequestContextFrameType::kNested); @@ -6504,7 +6711,7 @@ void RenderFrameImpl::ScrollFocusedEditableElementIntoRect( rect_for_scrolled_focused_editable_node_ = rect; has_scrolled_focused_editable_node_into_rect_ = true; - if (!GetRenderWidget()->compositor()->HasPendingPageScaleAnimation() && + if (!GetRenderWidget()->layer_tree_view()->HasPendingPageScaleAnimation() && autofill_client) { autofill_client->DidCompleteFocusChangeInFrame(); } @@ -6655,9 +6862,21 @@ void RenderFrameImpl::BeginNavigation(const NavigationPolicyInfo& info) { initiator ? base::make_optional<base::Value>(std::move(*initiator)) : base::nullopt); + mojom::NavigationClientAssociatedPtrInfo navigation_client_info; + if (IsPerNavigationMojoInterfaceEnabled()) { + WebDocumentLoader* document_loader = frame_->GetProvisionalDocumentLoader(); + DocumentState* document_state = + DocumentState::FromDocumentLoader(document_loader); + NavigationStateImpl* navigation_state = + static_cast<NavigationStateImpl*>(document_state->navigation_state()); + + 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(blob_url_token), + std::move(navigation_client_info)); } void RenderFrameImpl::LoadDataURL( @@ -6666,8 +6885,8 @@ void RenderFrameImpl::LoadDataURL( WebLocalFrame* frame, blink::WebFrameLoadType load_type, blink::WebHistoryItem item_for_history_navigation, - blink::WebHistoryLoadType history_load_type, - bool is_client_redirect) { + 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; #if defined(OS_ANDROID) @@ -6692,12 +6911,15 @@ void RenderFrameImpl::LoadDataURL( bool replace = load_type == WebFrameLoadType::kReloadBypassingCache || load_type == WebFrameLoadType::kReload; - frame->LoadData( + frame->CommitDataNavigation( 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, - item_for_history_navigation, history_load_type, is_client_redirect); + item_for_history_navigation, is_client_redirect, + std::move(navigation_data), + BuildNavigationTimings(params.navigation_start, + request_params.navigation_timing)); } else { CHECK(false) << "Invalid URL passed: " << params.url.possibly_invalid_spec(); @@ -6763,81 +6985,18 @@ GURL RenderFrameImpl::GetLoadingUrl() const { return request.Url(); } -void RenderFrameImpl::PopulateDocumentStateFromPending( - DocumentState* document_state) { - InternalDocumentStateData* internal_data = - InternalDocumentStateData::FromDocumentState(document_state); - - if (!pending_navigation_params_->common_params.url.SchemeIs( - url::kJavaScriptScheme) && - pending_navigation_params_->common_params.navigation_type == - FrameMsg_Navigate_Type::RESTORE) { - // We're doing a load of a page that was restored from the last session. - // By default this prefers the cache over loading - // (LOAD_SKIP_CACHE_VALIDATION) which can result in stale data for pages - // that are set to expire. We explicitly override that by setting the - // policy here so that as necessary we load from the network. - // - // TODO(davidben): Remove this in favor of passing a cache policy to the - // loadHistoryItem call in OnNavigate. That requires not overloading - // UseProtocolCachePolicy to mean both "normal load" and "determine cache - // policy based on load type, etc". - internal_data->set_cache_policy_override( - blink::mojom::FetchCacheMode::kDefault); - } - - internal_data->set_is_overriding_user_agent( - pending_navigation_params_->request_params.is_overriding_user_agent); - internal_data->set_must_reset_scroll_and_scale_state( - pending_navigation_params_->common_params.navigation_type == - FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL); - document_state->set_can_load_local_resources( - pending_navigation_params_->request_params.can_load_local_resources); -} NavigationState* RenderFrameImpl::CreateNavigationStateFromPending() { if (IsBrowserInitiated(pending_navigation_params_.get())) { return NavigationStateImpl::CreateBrowserInitiated( pending_navigation_params_->common_params, pending_navigation_params_->request_params, - pending_navigation_params_->time_commit_requested); + pending_navigation_params_->time_commit_requested, + std::move(pending_navigation_params_->commit_callback_)); } return NavigationStateImpl::CreateContentInitiated(); } -void RenderFrameImpl::UpdateNavigationState(DocumentState* document_state, - bool was_within_same_document, - bool content_initiated) { - // If this was a browser-initiated navigation, then there could be pending - // navigation params, so use them. Otherwise, just reset the document state - // here, since if pending navigation params exist they are for some other - // navigation <https://crbug.com/597239>. - if (!pending_navigation_params_ || content_initiated) { - document_state->set_navigation_state( - NavigationStateImpl::CreateContentInitiated()); - return; - } - - DCHECK(!pending_navigation_params_->common_params.navigation_start.is_null()); - document_state->set_navigation_state(CreateNavigationStateFromPending()); - - // The |set_was_load_data_with_base_url_request| state should not change for - // same document navigation, so skip updating it from the same document - // navigation params in this case. - if (!was_within_same_document) { - const CommonNavigationParams& common_params = - pending_navigation_params_->common_params; - 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); - document_state->set_was_load_data_with_base_url_request(load_data); - if (load_data) - document_state->set_data_url(common_params.url); - } - - pending_navigation_params_.reset(); -} - media::MediaPermission* RenderFrameImpl::GetMediaPermission() { if (!media_permission_dispatcher_) { media_permission_dispatcher_.reset(new MediaPermissionDispatcher( @@ -6901,6 +7060,11 @@ void RenderFrameImpl::RegisterMojoInterfaces() { base::Bind(&RenderFrameImpl::BindFrameNavigationControl, weak_factory_.GetWeakPtr())); + if (IsPerNavigationMojoInterfaceEnabled()) { + GetAssociatedInterfaceRegistry()->AddInterface(base::BindRepeating( + &RenderFrameImpl::BindNavigationClient, weak_factory_.GetWeakPtr())); + } + GetAssociatedInterfaceRegistry()->AddInterface(base::BindRepeating( &RenderFrameImpl::BindFullscreen, weak_factory_.GetWeakPtr())); @@ -6956,12 +7120,6 @@ void RenderFrameImpl::CheckIfAudioSinkExistsAndIsAuthorized( .device_status()); } -blink::WebSpeechRecognizer* RenderFrameImpl::SpeechRecognizer() { - if (!speech_recognition_dispatcher_) - speech_recognition_dispatcher_ = new SpeechRecognitionDispatcher(this); - return speech_recognition_dispatcher_; -} - blink::mojom::PageVisibilityState RenderFrameImpl::VisibilityState() const { const RenderFrameImpl* local_root = GetLocalRoot(); blink::mojom::PageVisibilityState current_state = @@ -7164,16 +7322,12 @@ void RenderFrameImpl::RenderWidgetWillHandleMouseEvent() { #endif } -bool RenderFrameImpl::ConsumeGestureOnNavigation() const { - return is_main_frame_ && - base::FeatureList::IsEnabled(kConsumeGestureOnNavigation); -} - -bool RenderFrameImpl::IsControlledByServiceWorker() { +blink::mojom::ControllerServiceWorkerMode +RenderFrameImpl::IsControlledByServiceWorker() { blink::WebServiceWorkerNetworkProvider* web_provider = frame_->GetDocumentLoader()->GetServiceWorkerNetworkProvider(); if (!web_provider) - return false; + return blink::mojom::ControllerServiceWorkerMode::kNoController; ServiceWorkerNetworkProvider* provider = ServiceWorkerNetworkProvider::FromWebServiceWorkerNetworkProvider( web_provider); diff --git a/chromium/content/renderer/render_frame_impl.h b/chromium/content/renderer/render_frame_impl.h index d841189173c..cb5ffc56b00 100644 --- a/chromium/content/renderer/render_frame_impl.h +++ b/chromium/content/renderer/render_frame_impl.h @@ -47,6 +47,7 @@ #include "content/public/common/referrer.h" #include "content/public/common/renderer_preferences.h" #include "content/public/common/request_context_type.h" +#include "content/public/common/resource_type.h" #include "content/public/common/stop_find_action.h" #include "content/public/renderer/render_frame.h" #include "content/public/renderer/websocket_handshake_throttle_provider.h" @@ -73,6 +74,7 @@ #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" +#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h" #include "third_party/blink/public/platform/autoplay.mojom.h" #include "third_party/blink/public/platform/site_engagement.mojom.h" #include "third_party/blink/public/platform/web_effective_connection_type.h" @@ -82,11 +84,11 @@ #include "third_party/blink/public/web/commit_result.mojom.h" #include "third_party/blink/public/web/web_ax_object.h" #include "third_party/blink/public/web/web_document_loader.h" -#include "third_party/blink/public/web/web_frame_client.h" #include "third_party/blink/public/web/web_frame_load_type.h" #include "third_party/blink/public/web/web_frame_serializer_client.h" #include "third_party/blink/public/web/web_history_commit_type.h" #include "third_party/blink/public/web/web_icon_url.h" +#include "third_party/blink/public/web/web_local_frame_client.h" #include "third_party/blink/public/web/web_meaningful_layout.h" #include "third_party/blink/public/web/web_script_execution_callback.h" #include "third_party/blink/public/web/web_triggering_event_info.h" @@ -116,11 +118,11 @@ class WebLocalFrame; class WebPushClient; class WebRelatedAppsFetcher; class WebSecurityOrigin; -class WebSpeechRecognizer; struct FramePolicy; struct WebContextMenuData; struct WebCursorInfo; struct WebFindOptions; +struct WebMediaPlayerAction; struct WebImeTextSpan; struct WebScrollIntoViewParams; } // namespace blink @@ -151,13 +153,13 @@ namespace content { class AssociatedInterfaceProviderImpl; class BlinkInterfaceRegistryImpl; class CompositorDependencies; -class DocumentState; class ExternalPopupMenu; class HistoryEntry; class ManifestManager; class MediaPermissionDispatcher; class MediaStreamDeviceObserver; class NavigationState; +class NavigationClient; class PepperPluginInstanceImpl; class PushMessagingClient; class RelatedAppsFetcher; @@ -168,7 +170,6 @@ class RenderViewImpl; class RenderWidget; class RenderWidgetFullscreenPepper; class SharedWorkerRepository; -class SpeechRecognitionDispatcher; class UserMediaClientImpl; struct CSPViolationParams; struct CommonNavigationParams; @@ -190,7 +191,7 @@ class CONTENT_EXPORT RenderFrameImpl mojom::FullscreenVideoElementHandler, mojom::HostZoom, mojom::FrameBindingsControl, - public blink::WebFrameClient, + public blink::WebLocalFrameClient, public blink::WebFrameSerializerClient, service_manager::mojom::InterfaceProvider { public: @@ -283,7 +284,7 @@ class CONTENT_EXPORT RenderFrameImpl // See RenderFrameObserver::DidMeaningfulLayout declaration for details. void DidMeaningfulLayout(blink::WebMeaningfulLayout layout_type); - // Draw commands have been issued by RenderWidgetCompositor. + // Draw commands have been issued by blink::LayerTreeView. void DidCommitAndDrawCompositorFrame(); // Returns the unique name of the RenderFrame. @@ -314,7 +315,7 @@ class CONTENT_EXPORT RenderFrameImpl // Start/Stop loading notifications. // TODO(nasko): Those are page-level methods at this time and come from - // WebViewClient. We should move them to be WebFrameClient calls and put + // WebViewClient. We should move them to be WebLocalFrameClient calls and put // logic in the browser side to balance starts/stops. // |to_different_document| will be true unless the load is a fragment // navigation, or triggered by history.pushState/replaceState. @@ -480,6 +481,8 @@ class CONTENT_EXPORT RenderFrameImpl void SetSelectedText(const base::string16& selection_text, size_t offset, const gfx::Range& range) override; + void SetZoomLevel(double zoom_level) override; + double GetZoomLevel() const override; void AddMessageToConsole(ConsoleMessageLevel level, const std::string& message) override; void SetPreviewsState(PreviewsState previews_state) override; @@ -525,14 +528,17 @@ class CONTENT_EXPORT RenderFrameImpl base::Optional<std::vector<mojom::TransferrableURLLoaderPtr>> subresource_overrides, mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info, - const base::UnguessableToken& devtools_navigation_token) override; + network::mojom::URLLoaderFactoryPtr prefetch_loader_factory, + 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 CommitSameDocumentNavigation( const CommonNavigationParams& common_params, const RequestNavigationParams& request_params, @@ -547,7 +553,7 @@ class CONTENT_EXPORT RenderFrameImpl // mojom::HostZoom implementation: void SetHostZoomLevel(const GURL& url, double zoom_level) override; - // blink::WebFrameClient implementation: + // blink::WebLocalFrameClient implementation: blink::WebPlugin* CreatePlugin(const blink::WebPluginParams& params) override; blink::WebMediaPlayer* CreateMediaPlayer( const blink::WebMediaPlayerSource& source, @@ -607,7 +613,8 @@ class CONTENT_EXPORT RenderFrameImpl const blink::WebVector<blink::WebString>& newly_matching_selectors, const blink::WebVector<blink::WebString>& stopped_matching_selectors) override; - void SetHasReceivedUserGesture() override; + void UpdateUserActivationState( + blink::UserActivationUpdateType update_type) override; void SetHasReceivedUserGestureBeforeNavigation(bool value) override; void SetMouseCapture(bool capture) override; bool ShouldReportDetailedMessageForSource( @@ -617,6 +624,7 @@ class CONTENT_EXPORT RenderFrameImpl unsigned source_line, const blink::WebString& stack_trace) override; void DownloadURL(const blink::WebURLRequest& request, + CrossOriginRedirects cross_origin_redirect_behavior, mojo::ScopedMessagePipeHandle blob_url_token) override; void LoadErrorPage(int reason) override; blink::WebNavigationPolicy DecidePolicyForNavigation( @@ -627,7 +635,6 @@ class CONTENT_EXPORT RenderFrameImpl blink::WebDocumentLoader* document_loader) override; void DidStartProvisionalLoad(blink::WebDocumentLoader* document_loader, blink::WebURLRequest& request) override; - void DidReceiveServerRedirectForProvisionalLoad() override; void DidFailProvisionalLoad(const blink::WebURLError& error, blink::WebHistoryCommitType commit_type) override; void DidCommitProvisionalLoad( @@ -702,7 +709,6 @@ class CONTENT_EXPORT RenderFrameImpl void WillReleaseScriptContext(v8::Local<v8::Context> context, int world_id) override; void DidChangeScrollOffset() override; - void WillInsertBody() override; void ReportFindInPageMatchCount(int request_id, int count, bool final_update) override; @@ -732,6 +738,7 @@ class CONTENT_EXPORT RenderFrameImpl void DidChangeManifest() override; void EnterFullscreen(const blink::WebFullscreenOptions& options) override; void ExitFullscreen() override; + void FullscreenStateChanged(bool is_fullscreen) override; void SuddenTerminationDisablerChanged( bool present, blink::WebSuddenTerminationDisablerType disabler_type) override; @@ -743,7 +750,6 @@ class CONTENT_EXPORT RenderFrameImpl void CheckIfAudioSinkExistsAndIsAuthorized( const blink::WebString& sink_id, blink::WebSetSinkIdCallbacks* web_callbacks) override; - blink::WebSpeechRecognizer* SpeechRecognizer() override; blink::mojom::PageVisibilityState VisibilityState() const override; std::unique_ptr<blink::WebURLLoaderFactory> CreateURLLoaderFactory() override; void DraggableRegionsChanged() override; @@ -785,6 +791,8 @@ class CONTENT_EXPORT RenderFrameImpl mojom::FrameBindingsControlAssociatedRequest request); void BindFrameNavigationControl( mojom::FrameNavigationControlAssociatedRequest request); + // Only used when PerNavigationMojoInterface is enabled. + void BindNavigationClient(mojom::NavigationClientAssociatedRequest request); blink::mojom::ManifestManager& GetManifestManager(); @@ -871,6 +879,18 @@ class CONTENT_EXPORT RenderFrameImpl // frame. void FrameDidCallFocus(); + // Called when an ongoing renderer-initiated navigation was dropped by the + // browser. + void OnDroppedNavigation(); + + void DidStartResponse(int request_id, + const network::ResourceResponseHead& response_head, + content::ResourceType resource_type); + void DidCompleteResponse(int request_id, + const network::URLLoaderCompletionStatus& status); + void DidCancelResponse(int request_id); + void DidReceiveTransferSizeUpdate(int request_id, int received_data_length); + protected: explicit RenderFrameImpl(CreateParams params); @@ -982,7 +1002,6 @@ class CONTENT_EXPORT RenderFrameImpl const FrameReplicationState& replicated_frame_state); void OnDeleteFrame(); void OnStop(); - void OnDroppedNavigation(); void OnCollapse(bool collapse); void OnShowContextMenu(const gfx::Point& location); void OnContextMenuClosed(const CustomContextMenuContext& custom_context); @@ -1042,6 +1061,8 @@ class CONTENT_EXPORT RenderFrameImpl void OnMixedContentFound(const FrameMsg_MixedContentFound_Params& params); void OnSetOverlayRoutingToken(const base::UnguessableToken& token); void OnNotifyUserActivation(); + void OnMediaPlayerActionAt(const gfx::PointF&, + const blink::WebMediaPlayerAction&); #if BUILDFLAG(USE_EXTERNAL_POPUP_MENU) #if defined(OS_MACOSX) @@ -1116,20 +1137,23 @@ class CONTENT_EXPORT RenderFrameImpl const blink::WebURLError& error, bool replace, HistoryEntry* entry, - const base::Optional<std::string>& error_page_content); + const base::Optional<std::string>& error_page_content, + std::unique_ptr<blink::WebDocumentLoader::ExtraData> navigation_data); void LoadNavigationErrorPageForHttpStatusError( const blink::WebURLRequest& failed_request, const GURL& unreachable_url, int http_status, bool replace, - HistoryEntry* entry); + HistoryEntry* entry, + 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); + const blink::WebHistoryItem& history_item, + std::unique_ptr<blink::WebDocumentLoader::ExtraData> navigation_data); void HandleJavascriptExecutionResult(const base::string16& javascript, int id, @@ -1150,13 +1174,14 @@ class CONTENT_EXPORT RenderFrameImpl void BeginNavigation(const NavigationPolicyInfo& info); // Loads a data url. - void LoadDataURL(const CommonNavigationParams& params, - const RequestNavigationParams& request_params, - blink::WebLocalFrame* frame, - blink::WebFrameLoadType load_type, - blink::WebHistoryItem item_for_history_navigation, - blink::WebHistoryLoadType history_load_type, - bool is_client_redirect); + void LoadDataURL( + const CommonNavigationParams& params, + const RequestNavigationParams& request_params, + blink::WebLocalFrame* frame, + blink::WebFrameLoadType load_type, + blink::WebHistoryItem item_for_history_navigation, + bool is_client_redirect, + std::unique_ptr<blink::WebDocumentLoader::ExtraData> navigation_data); // Sends a proper FrameHostMsg_DidFailProvisionalLoadWithError_Params IPC for // the failed request |request|. @@ -1170,20 +1195,10 @@ class CONTENT_EXPORT RenderFrameImpl // Returns the URL being loaded by the |frame_|'s request. GURL GetLoadingUrl() const; - // If we initiated a navigation, this function will populate |document_state| - // with the navigation information saved in OnNavigate(). - void PopulateDocumentStateFromPending(DocumentState* document_state); - // Returns a new NavigationState populated with the navigation information // saved in OnNavigate(). NavigationState* CreateNavigationStateFromPending(); - // Sets the NavigationState on the DocumentState based on - // the value of |pending_navigation_params_|. - void UpdateNavigationState(DocumentState* document_state, - bool was_within_same_document, - bool content_initiated); - #if BUILDFLAG(ENABLE_PLUGINS) void HandlePepperImeCommit(const base::string16& text); #endif // ENABLE_PLUGINS @@ -1232,11 +1247,8 @@ class CONTENT_EXPORT RenderFrameImpl void ShowDeferredContextMenu(const ContextMenuParams& params); - // Whether or not a navigation in this frame consumes user gestures. - bool ConsumeGestureOnNavigation() const; - - // Whether or not the frame is controlled by a service worker. - bool IsControlledByServiceWorker(); + // Whether the frame is controlled by a service worker. + blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker(); // Build DidCommitProvisionalLoad_Params based on the frame internal state. std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> @@ -1277,7 +1289,8 @@ class CONTENT_EXPORT RenderFrameImpl CreateWebSocketHandshakeThrottle() override; // Updates the state of this frame when asked to commit a navigation. - void PrepareFrameForCommit(); + void PrepareFrameForCommit(const GURL& url, + const RequestNavigationParams& request_params); // Updates the state when asked to commit a history navigation. Sets // |item_for_history_navigation| and |load_type| to the appropriate values for @@ -1471,11 +1484,6 @@ class CONTENT_EXPORT RenderFrameImpl // process. std::unique_ptr<ManifestManager> manifest_manager_; - // The speech recognition dispatcher attached to this frame, lazily - // initialized. It is an observer of this frame, owning itself and managing - // its own lifetime. - SpeechRecognitionDispatcher* speech_recognition_dispatcher_ = nullptr; - // The current accessibility mode. ui::AXMode accessibility_mode_; @@ -1554,6 +1562,9 @@ class CONTENT_EXPORT RenderFrameImpl mojo::AssociatedBinding<mojom::FullscreenVideoElementHandler> fullscreen_binding_; + // Only used when PerNavigationMojoInterface is enabled. + std::unique_ptr<NavigationClient> navigation_client_impl_; + // Indicates whether |didAccessInitialDocument| was called. bool has_accessed_initial_document_; @@ -1612,6 +1623,10 @@ class CONTENT_EXPORT RenderFrameImpl // 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_; + // URLLoaderFactory instances used for subresource loading. // Depending on how the frame was created, |loader_factories_| could be: // * |HostChildURLLoaderFactoryBundle| for standalone frames, or diff --git a/chromium/content/renderer/render_frame_impl_browsertest.cc b/chromium/content/renderer/render_frame_impl_browsertest.cc index a04c30ff0d6..884e79b63e8 100644 --- a/chromium/content/renderer/render_frame_impl_browsertest.cc +++ b/chromium/content/renderer/render_frame_impl_browsertest.cc @@ -19,6 +19,7 @@ #include "content/common/frame_owner_properties.h" #include "content/common/renderer.mojom.h" #include "content/common/view_messages.h" +#include "content/public/common/content_switches.h" #include "content/public/common/previews_state.h" #include "content/public/renderer/content_renderer_client.h" #include "content/public/renderer/document_state.h" @@ -210,7 +211,7 @@ TEST_F(RenderFrameImplTest, FrameResize) { TEST_F(RenderFrameImplTest, FrameWasShown) { RenderFrameTestObserver observer(frame()); - ViewMsg_WasShown was_shown_message(0, true, ui::LatencyInfo()); + ViewMsg_WasShown was_shown_message(0, true, base::TimeTicks()); frame_widget()->OnMessageReceived(was_shown_message); EXPECT_FALSE(frame_widget()->is_hidden()); @@ -240,7 +241,7 @@ TEST_F(RenderFrameImplTest, LocalChildFrameWasShown) { RenderFrameTestObserver observer(grandchild); - ViewMsg_WasShown was_shown_message(0, true, ui::LatencyInfo()); + ViewMsg_WasShown was_shown_message(0, true, base::TimeTicks()); frame_widget()->OnMessageReceived(was_shown_message); EXPECT_FALSE(frame_widget()->is_hidden()); @@ -253,7 +254,7 @@ TEST_F(RenderFrameImplTest, FrameWasShownAfterWidgetClose) { ViewMsg_Close close_message(0); frame_widget()->OnMessageReceived(close_message); - ViewMsg_WasShown was_shown_message(0, true, ui::LatencyInfo()); + ViewMsg_WasShown was_shown_message(0, true, base::TimeTicks()); // Test passes if this does not crash. static_cast<RenderViewImpl*>(view_)->OnMessageReceived(was_shown_message); } @@ -428,7 +429,9 @@ TEST_F(RenderFrameImplTest, DownloadUrlLimit) { blink::WebSecurityOrigin::Create(GURL("http://test"))); for (int i = 0; i < 10; ++i) { - frame()->DownloadURL(request, mojo::ScopedMessagePipeHandle()); + frame()->DownloadURL( + request, blink::WebLocalFrameClient::CrossOriginRedirects::kNavigate, + mojo::ScopedMessagePipeHandle()); base::RunLoop().RunUntilIdle(); const IPC::Message* msg2 = render_thread_->sink().GetFirstMessageMatching( FrameHostMsg_DownloadUrl::ID); @@ -437,7 +440,9 @@ TEST_F(RenderFrameImplTest, DownloadUrlLimit) { render_thread_->sink().ClearMessages(); } - frame()->DownloadURL(request, mojo::ScopedMessagePipeHandle()); + frame()->DownloadURL( + request, blink::WebLocalFrameClient::CrossOriginRedirects::kNavigate, + mojo::ScopedMessagePipeHandle()); base::RunLoop().RunUntilIdle(); const IPC::Message* msg3 = render_thread_->sink().GetFirstMessageMatching( FrameHostMsg_DownloadUrl::ID); @@ -650,6 +655,29 @@ TEST_F(RenderFrameImplTest, AutoplayFlags_WrongOrigin) { AutoplayFlagsForFrame(GetMainRenderFrame())); } +TEST_F(RenderFrameImplTest, FileUrlPathAlias) { + const struct { + const char* original; + const char* transformed; + } kTestCases[] = { + {"file:///alias", "file:///replacement"}, + {"file:///alias/path/to/file", "file:///replacement/path/to/file"}, + {"file://alias/path/to/file", "file://alias/path/to/file"}, + {"file:///notalias/path/to/file", "file:///notalias/path/to/file"}, + {"file:///root/alias/path/to/file", "file:///root/alias/path/to/file"}, + {"file:///", "file:///"}, + }; + base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( + switches::kFileUrlPathAlias, "/alias=/replacement"); + + for (const auto& test_case : kTestCases) { + WebURLRequest request; + request.SetURL(GURL(test_case.original)); + GetMainRenderFrame()->WillSendRequest(request); + EXPECT_EQ(test_case.transformed, request.Url().GetString().Utf8()); + } +} + // RenderFrameRemoteInterfacesTest ------------------------------------ namespace { diff --git a/chromium/content/renderer/render_frame_metadata_observer_impl.cc b/chromium/content/renderer/render_frame_metadata_observer_impl.cc index 5b5c8b82ae8..c8de63db72b 100644 --- a/chromium/content/renderer/render_frame_metadata_observer_impl.cc +++ b/chromium/content/renderer/render_frame_metadata_observer_impl.cc @@ -4,10 +4,19 @@ #include "content/renderer/render_frame_metadata_observer_impl.h" -#include "cc/trees/frame_token_allocator.h" +#include <cmath> + +#include "build/build_config.h" +#include "components/viz/common/quads/compositor_frame_metadata.h" namespace content { +namespace { +#if defined(OS_ANDROID) +constexpr float kEdgeThreshold = 10.0f; +#endif +} + RenderFrameMetadataObserverImpl::RenderFrameMetadataObserverImpl( mojom::RenderFrameMetadataObserverRequest request, mojom::RenderFrameMetadataObserverClientPtrInfo client_info) @@ -17,38 +26,40 @@ RenderFrameMetadataObserverImpl::RenderFrameMetadataObserverImpl( RenderFrameMetadataObserverImpl::~RenderFrameMetadataObserverImpl() {} -void RenderFrameMetadataObserverImpl::BindToCurrentThread( - cc::FrameTokenAllocator* frame_token_allocator) { +void RenderFrameMetadataObserverImpl::BindToCurrentThread() { DCHECK(request_.is_pending()); - frame_token_allocator_ = frame_token_allocator; render_frame_metadata_observer_binding_.Bind(std::move(request_)); render_frame_metadata_observer_client_.Bind(std::move(client_info_)); } void RenderFrameMetadataObserverImpl::OnRenderFrameSubmission( - cc::RenderFrameMetadata metadata) { + const cc::RenderFrameMetadata& render_frame_metadata, + viz::CompositorFrameMetadata* compositor_frame_metadata) { // By default only report metadata changes for fields which have a low // frequency of change. However if there are changes in high frequency // fields these can be reported while testing is enabled. bool send_metadata = false; + bool needs_activation_notification = true; if (render_frame_metadata_observer_client_) { if (report_all_frame_submissions_for_testing_enabled_) { - last_frame_token_ = frame_token_allocator_->GetOrAllocateFrameToken(); + last_frame_token_ = compositor_frame_metadata->frame_token; + compositor_frame_metadata->send_frame_token_to_embedder = true; render_frame_metadata_observer_client_->OnFrameSubmissionForTesting( last_frame_token_); send_metadata = !last_render_frame_metadata_ || - *last_render_frame_metadata_ != metadata; + *last_render_frame_metadata_ != render_frame_metadata; } else { send_metadata = !last_render_frame_metadata_ || - cc::RenderFrameMetadata::HasAlwaysUpdateMetadataChanged( - *last_render_frame_metadata_, metadata); + ShouldSendRenderFrameMetadata( + *last_render_frame_metadata_, render_frame_metadata, + &needs_activation_notification); } } // Allways cache the full metadata, so that it can correctly be sent upon // ReportAllFrameSubmissionsForTesting. This must only be done after we've // compared the two for changes. - last_render_frame_metadata_ = metadata; + last_render_frame_metadata_ = render_frame_metadata; // If the metadata is different, updates all the observers; or the metadata is // generated for first time and same as the default value, update the default @@ -57,18 +68,26 @@ void RenderFrameMetadataObserverImpl::OnRenderFrameSubmission( // Sending |root_scroll_offset| outside of tests would leave the browser // process with out of date information. It is an optional parameter // which we clear here. + auto metadata_copy = render_frame_metadata; +#if !defined(OS_ANDROID) if (!report_all_frame_submissions_for_testing_enabled_) - metadata.root_scroll_offset = base::nullopt; + metadata_copy.root_scroll_offset = base::nullopt; +#endif - last_frame_token_ = frame_token_allocator_->GetOrAllocateFrameToken(); + last_frame_token_ = compositor_frame_metadata->frame_token; + compositor_frame_metadata->send_frame_token_to_embedder = + needs_activation_notification; render_frame_metadata_observer_client_->OnRenderFrameMetadataChanged( - last_frame_token_, metadata); + needs_activation_notification ? last_frame_token_ : 0u, metadata_copy); } // Always cache the initial frame token, so that if a test connects later on // it can be notified of the initial state. - if (!last_frame_token_) - last_frame_token_ = frame_token_allocator_->GetOrAllocateFrameToken(); + if (!last_frame_token_) { + last_frame_token_ = compositor_frame_metadata->frame_token; + compositor_frame_metadata->send_frame_token_to_embedder = + needs_activation_notification; + } } void RenderFrameMetadataObserverImpl::ReportAllFrameSubmissionsForTesting( @@ -85,4 +104,72 @@ void RenderFrameMetadataObserverImpl::ReportAllFrameSubmissionsForTesting( last_frame_token_, *last_render_frame_metadata_); } +// static +bool RenderFrameMetadataObserverImpl::ShouldSendRenderFrameMetadata( + const cc::RenderFrameMetadata& rfm1, + const cc::RenderFrameMetadata& rfm2, + bool* needs_activation_notification) { + if (rfm1.root_background_color != rfm2.root_background_color || + rfm1.is_scroll_offset_at_top != rfm2.is_scroll_offset_at_top || + rfm1.selection != rfm2.selection || + rfm1.page_scale_factor != rfm2.page_scale_factor || + rfm1.is_mobile_optimized != rfm2.is_mobile_optimized || + rfm1.device_scale_factor != rfm2.device_scale_factor || + rfm1.viewport_size_in_pixels != rfm2.viewport_size_in_pixels || + rfm1.local_surface_id != rfm2.local_surface_id) { + *needs_activation_notification = true; + return true; + } + +#if defined(OS_ANDROID) + if (rfm1.top_controls_height != rfm2.top_controls_height || + rfm1.top_controls_shown_ratio != rfm2.top_controls_shown_ratio || + rfm1.bottom_controls_height != rfm2.bottom_controls_height || + rfm1.bottom_controls_shown_ratio != rfm2.bottom_controls_shown_ratio || + rfm1.min_page_scale_factor != rfm2.min_page_scale_factor || + rfm1.max_page_scale_factor != rfm2.max_page_scale_factor || + rfm1.root_overflow_y_hidden != rfm2.root_overflow_y_hidden || + rfm1.scrollable_viewport_size != rfm2.scrollable_viewport_size || + rfm1.root_layer_size != rfm2.root_layer_size || + rfm1.has_transparent_background != rfm2.has_transparent_background) { + *needs_activation_notification = true; + return true; + } + + gfx::Vector2dF old_root_scroll_offset = + rfm1.root_scroll_offset.value_or(gfx::Vector2dF()); + gfx::Vector2dF new_root_scroll_offset = + rfm2.root_scroll_offset.value_or(gfx::Vector2dF()); + gfx::RectF old_viewport_rect( + gfx::PointF(old_root_scroll_offset.x(), old_root_scroll_offset.y()), + rfm1.scrollable_viewport_size); + gfx::RectF new_viewport_rect( + gfx::PointF(new_root_scroll_offset.x(), new_root_scroll_offset.y()), + rfm2.scrollable_viewport_size); + gfx::RectF new_root_layer_rect(rfm2.root_layer_size); + bool at_left_or_right_edge = + rfm2.root_layer_size.width() > rfm2.scrollable_viewport_size.width() && + (std::abs(new_viewport_rect.right() - new_root_layer_rect.right()) < + kEdgeThreshold || + std::abs(new_viewport_rect.x() - new_root_layer_rect.x()) < + kEdgeThreshold); + + bool at_top_or_bottom_edge = + rfm2.root_layer_size.height() > rfm2.scrollable_viewport_size.height() && + (std::abs(new_viewport_rect.y() - new_root_layer_rect.y()) < + kEdgeThreshold || + std::abs(new_viewport_rect.bottom() - new_root_layer_rect.bottom()) < + kEdgeThreshold); + + if (old_viewport_rect != new_viewport_rect && + (at_left_or_right_edge || at_top_or_bottom_edge)) { + *needs_activation_notification = false; + return true; + } +#endif + + *needs_activation_notification = false; + return false; +} + } // namespace content diff --git a/chromium/content/renderer/render_frame_metadata_observer_impl.h b/chromium/content/renderer/render_frame_metadata_observer_impl.h index d7b159165da..ffa830f9b11 100644 --- a/chromium/content/renderer/render_frame_metadata_observer_impl.h +++ b/chromium/content/renderer/render_frame_metadata_observer_impl.h @@ -7,13 +7,10 @@ #include "cc/trees/render_frame_metadata.h" #include "cc/trees/render_frame_metadata_observer.h" +#include "content/common/content_export.h" #include "content/common/render_frame_metadata.mojom.h" #include "mojo/public/cpp/bindings/binding.h" -namespace cc { -class FrameTokenAllocator; -} // namespace cc - namespace content { // Implementation of cc::RenderFrameMetadataObserver which exists in the @@ -25,7 +22,7 @@ namespace content { // Mojo pipe is properly bound. // // Subsequent usage should only be from the Compositor thread. -class RenderFrameMetadataObserverImpl +class CONTENT_EXPORT RenderFrameMetadataObserverImpl : public cc::RenderFrameMetadataObserver, public mojom::RenderFrameMetadataObserver { public: @@ -35,14 +32,28 @@ class RenderFrameMetadataObserverImpl ~RenderFrameMetadataObserverImpl() override; // cc::RenderFrameMetadataObserver: - void BindToCurrentThread( - cc::FrameTokenAllocator* frame_token_allocator) override; - void OnRenderFrameSubmission(cc::RenderFrameMetadata metadata) override; + void BindToCurrentThread() override; + void OnRenderFrameSubmission( + const cc::RenderFrameMetadata& render_frame_metadata, + viz::CompositorFrameMetadata* compositor_frame_metadata) override; // mojom::RenderFrameMetadataObserver: void ReportAllFrameSubmissionsForTesting(bool enabled) override; private: + friend class RenderFrameMetadataObserverImplTest; + + // Certain fields should always have their changes reported. This will return + // true when there is a difference between |rfm1| and |rfm2| for those fields. + // These fields have a low frequency rate of change. + // |needs_activation_notification| indicates whether the browser process + // expects notification of activation of the assoicated CompositorFrame from + // Viz. + static bool ShouldSendRenderFrameMetadata( + const cc::RenderFrameMetadata& rfm1, + const cc::RenderFrameMetadata& rfm2, + bool* needs_activation_notification); + // When true this will notifiy |render_frame_metadata_observer_client_| of all // frame submissions. bool report_all_frame_submissions_for_testing_enabled_ = false; @@ -50,9 +61,6 @@ class RenderFrameMetadataObserverImpl uint32_t last_frame_token_ = 0; base::Optional<cc::RenderFrameMetadata> last_render_frame_metadata_; - // Not owned. - cc::FrameTokenAllocator* frame_token_allocator_ = nullptr; - // These are destroyed when BindToCurrentThread() is called. mojom::RenderFrameMetadataObserverRequest request_; mojom::RenderFrameMetadataObserverClientPtrInfo client_info_; diff --git a/chromium/content/renderer/render_frame_metadata_observer_impl_unittest.cc b/chromium/content/renderer/render_frame_metadata_observer_impl_unittest.cc new file mode 100644 index 00000000000..462e6392120 --- /dev/null +++ b/chromium/content/renderer/render_frame_metadata_observer_impl_unittest.cc @@ -0,0 +1,158 @@ +// 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/render_frame_metadata_observer_impl.h" + +#include "base/run_loop.h" +#include "base/test/scoped_task_environment.h" +#include "build/build_config.h" +#include "cc/trees/render_frame_metadata.h" +#include "components/viz/common/quads/compositor_frame_metadata.h" +#include "content/common/render_frame_metadata.mojom.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace content { +namespace { + +ACTION_P(InvokeClosure, closure) { + closure.Run(); +} + +} // namespace + +class MockRenderFrameMetadataObserverClient + : public mojom::RenderFrameMetadataObserverClient { + public: + MockRenderFrameMetadataObserverClient( + mojom::RenderFrameMetadataObserverClientRequest client_request, + mojom::RenderFrameMetadataObserverPtr observer) + : render_frame_metadata_observer_client_binding_( + this, + std::move(client_request)), + render_frame_metadata_observer_ptr_(std::move(observer)) {} + + MOCK_METHOD2(OnRenderFrameMetadataChanged, + void(uint32_t frame_token, + const cc::RenderFrameMetadata& metadata)); + MOCK_METHOD1(OnFrameSubmissionForTesting, void(uint32_t frame_token)); + + private: + mojo::Binding<mojom::RenderFrameMetadataObserverClient> + render_frame_metadata_observer_client_binding_; + mojom::RenderFrameMetadataObserverPtr render_frame_metadata_observer_ptr_; + + DISALLOW_COPY_AND_ASSIGN(MockRenderFrameMetadataObserverClient); +}; + +class RenderFrameMetadataObserverImplTest : public testing::Test { + public: + RenderFrameMetadataObserverImplTest() = default; + ~RenderFrameMetadataObserverImplTest() override = default; + + RenderFrameMetadataObserverImpl& observer_impl() { return *observer_impl_; } + + MockRenderFrameMetadataObserverClient& client() { return *client_; } + + // testing::Test: + void SetUp() override { + mojom::RenderFrameMetadataObserverPtr ptr; + mojom::RenderFrameMetadataObserverRequest request = mojo::MakeRequest(&ptr); + mojom::RenderFrameMetadataObserverClientPtrInfo client_info; + mojom::RenderFrameMetadataObserverClientRequest client_request = + mojo::MakeRequest(&client_info); + + client_ = std::make_unique< + testing::NiceMock<MockRenderFrameMetadataObserverClient>>( + std::move(client_request), std::move(ptr)); + observer_impl_ = std::make_unique<RenderFrameMetadataObserverImpl>( + std::move(request), std::move(client_info)); + observer_impl_->BindToCurrentThread(); + } + + void TearDown() override { + observer_impl_.reset(); + client_.reset(); + scoped_task_environment_.RunUntilIdle(); + } + + private: + base::test::ScopedTaskEnvironment scoped_task_environment_; + std::unique_ptr<testing::NiceMock<MockRenderFrameMetadataObserverClient>> + client_; + std::unique_ptr<RenderFrameMetadataObserverImpl> observer_impl_; + + DISALLOW_COPY_AND_ASSIGN(RenderFrameMetadataObserverImplTest); +}; + +// This test verifies that the RenderFrameMetadataObserverImpl picks up +// the frame token from CompositorFrameMetadata and passes it along to the +// client. This test also verifies that the RenderFrameMetadata object is +// passed along to the client. +TEST_F(RenderFrameMetadataObserverImplTest, ShouldSendFrameToken) { + viz::CompositorFrameMetadata compositor_frame_metadata; + compositor_frame_metadata.send_frame_token_to_embedder = false; + compositor_frame_metadata.frame_token = 1337; + cc::RenderFrameMetadata render_frame_metadata; + render_frame_metadata.is_mobile_optimized = true; + observer_impl().OnRenderFrameSubmission(render_frame_metadata, + &compositor_frame_metadata); + // |is_mobile_optimized| should be synchronized with frame activation so + // RenderFrameMetadataObserverImpl should ask for the frame token from + // Viz. + EXPECT_TRUE(compositor_frame_metadata.send_frame_token_to_embedder); + { + base::RunLoop run_loop; + EXPECT_CALL(client(), + OnRenderFrameMetadataChanged(1337, render_frame_metadata)) + .WillOnce(InvokeClosure(run_loop.QuitClosure())); + run_loop.Run(); + } +} + +// This test verifies that a frame token is not requested from viz when +// the root scroll offset changes on Android. +#if defined(OS_ANDROID) +TEST_F(RenderFrameMetadataObserverImplTest, ShouldSendFrameTokenOnAndroid) { + viz::CompositorFrameMetadata compositor_frame_metadata; + compositor_frame_metadata.send_frame_token_to_embedder = false; + compositor_frame_metadata.frame_token = 1337; + cc::RenderFrameMetadata render_frame_metadata; + render_frame_metadata.root_scroll_offset = gfx::Vector2dF(0.f, 1.f); + render_frame_metadata.root_layer_size = gfx::SizeF(100.f, 100.f); + render_frame_metadata.scrollable_viewport_size = gfx::SizeF(100.f, 50.f); + observer_impl().OnRenderFrameSubmission(render_frame_metadata, + &compositor_frame_metadata); + // The first RenderFrameMetadata will always get a corresponding frame token + // from Viz because this is the first frame. + EXPECT_TRUE(compositor_frame_metadata.send_frame_token_to_embedder); + { + base::RunLoop run_loop; + EXPECT_CALL(client(), + OnRenderFrameMetadataChanged(1337, render_frame_metadata)) + .WillOnce(InvokeClosure(run_loop.QuitClosure())); + run_loop.Run(); + } + + // Scroll back to the top. + render_frame_metadata.root_scroll_offset = gfx::Vector2dF(0.f, 0.f); + + observer_impl().OnRenderFrameSubmission(render_frame_metadata, + &compositor_frame_metadata); + // Android does not need a corresponding frame token. + EXPECT_FALSE(compositor_frame_metadata.send_frame_token_to_embedder); + { + base::RunLoop run_loop; + // The 0u frame token indicates that the client should not expect + // a corresponding frame token from Viz. + EXPECT_CALL(client(), + OnRenderFrameMetadataChanged(0u, render_frame_metadata)) + .WillOnce(InvokeClosure(run_loop.QuitClosure())); + run_loop.Run(); + } +} +#endif + +} // namespace content diff --git a/chromium/content/renderer/render_frame_proxy.cc b/chromium/content/renderer/render_frame_proxy.cc index 902038d46d7..8a50e185e1f 100644 --- a/chromium/content/renderer/render_frame_proxy.cc +++ b/chromium/content/renderer/render_frame_proxy.cc @@ -141,8 +141,8 @@ RenderFrameProxy* RenderFrameProxy::CreateFrameProxy( // be updated, as the OnSwapOut flow which normally does this won't happen // in that case. See https://crbug.com/653746 and // https://crbug.com/651980. - if (!render_view->is_swapped_out()) - render_view->SetSwappedOut(true); + if (!render_widget->is_swapped_out()) + render_widget->SetSwappedOut(true); } else { // Create a frame under an existing parent. The parent is always expected // to be a RenderFrameProxy, because navigations initiated by local frames @@ -243,7 +243,7 @@ void RenderFrameProxy::Init(blink::WebRemoteFrame* web_frame, render_widget_->GetOriginalScreenInfo(); #if defined(USE_AURA) - if (features::IsMashEnabled()) { + if (!features::IsAshInBrowserProcess()) { RendererWindowTreeClient* renderer_window_tree_client = RendererWindowTreeClient::Get(render_widget_->routing_id()); // It's possible a MusEmbeddedFrame has already been scheduled for creation @@ -256,7 +256,7 @@ void RenderFrameProxy::Init(blink::WebRemoteFrame* web_frame, #endif } -void RenderFrameProxy::ResendResizeParams() { +void RenderFrameProxy::ResendVisualProperties() { // Reset |sent_visual_properties_| in order to allocate a new // viz::LocalSurfaceId. sent_visual_properties_ = base::nullopt; @@ -285,6 +285,11 @@ void RenderFrameProxy::OnScreenInfoChanged(const ScreenInfo& screen_info) { SynchronizeVisualProperties(); } +void RenderFrameProxy::OnZoomLevelChanged(double zoom_level) { + pending_visual_properties_.zoom_level = zoom_level; + SynchronizeVisualProperties(); +} + void RenderFrameProxy::UpdateCaptureSequenceNumber( uint32_t capture_sequence_number) { pending_visual_properties_.capture_sequence_number = capture_sequence_number; @@ -322,8 +327,10 @@ void RenderFrameProxy::SetReplicatedState(const FrameReplicationState& state) { web_frame_->SetReplicatedInsecureNavigationsSet( state.insecure_navigations_set); web_frame_->SetReplicatedFeaturePolicyHeader(state.feature_policy_header); - if (state.has_received_user_gesture) - web_frame_->SetHasReceivedUserGesture(); + if (state.has_received_user_gesture) { + web_frame_->UpdateUserActivationState( + blink::UserActivationUpdateType::kNotifyActivation); + } web_frame_->SetHasReceivedUserGestureBeforeNavigation( state.has_received_user_gesture_before_nav); @@ -367,24 +374,6 @@ void RenderFrameProxy::OnDidSetFramePolicyHeaders( web_frame_->SetReplicatedFeaturePolicyHeader(feature_policy_header); } -void RenderFrameProxy::SetChildFrameSurface( - const viz::SurfaceInfo& surface_info) { - // If this WebFrame has already been detached, its parent will be null. This - // can happen when swapping a WebRemoteFrame with a WebLocalFrame, where this - // message may arrive after the frame was removed from the frame tree, but - // before the frame has been destroyed. http://crbug.com/446575. - if (!web_frame()->Parent()) - return; - - if (!enable_surface_synchronization_) { - compositing_helper_->SetPrimarySurfaceId( - surface_info.id(), local_frame_size(), - cc::DeadlinePolicy::UseDefaultDeadline()); - } - compositing_helper_->SetFallbackSurfaceId(surface_info.id(), - local_frame_size()); -} - bool RenderFrameProxy::OnMessageReceived(const IPC::Message& msg) { // Forward Page IPCs to the RenderView. if ((IPC_MESSAGE_CLASS(msg) == PageMsgStart)) { @@ -398,7 +387,8 @@ bool RenderFrameProxy::OnMessageReceived(const IPC::Message& msg) { IPC_BEGIN_MESSAGE_MAP(RenderFrameProxy, msg) IPC_MESSAGE_HANDLER(FrameMsg_DeleteProxy, OnDeleteProxy) IPC_MESSAGE_HANDLER(FrameMsg_ChildFrameProcessGone, OnChildFrameProcessGone) - IPC_MESSAGE_HANDLER(FrameMsg_SetChildFrameSurface, OnSetChildFrameSurface) + IPC_MESSAGE_HANDLER(FrameMsg_FirstSurfaceActivation, + OnFirstSurfaceActivation) IPC_MESSAGE_HANDLER(FrameMsg_IntrinsicSizingInfoOfChildChanged, OnIntrinsicSizingInfoOfChildChanged) IPC_MESSAGE_HANDLER(FrameMsg_UpdateOpener, OnUpdateOpener) @@ -431,8 +421,8 @@ bool RenderFrameProxy::OnMessageReceived(const IPC::Message& msg) { IPC_MESSAGE_HANDLER(FrameMsg_DisableAutoResize, OnDisableAutoResize) IPC_MESSAGE_HANDLER(FrameMsg_SetFocusedFrame, OnSetFocusedFrame) IPC_MESSAGE_HANDLER(FrameMsg_WillEnterFullscreen, OnWillEnterFullscreen) - IPC_MESSAGE_HANDLER(FrameMsg_SetHasReceivedUserGesture, - OnSetHasReceivedUserGesture) + IPC_MESSAGE_HANDLER(FrameMsg_UpdateUserActivationState, + OnUpdateUserActivationState) IPC_MESSAGE_HANDLER(FrameMsg_ScrollRectToVisible, OnScrollRectToVisible) IPC_MESSAGE_HANDLER(FrameMsg_BubbleLogicalScroll, OnBubbleLogicalScroll) IPC_MESSAGE_HANDLER(FrameMsg_SetHasReceivedUserGestureBeforeNavigation, @@ -459,9 +449,22 @@ void RenderFrameProxy::OnChildFrameProcessGone() { screen_info().device_scale_factor); } -void RenderFrameProxy::OnSetChildFrameSurface( +void RenderFrameProxy::OnFirstSurfaceActivation( const viz::SurfaceInfo& surface_info) { - SetChildFrameSurface(surface_info); + // If this WebFrame has already been detached, its parent will be null. This + // can happen when swapping a WebRemoteFrame with a WebLocalFrame, where this + // message may arrive after the frame was removed from the frame tree, but + // before the frame has been destroyed. http://crbug.com/446575. + if (!web_frame()->Parent()) + return; + + if (!enable_surface_synchronization_) { + compositing_helper_->SetPrimarySurfaceId( + surface_info.id(), local_frame_size(), + cc::DeadlinePolicy::UseDefaultDeadline()); + } + compositing_helper_->SetFallbackSurfaceId(surface_info.id(), + local_frame_size()); } void RenderFrameProxy::OnIntrinsicSizingInfoOfChildChanged( @@ -482,12 +485,12 @@ void RenderFrameProxy::OnViewChanged( const FrameMsg_ViewChanged_Params& params) { crashed_ = false; // In mash the FrameSinkId comes from RendererWindowTreeClient. - if (!base::FeatureList::IsEnabled(features::kMash)) + if (features::IsAshInBrowserProcess()) frame_sink_id_ = *params.frame_sink_id; // Resend the FrameRects and allocate a new viz::LocalSurfaceId when the view // changes. - ResendResizeParams(); + ResendVisualProperties(); } void RenderFrameProxy::OnDidStopLoading() { @@ -564,8 +567,9 @@ void RenderFrameProxy::OnWillEnterFullscreen() { web_frame_->WillEnterFullscreen(); } -void RenderFrameProxy::OnSetHasReceivedUserGesture() { - web_frame_->SetHasReceivedUserGesture(); +void RenderFrameProxy::OnUpdateUserActivationState( + blink::UserActivationUpdateType update_type) { + web_frame_->UpdateUserActivationState(update_type); } void RenderFrameProxy::OnScrollRectToVisible( @@ -639,6 +643,8 @@ void RenderFrameProxy::SynchronizeVisualProperties() { pending_visual_properties_.screen_space_rect.size() || sent_visual_properties_->screen_info != pending_visual_properties_.screen_info || + sent_visual_properties_->zoom_level != + pending_visual_properties_.zoom_level || capture_sequence_number_changed; if (synchronized_props_changed) @@ -860,17 +866,17 @@ base::UnguessableToken RenderFrameProxy::GetDevToolsFrameToken() { #if defined(USE_AURA) void RenderFrameProxy::OnMusEmbeddedFrameSurfaceChanged( const viz::SurfaceInfo& surface_info) { - SetChildFrameSurface(surface_info); + OnFirstSurfaceActivation(surface_info); } void RenderFrameProxy::OnMusEmbeddedFrameSinkIdAllocated( const viz::FrameSinkId& frame_sink_id) { // RendererWindowTreeClient should only call this when mus is hosting viz. - DCHECK(base::FeatureList::IsEnabled(features::kMash)); + DCHECK(!features::IsAshInBrowserProcess()); frame_sink_id_ = frame_sink_id; // Resend the FrameRects and allocate a new viz::LocalSurfaceId when the view // changes. - ResendResizeParams(); + ResendVisualProperties(); } #endif @@ -890,7 +896,7 @@ SkBitmap* RenderFrameProxy::GetSadPageBitmap() { } uint32_t RenderFrameProxy::Print(const blink::WebRect& rect, - blink::WebCanvas* canvas) { + cc::PaintCanvas* canvas) { #if BUILDFLAG(ENABLE_PRINTING) printing::PdfMetafileSkia* metafile = printing::MetafileSkiaWrapper::GetMetafileFromCanvas(canvas); diff --git a/chromium/content/renderer/render_frame_proxy.h b/chromium/content/renderer/render_frame_proxy.h index 06f4981a856..abe2aaa15ce 100644 --- a/chromium/content/renderer/render_frame_proxy.h +++ b/chromium/content/renderer/render_frame_proxy.h @@ -7,6 +7,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "cc/paint/paint_canvas.h" #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" #include "content/common/content_export.h" #include "content/common/frame_messages.h" @@ -16,7 +17,7 @@ #include "ipc/ipc_listener.h" #include "ipc/ipc_sender.h" #include "third_party/blink/public/common/feature_policy/feature_policy.h" -#include "third_party/blink/public/platform/web_canvas.h" +#include "third_party/blink/public/common/frame/user_activation_update_type.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/web/web_remote_frame.h" @@ -126,7 +127,7 @@ class CONTENT_EXPORT RenderFrameProxy : public IPC::Listener, // IPC::Listener bool OnMessageReceived(const IPC::Message& msg) override; - // Out-of-process child frames receive a signal from RenderWidgetCompositor + // Out-of-process child frames receive a signal from blink::LayerTreeView // when a compositor frame will begin. void WillBeginCompositorFrame(); @@ -134,6 +135,10 @@ class CONTENT_EXPORT RenderFrameProxy : public IPC::Listener, // ScreenInfo has changed. void OnScreenInfoChanged(const ScreenInfo& screen_info); + // Out-of-process child frames receive a signal from RenderWidget when the + // zoom level has changed. + void OnZoomLevelChanged(double zoom_level); + // Invoked by RenderWidget when a new capture sequence number was set, // indicating that surfaces should be synchronized. void UpdateCaptureSequenceNumber(uint32_t capture_sequence_number); @@ -202,7 +207,7 @@ class CONTENT_EXPORT RenderFrameProxy : public IPC::Listener, blink::WebLocalFrame* source) override; void FrameFocused() override; base::UnguessableToken GetDevToolsFrameToken() override; - uint32_t Print(const blink::WebRect& rect, blink::WebCanvas* canvas) override; + uint32_t Print(const blink::WebRect& rect, cc::PaintCanvas* canvas) override; // IPC handlers void OnDidStartLoading(); @@ -214,16 +219,13 @@ class CONTENT_EXPORT RenderFrameProxy : public IPC::Listener, RenderViewImpl* render_view, RenderWidget* render_widget); - void ResendResizeParams(); - - void SetChildFrameSurface(const viz::SurfaceInfo& surface_info); + void ResendVisualProperties(); // IPC handlers void OnDeleteProxy(); void OnChildFrameProcessGone(); void OnCompositorFrameSwapped(const IPC::Message& message); - // TODO(fsamuel): Rename OnFirstSurfaceActivation(). - void OnSetChildFrameSurface(const viz::SurfaceInfo& surface_info); + void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info); void OnIntrinsicSizingInfoOfChildChanged( blink::WebIntrinsicSizingInfo sizing_info); void OnUpdateOpener(int opener_routing_id); @@ -249,7 +251,7 @@ class CONTENT_EXPORT RenderFrameProxy : public IPC::Listener, void OnSetPageFocus(bool is_focused); void OnSetFocusedFrame(); void OnWillEnterFullscreen(); - void OnSetHasReceivedUserGesture(); + void OnUpdateUserActivationState(blink::UserActivationUpdateType update_type); void OnScrollRectToVisible(const gfx::Rect& rect_to_scroll, const blink::WebScrollIntoViewParams& params); void OnBubbleLogicalScroll(blink::WebScrollDirection direction, diff --git a/chromium/content/renderer/render_process_impl.cc b/chromium/content/renderer/render_process_impl.cc index f839d5610a1..80559a12e02 100644 --- a/chromium/content/renderer/render_process_impl.cc +++ b/chromium/content/renderer/render_process_impl.cc @@ -115,7 +115,6 @@ RenderProcessImpl::RenderProcessImpl( // closer to V8s normal performance and behavior. constexpr char kDisabledFlags[] = "--noturbo_verify " - "--noverify_csa " "--noturbo_verify_allocation " "--nodebug_code"; @@ -138,23 +137,37 @@ RenderProcessImpl::RenderProcessImpl( "--harmony-import-meta"); SetV8FlagIfFeature(features::kAsmJsToWebAssembly, "--validate-asm"); SetV8FlagIfNotFeature(features::kAsmJsToWebAssembly, "--no-validate-asm"); - SetV8FlagIfNotFeature(features::kWebAssembly, - "--wasm-disable-structured-cloning"); + + SetV8FlagIfFeature(features::kV8Orinoco, "--no-single-threaded-gc"); + SetV8FlagIfNotFeature(features::kV8Orinoco, "--single-threaded-gc"); SetV8FlagIfFeature(features::kV8VmFuture, "--future"); SetV8FlagIfNotFeature(features::kV8VmFuture, "--no-future"); - SetV8FlagIfFeature(features::kWebAssemblyBaseline, "--wasm-tier-up"); - SetV8FlagIfNotFeature(features::kWebAssemblyBaseline, "--no-wasm-tier-up"); - - SetV8FlagIfFeature(features::kSharedArrayBuffer, - "--harmony-sharedarraybuffer"); - SetV8FlagIfNotFeature(features::kSharedArrayBuffer, - "--no-harmony-sharedarraybuffer"); + SetV8FlagIfFeature(features::kWebAssemblyBaseline, + "--liftoff --wasm-tier-up"); + SetV8FlagIfNotFeature(features::kWebAssemblyBaseline, + "--no-liftoff --no-wasm-tier-up"); + + if (base::FeatureList::IsEnabled(features::kWebAssemblyThreads)) { + constexpr char kFlags[] = + "--harmony-sharedarraybuffer " + "--no-wasm-disable-structured-cloning " + "--experimental-wasm-threads"; + + v8::V8::SetFlagsFromString(kFlags, sizeof(kFlags)); + } else { + SetV8FlagIfNotFeature(features::kWebAssembly, + "--wasm-disable-structured-cloning"); + SetV8FlagIfFeature(features::kSharedArrayBuffer, + "--harmony-sharedarraybuffer"); + SetV8FlagIfNotFeature(features::kSharedArrayBuffer, + "--no-harmony-sharedarraybuffer"); + } SetV8FlagIfNotFeature(features::kWebAssemblyTrapHandler, "--no-wasm-trap-handler"); -#if defined(OS_LINUX) && defined(ARCH_CPU_X86_64) && !defined(OS_ANDROID) +#if defined(OS_LINUX) && defined(ARCH_CPU_X86_64) if (base::FeatureList::IsEnabled(features::kWebAssemblyTrapHandler)) { bool use_v8_signal_handler = false; base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); diff --git a/chromium/content/renderer/render_thread_impl.cc b/chromium/content/renderer/render_thread_impl.cc index 06f7d448799..ca6a21b0308 100644 --- a/chromium/content/renderer/render_thread_impl.cc +++ b/chromium/content/renderer/render_thread_impl.cc @@ -42,6 +42,7 @@ #include "build/build_config.h" #include "cc/base/histograms.h" #include "cc/base/switches.h" +#include "cc/mojo_embedder/async_layer_tree_frame_sink.h" #include "cc/raster/task_graph_runner.h" #include "cc/trees/layer_tree_frame_sink.h" #include "cc/trees/layer_tree_host_common.h" @@ -49,14 +50,12 @@ #include "components/discardable_memory/client/client_discardable_shared_memory_manager.h" #include "components/metrics/public/interfaces/single_sample_metrics.mojom.h" #include "components/metrics/single_sample_metrics.h" -#include "components/viz/client/client_layer_tree_frame_sink.h" #include "components/viz/client/hit_test_data_provider.h" #include "components/viz/client/hit_test_data_provider_draw_quad.h" #include "components/viz/client/local_surface_id_provider.h" #include "components/viz/common/features.h" #include "components/viz/common/frame_sinks/copy_output_request.h" #include "components/viz/common/switches.h" -#include "content/child/memory/child_memory_coordinator_impl.h" #include "content/child/runtime_features.h" #include "content/child/thread_safe_sender.h" #include "content/common/buildflags.h" @@ -77,6 +76,7 @@ #include "content/public/common/service_names.mojom.h" #include "content/public/common/simple_connection_filter.h" #include "content/public/common/url_constants.h" +#include "content/public/common/use_zoom_for_dsf_policy.h" #include "content/public/renderer/content_renderer_client.h" #include "content/public/renderer/render_thread_observer.h" #include "content/public/renderer/render_view_visitor.h" @@ -94,7 +94,8 @@ #include "content/renderer/indexed_db/indexed_db_dispatcher.h" #include "content/renderer/input/widget_input_handler_manager.h" #include "content/renderer/loader/resource_dispatcher.h" -#include "content/renderer/media/audio_renderer_mixer_manager.h" +#include "content/renderer/low_memory_mode_controller.h" +#include "content/renderer/media/audio/audio_renderer_mixer_manager.h" #include "content/renderer/media/gpu/gpu_video_accelerator_factories_impl.h" #include "content/renderer/media/midi/midi_message_filter.h" #include "content/renderer/media/render_media_client.h" @@ -114,7 +115,6 @@ #include "content/renderer/renderer_blink_platform_impl.h" #include "content/renderer/service_worker/embedded_worker_instance_client_impl.h" #include "content/renderer/service_worker/service_worker_context_client.h" -#include "content/renderer/service_worker/service_worker_message_filter.h" #include "content/renderer/shared_worker/embedded_shared_worker_stub.h" #include "content/renderer/shared_worker/shared_worker_factory_impl.h" #include "content/renderer/web_database_observer_impl.h" @@ -148,10 +148,9 @@ #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 "skia/ext/event_tracer_impl.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_main_thread_scheduler.h" +#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h" #include "third_party/blink/public/platform/web_cache.h" #include "third_party/blink/public/platform/web_image_generator.h" #include "third_party/blink/public/platform/web_memory_coordinator.h" @@ -172,7 +171,6 @@ #include "ui/base/ui_base_switches.h" #include "ui/display/display_switches.h" - #if defined(OS_ANDROID) #include <cpu-features.h> #include "content/renderer/android/synchronous_layer_tree_frame_sink.h" @@ -183,7 +181,6 @@ #if defined(OS_MACOSX) #include "base/mac/mac_util.h" #include "content/renderer/theme_helper_mac.h" -#include "content/renderer/webscrollbarbehavior_impl_mac.h" #endif #if defined(OS_WIN) @@ -197,6 +194,7 @@ #if defined(ENABLE_IPC_FUZZER) #include "content/common/external_ipc_dumper.h" +#include "mojo/public/cpp/bindings/message_dumper.h" #endif #if defined(OS_MACOSX) @@ -222,12 +220,6 @@ namespace { const int64_t kInitialIdleHandlerDelayMs = 1000; const int64_t kLongIdleHandlerDelayMs = 30 * 1000; -// Maximum allocation size allowed for image scaling filters that -// require pre-scaling. Skia will fallback to a filter that doesn't -// require pre-scaling if the default filter would require an -// allocation that exceeds this limit. -const size_t kImageCacheSingleAllocationByteLimit = 64 * 1024 * 1024; - #if defined(OS_ANDROID) // Unique identifier for each output surface created. uint32_t g_next_layer_tree_frame_sink_id = 1; @@ -650,9 +642,8 @@ RenderThreadImpl* RenderThreadImpl::Create( const InProcessChildThreadParams& params, base::MessageLoop* unowned_message_loop) { TRACE_EVENT0("startup", "RenderThreadImpl::Create"); - std::unique_ptr<blink::scheduler::WebMainThreadScheduler> - main_thread_scheduler = - blink::scheduler::WebMainThreadScheduler::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); @@ -661,7 +652,7 @@ RenderThreadImpl* RenderThreadImpl::Create( // static RenderThreadImpl* RenderThreadImpl::Create( std::unique_ptr<base::MessageLoop> main_message_loop, - std::unique_ptr<blink::scheduler::WebMainThreadScheduler> + std::unique_ptr<blink::scheduler::WebThreadScheduler> main_thread_scheduler) { TRACE_EVENT0("startup", "RenderThreadImpl::Create"); return new RenderThreadImpl(std::move(main_message_loop), @@ -712,7 +703,7 @@ RenderThreadImpl::DeprecatedGetMainTaskRunner() { // the browser RenderThreadImpl::RenderThreadImpl( const InProcessChildThreadParams& params, - std::unique_ptr<blink::scheduler::WebMainThreadScheduler> scheduler, + std::unique_ptr<blink::scheduler::WebThreadScheduler> scheduler, const scoped_refptr<base::SingleThreadTaskRunner>& resource_task_queue, base::MessageLoop* unowned_message_loop) : ChildThreadImpl( @@ -736,7 +727,7 @@ RenderThreadImpl::RenderThreadImpl( // which means that we need to make the render thread pump UI events. RenderThreadImpl::RenderThreadImpl( std::unique_ptr<base::MessageLoop> owned_message_loop, - std::unique_ptr<blink::scheduler::WebMainThreadScheduler> scheduler) + std::unique_ptr<blink::scheduler::WebThreadScheduler> scheduler) : ChildThreadImpl( Options::Builder() .AutoStartServiceManagerConnection(false) @@ -790,9 +781,9 @@ void RenderThreadImpl::Init( main_thread_runner(), GetConnector())); gpu_ = ui::Gpu::Create(GetConnector(), - base::FeatureList::IsEnabled(features::kMash) - ? ui::mojom::kServiceName - : mojom::kBrowserServiceName, + features::IsAshInBrowserProcess() + ? mojom::kBrowserServiceName + : ui::mojom::kServiceName, GetIOTaskRunner()); resource_dispatcher_.reset(new ResourceDispatcher()); @@ -802,7 +793,6 @@ void RenderThreadImpl::Init( auto registry = std::make_unique<service_manager::BinderRegistry>(); InitializeWebKit(resource_task_queue, registry.get()); - blink_initialized_time_ = base::TimeTicks::Now(); // In single process the single process is all there is. webkit_shared_timer_suspended_ = false; @@ -848,7 +838,7 @@ void RenderThreadImpl::Init( AddFilter(midi_message_filter_.get()); #if defined(USE_AURA) - if (features::IsMashEnabled()) + if (!features::IsAshInBrowserProcess()) CreateRenderWidgetWindowTreeClientFactory(GetServiceManagerConnection()); #endif @@ -880,10 +870,6 @@ void RenderThreadImpl::Init( base::Bind(&RenderThreadImpl::OnRendererInterfaceRequest, base::Unretained(this))); - InitSkiaEventTracer(); - base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( - skia::SkiaMemoryDumpProvider::GetInstance(), "Skia", nullptr); - const base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); @@ -894,6 +880,7 @@ void RenderThreadImpl::Init( IPC::ChannelProxy::OutgoingMessageFilter* filter = LoadExternalIPCDumper(dump_directory); GetChannel()->set_outgoing_message_filter(filter); + mojo::MessageDumper::SetMessageDumpDirectory(dump_directory); } #endif @@ -916,6 +903,8 @@ void RenderThreadImpl::Init( is_elastic_overscroll_enabled_ = false; #endif + is_zoom_for_dsf_enabled_ = content::IsUseZoomForDSFEnabled(); + if (command_line.HasSwitch(switches::kDisableLCDText)) { is_lcd_text_enabled_ = false; } else if (command_line.HasSwitch(switches::kEnableLCDText)) { @@ -980,20 +969,6 @@ void RenderThreadImpl::Init( base::Bind(&RenderThreadImpl::OnSyncMemoryPressure, base::Unretained(this)))); - if (base::FeatureList::IsEnabled(features::kMemoryCoordinator)) { - // Disable MemoryPressureListener when memory coordinator is enabled. - base::MemoryPressureListener::SetNotificationsSuppressed(true); - - // TODO(bashi): Revisit how to manage the lifetime of - // ChildMemoryCoordinatorImpl. - // https://codereview.chromium.org/2094583002/#msg52 - mojom::MemoryCoordinatorHandlePtr parent_coordinator; - GetConnector()->BindInterface(mojom::kBrowserServiceName, - mojo::MakeRequest(&parent_coordinator)); - memory_coordinator_ = CreateChildMemoryCoordinator( - std::move(parent_coordinator), this); - } - int num_raster_threads = 0; std::string string_value = command_line.GetSwitchValueASCII(switches::kNumRasterThreads); @@ -1018,7 +993,7 @@ void RenderThreadImpl::Init( categorized_worker_pool_->Start(num_raster_threads); discardable_memory::mojom::DiscardableSharedMemoryManagerPtr manager_ptr; - if (features::IsMashEnabled()) { + if (!features::IsAshInBrowserProcess()) { #if defined(USE_AURA) GetServiceManagerConnection()->GetConnector()->BindInterface( ui::mojom::kServiceName, &manager_ptr); @@ -1127,7 +1102,7 @@ bool RenderThreadImpl::Send(IPC::Message* msg) { } } - std::unique_ptr<blink::scheduler::WebMainThreadScheduler::RendererPauseHandle> + std::unique_ptr<blink::scheduler::WebThreadScheduler::RendererPauseHandle> renderer_paused_handle; if (pumping_events) { @@ -1192,7 +1167,8 @@ void RenderThreadImpl::RegisterPendingFrameCreate( CHECK(result.second) << "Inserting a duplicate item."; } -mojom::StoragePartitionService* RenderThreadImpl::GetStoragePartitionService() { +blink::mojom::StoragePartitionService* +RenderThreadImpl::GetStoragePartitionService() { return storage_partition_service_.get(); } @@ -1278,7 +1254,7 @@ void RenderThreadImpl::InitializeWebKit( v8::Isolate* isolate = blink::MainThreadIsolate(); isolate->SetCreateHistogramFunction(CreateHistogram); isolate->SetAddHistogramSampleFunction(AddHistogramSample); - main_thread_scheduler_->SetRAILModeObserver(this); + main_thread_scheduler_->AddRAILModeObserver(this); main_thread_compositor_task_runner_ = main_thread_scheduler_->CompositorTaskRunner(); @@ -1286,12 +1262,6 @@ void RenderThreadImpl::InitializeWebKit( if (!command_line.HasSwitch(switches::kDisableThreadedCompositing)) InitializeCompositorThread(); - scoped_refptr<base::SingleThreadTaskRunner> compositor_impl_side_task_runner; - if (compositor_task_runner_) - compositor_impl_side_task_runner = compositor_task_runner_; - else - compositor_impl_side_task_runner = base::ThreadTaskRunnerHandle::Get(); - RenderThreadImpl::RegisterSchemes(); RenderMediaClient::Initialize(); @@ -1306,17 +1276,9 @@ void RenderThreadImpl::InitializeWebKit( isolate->IsolateInBackgroundNotification(); } - service_worker_message_filter_ = new ServiceWorkerMessageFilter( - thread_safe_sender(), GetWebMainThreadScheduler()->IPCTaskRunner()); - AddFilter(service_worker_message_filter_->GetFilter()); - - main_thread_scheduler_->SetFreezingWhenBackgroundedEnabled( - GetContentClient()->renderer()->AllowFreezingWhenProcessBackgrounded()); - - SkGraphics::SetResourceCacheSingleAllocationByteLimit( - kImageCacheSingleAllocationByteLimit); - - // Hook up blink's codecs so skia can call them + // Hook up blink's codecs so skia can call them. Since only the renderer + // processes should be doing image decoding, this is not done in the common + // skia initialization code for the GPU. SkGraphics::SetImageGeneratorFromEncodedDataFactory( blink::WebImageGenerator::CreateAsSkImageGenerator); @@ -1475,7 +1437,7 @@ media::GpuVideoAcceleratorFactories* RenderThreadImpl::GetGpuFactories() { limits, support_locking, support_gles2_interface, support_raster_interface, support_oop_rasterization, support_grcontext, - ui::command_buffer_metrics::MEDIA_CONTEXT, + ui::command_buffer_metrics::ContextType::MEDIA, kGpuStreamIdMedia, kGpuStreamPriorityMedia); const bool enable_video_accelerator = @@ -1538,7 +1500,7 @@ RenderThreadImpl::SharedMainThreadContextProvider() { std::move(gpu_channel_host), GetGpuMemoryBufferManager(), gpu::SharedMemoryLimits(), support_locking, support_gles2_interface, support_raster_interface, support_oop_rasterization, support_grcontext, - ui::command_buffer_metrics::RENDERER_MAINTHREAD_CONTEXT, + ui::command_buffer_metrics::ContextType::RENDERER_MAIN_THREAD, kGpuStreamIdDefault, kGpuStreamPriorityDefault); auto result = shared_main_thread_contexts_->BindToCurrentThread(); if (result != gpu::ContextResult::kSuccess) @@ -1647,6 +1609,10 @@ bool RenderThreadImpl::IsElasticOverscrollEnabled() { return is_elastic_overscroll_enabled_; } +bool RenderThreadImpl::IsUseZoomForDSFEnabled() { + return is_zoom_for_dsf_enabled_; +} + scoped_refptr<base::SingleThreadTaskRunner> RenderThreadImpl::GetCompositorMainThreadTaskRunner() { return main_thread_compositor_task_runner_; @@ -1661,7 +1627,7 @@ gpu::GpuMemoryBufferManager* RenderThreadImpl::GetGpuMemoryBufferManager() { return gpu_->gpu_memory_buffer_manager(); } -blink::scheduler::WebMainThreadScheduler* +blink::scheduler::WebThreadScheduler* RenderThreadImpl::GetWebMainThreadScheduler() { return main_thread_scheduler_.get(); } @@ -1698,6 +1664,12 @@ RenderThreadImpl::CreateUkmRecorderFactory() { return std::make_unique<UkmRecorderFactoryImpl>(GetConnector()->Clone()); } +#ifdef OS_ANDROID +bool RenderThreadImpl::UsingSynchronousCompositing() { + return GetContentClient()->UsingSynchronousCompositing(); +} +#endif + void RenderThreadImpl::OnRAILModeChanged(v8::RAILMode rail_mode) { blink::MainThreadIsolate()->SetRAILMode(rail_mode); blink::SetRAILModeOnWorkerThreadIsolates(rail_mode); @@ -1815,6 +1787,16 @@ void RenderThreadImpl::ProcessPurgeAndSuspend() { base::TimeDelta::FromMinutes(90)); } +void RenderThreadImpl::SetIsLockedToSite() { + DCHECK(blink_platform_impl_); + blink_platform_impl_->SetIsLockedToSite(); +} + +void RenderThreadImpl::EnableV8LowMemoryMode() { + if (!low_memory_mode_controller_) + low_memory_mode_controller_.reset(new LowMemoryModeController()); +} + bool RenderThreadImpl::GetRendererMemoryMetrics( RendererMemoryMetrics* memory_metrics) const { DCHECK(memory_metrics); @@ -1980,7 +1962,7 @@ void RenderThreadImpl::RequestNewLayerTreeFrameSink( int routing_id, scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue, const GURL& url, - const LayerTreeFrameSinkCallback& callback, + LayerTreeFrameSinkCallback callback, mojom::RenderFrameMetadataObserverClientRequest render_frame_metadata_observer_client_request, mojom::RenderFrameMetadataObserverPtr render_frame_metadata_observer_ptr) { @@ -1993,7 +1975,7 @@ void RenderThreadImpl::RequestNewLayerTreeFrameSink( const base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); - viz::ClientLayerTreeFrameSink::InitParams params; + cc::mojo_embedder::AsyncLayerTreeFrameSink::InitParams params; params.compositor_task_runner = compositor_task_runner_; params.enable_surface_synchronization = features::IsSurfaceSynchronizationEnabled(); @@ -2017,22 +1999,22 @@ void RenderThreadImpl::RequestNewLayerTreeFrameSink( params.synthetic_begin_frame_source = CreateSyntheticBeginFrameSource(); #if defined(USE_AURA) - if (base::FeatureList::IsEnabled(features::kMash)) { + if (!features::IsAshInBrowserProcess()) { if (!RendererWindowTreeClient::Get(routing_id)) { - callback.Run(nullptr); + std::move(callback).Run(nullptr); return; } scoped_refptr<gpu::GpuChannelHost> channel = EstablishGpuChannelSync(); // If the channel could not be established correctly, then return null. This // would cause the compositor to wait and try again at a later time. if (!channel) { - callback.Run(nullptr); + std::move(callback).Run(nullptr); return; } RendererWindowTreeClient::Get(routing_id) ->RequestLayerTreeFrameSink( gpu_->CreateContextProvider(std::move(channel)), - GetGpuMemoryBufferManager(), callback); + GetGpuMemoryBufferManager(), std::move(callback)); frame_sink_provider_->RegisterRenderFrameMetadataObserver( routing_id, std::move(render_frame_metadata_observer_client_request), std::move(render_frame_metadata_observer_ptr)); @@ -2054,8 +2036,9 @@ void RenderThreadImpl::RequestNewLayerTreeFrameSink( frame_sink_provider_->RegisterRenderFrameMetadataObserver( routing_id, std::move(render_frame_metadata_observer_client_request), std::move(render_frame_metadata_observer_ptr)); - callback.Run(std::make_unique<viz::ClientLayerTreeFrameSink>( - nullptr, nullptr, ¶ms)); + std::move(callback).Run( + std::make_unique<cc::mojo_embedder::AsyncLayerTreeFrameSink>( + nullptr, nullptr, ¶ms)); return; } @@ -2064,7 +2047,7 @@ void RenderThreadImpl::RequestNewLayerTreeFrameSink( if (!gpu_channel_host) { // Wait and try again. We may hear that the compositing mode has switched // to software in the meantime. - callback.Run(nullptr); + std::move(callback).Run(nullptr); return; } @@ -2072,7 +2055,7 @@ void RenderThreadImpl::RequestNewLayerTreeFrameSink( SharedCompositorWorkerContextProvider(); if (!worker_context_provider) { // Cause the compositor to wait and try again. - callback.Run(nullptr); + std::move(callback).Run(nullptr); return; } @@ -2097,18 +2080,19 @@ void RenderThreadImpl::RequestNewLayerTreeFrameSink( constexpr bool automatic_flushes = false; constexpr bool support_locking = false; - constexpr bool support_grcontext = false; + constexpr bool support_grcontext = true; scoped_refptr<ui::ContextProviderCommandBuffer> context_provider( new ui::ContextProviderCommandBuffer( gpu_channel_host, GetGpuMemoryBufferManager(), kGpuStreamIdDefault, kGpuStreamPriorityDefault, gpu::kNullSurfaceHandle, url, automatic_flushes, support_locking, support_grcontext, limits, - attributes, ui::command_buffer_metrics::RENDER_COMPOSITOR_CONTEXT)); + attributes, + ui::command_buffer_metrics::ContextType::RENDER_COMPOSITOR)); if (layout_test_deps_) { if (!layout_test_deps_->UseDisplayCompositorPixelDump()) { - callback.Run(layout_test_deps_->CreateLayerTreeFrameSink( + std::move(callback).Run(layout_test_deps_->CreateLayerTreeFrameSink( routing_id, std::move(gpu_channel_host), std::move(context_provider), std::move(worker_context_provider), GetGpuMemoryBufferManager(), this)); @@ -2123,14 +2107,14 @@ void RenderThreadImpl::RequestNewLayerTreeFrameSink( #if defined(OS_ANDROID) if (GetContentClient()->UsingSynchronousCompositing()) { - RenderViewImpl* view = RenderViewImpl::FromRoutingID(routing_id); - if (view) { - callback.Run(std::make_unique<SynchronousLayerTreeFrameSink>( + RenderWidget* widget = RenderWidget::FromRoutingID(routing_id); + if (widget) { + std::move(callback).Run(std::make_unique<SynchronousLayerTreeFrameSink>( std::move(context_provider), std::move(worker_context_provider), compositor_task_runner_, GetGpuMemoryBufferManager(), sync_message_filter(), routing_id, g_next_layer_tree_frame_sink_id++, std::move(params.synthetic_begin_frame_source), - view->widget_input_handler_manager() + widget->widget_input_handler_manager() ->GetSynchronousCompositorRegistry(), std::move(frame_swap_message_queue))); return; @@ -2146,9 +2130,10 @@ void RenderThreadImpl::RequestNewLayerTreeFrameSink( routing_id, std::move(render_frame_metadata_observer_client_request), std::move(render_frame_metadata_observer_ptr)); params.gpu_memory_buffer_manager = GetGpuMemoryBufferManager(); - callback.Run(std::make_unique<viz::ClientLayerTreeFrameSink>( - std::move(context_provider), std::move(worker_context_provider), - ¶ms)); + std::move(callback).Run( + std::make_unique<cc::mojo_embedder::AsyncLayerTreeFrameSink>( + std::move(context_provider), std::move(worker_context_provider), + ¶ms)); } blink::AssociatedInterfaceRegistry* @@ -2166,12 +2151,10 @@ RenderThreadImpl::RequestCopyOfOutputForLayoutTest( } std::unique_ptr<blink::WebMediaStreamCenter> -RenderThreadImpl::CreateMediaStreamCenter( - blink::WebMediaStreamCenterClient* client) { +RenderThreadImpl::CreateMediaStreamCenter() { std::unique_ptr<blink::WebMediaStreamCenter> media_stream_center; if (!media_stream_center) { - media_stream_center = std::make_unique<MediaStreamCenter>( - client, GetPeerConnectionDependencyFactory()); + media_stream_center = std::make_unique<MediaStreamCenter>(); } return media_stream_center; } @@ -2241,8 +2224,8 @@ void RenderThreadImpl::CreateFrameProxy( void RenderThreadImpl::SetUpEmbeddedWorkerChannelForServiceWorker( mojom::EmbeddedWorkerInstanceClientRequest client_request) { - EmbeddedWorkerInstanceClientImpl::Create( - blink_initialized_time_, GetIOTaskRunner(), std::move(client_request)); + EmbeddedWorkerInstanceClientImpl::Create(GetIOTaskRunner(), + std::move(client_request)); } void RenderThreadImpl::OnNetworkConnectionChanged( @@ -2288,14 +2271,10 @@ void RenderThreadImpl::SetUserAgent(const std::string& user_agent) { void RenderThreadImpl::UpdateScrollbarTheme( mojom::UpdateScrollbarThemeParamsPtr params) { #if defined(OS_MACOSX) - static_cast<WebScrollbarBehaviorImpl*>( - blink_platform_impl_->ScrollbarBehavior()) - ->set_jump_on_track_click(params->jump_on_track_click); - blink::WebScrollbarTheme::UpdateScrollbarsWithNSDefaults( params->initial_button_delay, params->autoscroll_button_delay, params->preferred_scroller_style, params->redraw, - params->button_placement); + params->button_placement, params->jump_on_track_click); is_elastic_overscroll_enabled_ = params->scroll_view_rubber_banding; #else @@ -2317,13 +2296,7 @@ void RenderThreadImpl::OnSystemColorsChanged( void RenderThreadImpl::PurgePluginListCache(bool reload_pages) { #if BUILDFLAG(ENABLE_PLUGINS) - // The call below will cause a GetPlugins call with refresh=true, but at this - // point we already know that the browser has refreshed its list, so disable - // refresh temporarily to prevent each renderer process causing the list to be - // regenerated. - blink_platform_impl_->set_plugin_refresh_allowed(false); blink::ResetPluginCache(reload_pages); - blink_platform_impl_->set_plugin_refresh_allowed(true); for (auto& observer : observers_) observer.PluginListChanged(); @@ -2366,8 +2339,6 @@ void RenderThreadImpl::OnPurgeMemory() { OnTrimMemoryImmediately(); ReleaseFreeMemory(); - if (blink_platform_impl_) - blink::WebMemoryCoordinator::OnPurgeMemory(); } void RenderThreadImpl::RecordPurgeMemory(RendererMemoryMetrics before) { @@ -2417,17 +2388,21 @@ RenderThreadImpl::SharedCompositorWorkerContextProvider() { bool support_locking = true; bool support_oop_rasterization = - base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableOOPRasterization); + gpu_channel_host->gpu_feature_info() + .status_values[gpu::GPU_FEATURE_TYPE_OOP_RASTERIZATION] == + gpu::kGpuFeatureStatusEnabled; bool support_gles2_interface = !support_oop_rasterization; bool support_raster_interface = true; bool support_grcontext = !support_oop_rasterization; + auto shared_memory_limits = + support_oop_rasterization ? gpu::SharedMemoryLimits::ForOOPRasterContext() + : gpu::SharedMemoryLimits(); shared_worker_context_provider_ = CreateOffscreenContext( std::move(gpu_channel_host), GetGpuMemoryBufferManager(), - gpu::SharedMemoryLimits(), support_locking, support_gles2_interface, + shared_memory_limits, support_locking, support_gles2_interface, support_raster_interface, support_oop_rasterization, support_grcontext, - ui::command_buffer_metrics::RENDER_WORKER_CONTEXT, kGpuStreamIdWorker, - kGpuStreamPriorityWorker); + ui::command_buffer_metrics::ContextType::RENDER_WORKER, + kGpuStreamIdWorker, kGpuStreamPriorityWorker); auto result = shared_worker_context_provider_->BindToCurrentThread(); if (result != gpu::ContextResult::kSuccess) shared_worker_context_provider_ = nullptr; @@ -2500,7 +2475,7 @@ void RenderThreadImpl::ReleaseFreeMemory() { if (blink_platform_impl_) { // Purge Skia font cache, resource cache, and image filter. SkGraphics::PurgeAllCaches(); - blink::DecommitFreeableMemory(); + blink::WebMemoryCoordinator::OnPurgeMemory(); } } diff --git a/chromium/content/renderer/render_thread_impl.h b/chromium/content/renderer/render_thread_impl.h index 6ab16c9a4fa..78326bc4c21 100644 --- a/chromium/content/renderer/render_thread_impl.h +++ b/chromium/content/renderer/render_thread_impl.h @@ -40,13 +40,12 @@ #include "content/common/render_message_filter.mojom.h" #include "content/common/renderer.mojom.h" #include "content/common/renderer_host.mojom.h" -#include "content/common/storage_partition_service.mojom.h" #include "content/public/renderer/render_thread.h" #include "content/public/renderer/url_loader_throttle_provider.h" #include "content/renderer/gpu/compositor_dependencies.h" #include "content/renderer/layout_test_dependencies.h" -#include "content/renderer/media/audio_input_ipc_factory.h" -#include "content/renderer/media/audio_output_ipc_factory.h" +#include "content/renderer/media/audio/audio_input_ipc_factory.h" +#include "content/renderer/media/audio/audio_output_ipc_factory.h" #include "gpu/ipc/client/gpu_channel_host.h" #include "ipc/ipc_sync_channel.h" #include "media/media_buildflags.h" @@ -59,7 +58,8 @@ #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/platform/scheduler/web_main_thread_scheduler.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_connection_type.h" #include "third_party/blink/public/web/web_memory_statistics.h" #include "ui/gfx/native_widget_types.h" @@ -75,7 +75,6 @@ namespace scheduler { class WebThreadBase; } class WebMediaStreamCenter; -class WebMediaStreamCenterClient; } namespace base { @@ -137,6 +136,7 @@ class FileSystemDispatcher; class FrameSwapMessageQueue; class GpuVideoAcceleratorFactoriesImpl; class IndexedDBDispatcher; +class LowMemoryModeController; class MidiMessageFilter; class P2PSocketDispatcher; class PeerConnectionDependencyFactory; @@ -144,7 +144,6 @@ class PeerConnectionTracker; class RenderThreadObserver; class RendererBlinkPlatformImpl; class ResourceDispatcher; -class ServiceWorkerMessageFilter; class VideoCaptureImplManager; #if defined(OS_ANDROID) @@ -169,8 +168,7 @@ class StreamTextureFactory; class CONTENT_EXPORT RenderThreadImpl : public RenderThread, public ChildThreadImpl, - public blink::scheduler::WebMainThreadScheduler::RAILModeObserver, - public ChildMemoryCoordinatorDelegate, + public blink::scheduler::WebThreadScheduler::RAILModeObserver, public base::MemoryCoordinatorClient, public mojom::Renderer, public viz::mojom::CompositingModeWatcher, @@ -180,7 +178,7 @@ class CONTENT_EXPORT RenderThreadImpl base::MessageLoop* unowned_message_loop); static RenderThreadImpl* Create( std::unique_ptr<base::MessageLoop> main_message_loop, - std::unique_ptr<blink::scheduler::WebMainThreadScheduler> + std::unique_ptr<blink::scheduler::WebThreadScheduler> main_thread_scheduler); static RenderThreadImpl* current(); static mojom::RenderMessageFilter* current_render_message_filter(); @@ -250,18 +248,22 @@ class CONTENT_EXPORT RenderThreadImpl bool IsPartialRasterEnabled() override; bool IsGpuMemoryBufferCompositorResourcesEnabled() override; bool IsElasticOverscrollEnabled() override; + bool IsUseZoomForDSFEnabled() override; scoped_refptr<base::SingleThreadTaskRunner> GetCompositorMainThreadTaskRunner() override; scoped_refptr<base::SingleThreadTaskRunner> GetCompositorImplThreadTaskRunner() override; - blink::scheduler::WebMainThreadScheduler* GetWebMainThreadScheduler() - override; + blink::scheduler::WebThreadScheduler* GetWebMainThreadScheduler() override; cc::TaskGraphRunner* GetTaskGraphRunner() override; - bool IsThreadedAnimationEnabled() override; bool IsScrollAnimatorEnabled() override; std::unique_ptr<cc::UkmRecorderFactory> CreateUkmRecorderFactory() override; +#ifdef OS_ANDROID + bool UsingSynchronousCompositing() override; +#endif + + bool IsThreadedAnimationEnabled(); - // blink::scheduler::WebMainThreadScheduler::RAILModeObserver implementation. + // blink::scheduler::WebThreadScheduler::RAILModeObserver implementation. void OnRAILModeChanged(v8::RAILMode rail_mode) override; // viz::mojom::CompositingModeWatcher implementation. @@ -281,12 +283,12 @@ class CONTENT_EXPORT RenderThreadImpl gpu::GpuMemoryBufferManager* GetGpuMemoryBufferManager(); using LayerTreeFrameSinkCallback = - base::Callback<void(std::unique_ptr<cc::LayerTreeFrameSink>)>; + base::OnceCallback<void(std::unique_ptr<cc::LayerTreeFrameSink>)>; void RequestNewLayerTreeFrameSink( int routing_id, scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue, const GURL& url, - const LayerTreeFrameSinkCallback& callback, + LayerTreeFrameSinkCallback callback, mojom::RenderFrameMetadataObserverClientRequest render_frame_metadata_observer_client_request, mojom::RenderFrameMetadataObserverPtr render_frame_metadata_observer_ptr); @@ -305,6 +307,14 @@ class CONTENT_EXPORT RenderThreadImpl std::unique_ptr<LayoutTestDependencies> deps) { layout_test_deps_ = std::move(deps); } + // Returns whether we are running layout tests with display compositor for + // pixel dump enabled. It is meant to disable feature that require display + // compositor while it is not enabled by default. + // This should only be called if currently running in layout tests. + bool LayoutTestModeUsesDisplayCompositorPixelDump() const { + DCHECK(layout_test_deps_); + return layout_test_deps_->UseDisplayCompositorPixelDump(); + } discardable_memory::ClientDiscardableSharedMemoryManager* GetDiscardableSharedMemoryManagerForTest() { @@ -352,8 +362,7 @@ class CONTENT_EXPORT RenderThreadImpl // Creates the embedder implementation of WebMediaStreamCenter. // The resulting object is owned by WebKit and deleted by WebKit at tear-down. - std::unique_ptr<blink::WebMediaStreamCenter> CreateMediaStreamCenter( - blink::WebMediaStreamCenterClient* client); + std::unique_ptr<blink::WebMediaStreamCenter> CreateMediaStreamCenter(); BrowserPluginManager* browser_plugin_manager() const { return browser_plugin_manager_.get(); @@ -375,6 +384,10 @@ class CONTENT_EXPORT RenderThreadImpl return vc_manager_.get(); } + LowMemoryModeController* low_memory_mode_controller() const { + return low_memory_mode_controller_.get(); + } + mojom::RenderFrameMessageFilter* render_frame_message_filter(); mojom::RenderMessageFilter* render_message_filter(); @@ -486,7 +499,7 @@ class CONTENT_EXPORT RenderThreadImpl int routing_id, mojom::FrameRequest frame); - mojom::StoragePartitionService* GetStoragePartitionService(); + blink::mojom::StoragePartitionService* GetStoragePartitionService(); mojom::RendererHost* GetRendererHost(); // ChildMemoryCoordinatorDelegate implementation. @@ -512,12 +525,12 @@ class CONTENT_EXPORT RenderThreadImpl protected: RenderThreadImpl( const InProcessChildThreadParams& params, - std::unique_ptr<blink::scheduler::WebMainThreadScheduler> scheduler, + 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::WebMainThreadScheduler> scheduler); + std::unique_ptr<blink::scheduler::WebThreadScheduler> scheduler); private: void OnProcessFinalRelease() override; @@ -581,6 +594,8 @@ class CONTENT_EXPORT RenderThreadImpl void SetProcessBackgrounded(bool backgrounded) override; void SetSchedulerKeepActive(bool keep_active) override; void ProcessPurgeAndSuspend() override; + void SetIsLockedToSite() override; + void EnableV8LowMemoryMode() override; void OnMemoryPressure( base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level); @@ -612,8 +627,7 @@ class CONTENT_EXPORT RenderThreadImpl std::unique_ptr<AppCacheDispatcher> appcache_dispatcher_; std::unique_ptr<DomStorageDispatcher> dom_storage_dispatcher_; std::unique_ptr<IndexedDBDispatcher> main_thread_indexed_db_dispatcher_; - std::unique_ptr<blink::scheduler::WebMainThreadScheduler> - main_thread_scheduler_; + 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_; @@ -621,7 +635,6 @@ class CONTENT_EXPORT RenderThreadImpl // Used on the renderer and IPC threads. scoped_refptr<MidiMessageFilter> midi_message_filter_; - scoped_refptr<ServiceWorkerMessageFilter> service_worker_message_filter_; std::unique_ptr<BrowserPluginManager> browser_plugin_manager_; @@ -650,9 +663,6 @@ class CONTENT_EXPORT RenderThreadImpl // Used on the render thread. std::unique_ptr<VideoCaptureImplManager> vc_manager_; - // The time Blink was initialized. Used for UMA. - base::TimeTicks blink_initialized_time_; - // The count of RenderWidgets running through this thread. int widget_count_; @@ -724,7 +734,9 @@ class CONTENT_EXPORT RenderThreadImpl std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_; - std::unique_ptr<ChildMemoryCoordinatorImpl> memory_coordinator_; + // Created in response to EnableV8LowMemoryMode(), this manages V8's + // memory saving mode. + std::unique_ptr<LowMemoryModeController> low_memory_mode_controller_; std::unique_ptr<ui::Gpu> gpu_; @@ -739,6 +751,7 @@ class CONTENT_EXPORT RenderThreadImpl bool is_gpu_memory_buffer_compositor_resources_enabled_; bool is_partial_raster_enabled_; bool is_elastic_overscroll_enabled_; + bool is_zoom_for_dsf_enabled_; bool is_threaded_animation_enabled_; bool is_scroll_animator_enabled_; @@ -773,7 +786,7 @@ class CONTENT_EXPORT RenderThreadImpl std::map<int, scoped_refptr<PendingFrameCreate>>; PendingFrameCreateMap pending_frame_creates_; - mojom::StoragePartitionServicePtr storage_partition_service_; + blink::mojom::StoragePartitionServicePtr storage_partition_service_; mojom::RendererHostAssociatedPtr renderer_host_; AssociatedInterfaceRegistryImpl associated_interfaces_; diff --git a/chromium/content/renderer/render_thread_impl_browsertest.cc b/chromium/content/renderer/render_thread_impl_browsertest.cc index f5977ad2ea6..3e65072fe27 100644 --- a/chromium/content/renderer/render_thread_impl_browsertest.cc +++ b/chromium/content/renderer/render_thread_impl_browsertest.cc @@ -50,12 +50,12 @@ #include "gpu/ipc/host/gpu_switches.h" #include "ipc/ipc.mojom.h" #include "ipc/ipc_channel_mojo.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/outgoing_broker_client_invitation.h" -#include "mojo/edk/embedder/scoped_ipc_support.h" +#include "mojo/core/embedder/embedder.h" +#include "mojo/core/embedder/scoped_ipc_support.h" +#include "mojo/public/cpp/system/invitation.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" -#include "third_party/blink/public/platform/scheduler/web_main_thread_scheduler.h" +#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h" #include "ui/base/ui_base_switches.h" #include "ui/gfx/buffer_format_util.h" @@ -132,7 +132,7 @@ class RenderThreadImplForTest : public RenderThreadImpl { public: RenderThreadImplForTest( const InProcessChildThreadParams& params, - std::unique_ptr<blink::scheduler::WebMainThreadScheduler> scheduler, + std::unique_ptr<blink::scheduler::WebThreadScheduler> scheduler, scoped_refptr<base::SingleThreadTaskRunner>& test_task_counter, base::MessageLoop* unowned_message_loop) : RenderThreadImpl(params, @@ -209,10 +209,10 @@ class RenderThreadImplBrowserTest : public testing::Test { blink::scheduler::GetSingleThreadTaskRunnerForTesting(); InitializeMojo(); - mojo_ipc_support_.reset(new mojo::edk::ScopedIPCSupport( - io_task_runner, mojo::edk::ScopedIPCSupport::ShutdownPolicy::FAST)); + mojo_ipc_support_.reset(new mojo::core::ScopedIPCSupport( + io_task_runner, mojo::core::ScopedIPCSupport::ShutdownPolicy::FAST)); shell_context_.reset(new TestServiceManagerContext); - mojo::edk::OutgoingBrokerClientInvitation invitation; + mojo::OutgoingInvitation invitation; service_manager::Identity child_identity( mojom::kRendererServiceName, service_manager::mojom::kInheritUserID, "test"); @@ -248,9 +248,9 @@ class RenderThreadImplBrowserTest : public testing::Test { // in RenderThreadImpl::Init(). cmd->AppendSwitch(switches::kIgnoreGpuBlacklist); - std::unique_ptr<blink::scheduler::WebMainThreadScheduler> + std::unique_ptr<blink::scheduler::WebThreadScheduler> main_thread_scheduler = - blink::scheduler::WebMainThreadScheduler::Create(); + blink::scheduler::WebThreadScheduler::CreateMainThreadScheduler(); scoped_refptr<base::SingleThreadTaskRunner> test_task_counter( test_task_counter_.get()); @@ -293,7 +293,7 @@ class RenderThreadImplBrowserTest : public testing::Test { std::unique_ptr<TestServiceManagerContext> shell_context_; std::unique_ptr<ChildConnection> child_connection_; std::unique_ptr<IPC::ChannelProxy> channel_; - std::unique_ptr<mojo::edk::ScopedIPCSupport> mojo_ipc_support_; + std::unique_ptr<mojo::core::ScopedIPCSupport> mojo_ipc_support_; std::unique_ptr<MockRenderProcess> mock_process_; scoped_refptr<QuitOnTestMsgFilter> test_msg_filter_; diff --git a/chromium/content/renderer/render_view_browsertest.cc b/chromium/content/renderer/render_view_browsertest.cc index 79c8ff2cff0..caa6b4a4d37 100644 --- a/chromium/content/renderer/render_view_browsertest.cc +++ b/chromium/content/renderer/render_view_browsertest.cc @@ -29,6 +29,7 @@ #include "content/common/view_messages.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/native_web_keyboard_event.h" +#include "content/public/browser/web_ui_controller.h" #include "content/public/browser/web_ui_controller_factory.h" #include "content/public/common/bindings_policy.h" #include "content/public/common/browser_side_navigation_policy.h" @@ -45,7 +46,7 @@ #include "content/public/test/render_view_test.h" #include "content/public/test/test_utils.h" #include "content/renderer/accessibility/render_accessibility_impl.h" -#include "content/renderer/gpu/render_widget_compositor.h" +#include "content/renderer/gpu/layer_tree_view.h" #include "content/renderer/history_entry.h" #include "content/renderer/history_serialization.h" #include "content/renderer/loader/request_extra_data.h" @@ -56,6 +57,7 @@ #include "content/renderer/service_worker/service_worker_network_provider.h" #include "content/shell/browser/shell.h" #include "content/shell/browser/shell_browser_context.h" +#include "content/test/fake_compositor_dependencies.h" #include "content/test/mock_keyboard.h" #include "content/test/test_render_frame.h" #include "net/base/net_errors.h" @@ -63,7 +65,9 @@ #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/platform/modules/serviceworker/web_service_worker_network_provider.h" +#include "third_party/blink/public/common/origin_trials/origin_trial_policy.h" +#include "third_party/blink/public/common/origin_trials/trial_token_validator.h" +#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h" #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" #include "third_party/blink/public/platform/web_data.h" #include "third_party/blink/public/platform/web_http_body.h" @@ -78,6 +82,7 @@ #include "third_party/blink/public/web/web_history_item.h" #include "third_party/blink/public/web/web_input_method_controller.h" #include "third_party/blink/public/web/web_local_frame.h" +#include "third_party/blink/public/web/web_origin_trials.h" #include "third_party/blink/public/web/web_performance.h" #include "third_party/blink/public/web/web_script_source.h" #include "third_party/blink/public/web/web_settings.h" @@ -160,8 +165,9 @@ int ConvertMockKeyboardModifier(MockKeyboard::Modifiers modifiers) { class WebUITestWebUIControllerFactory : public WebUIControllerFactory { public: - WebUIController* CreateWebUIControllerForURL(WebUI* web_ui, - const GURL& url) const override { + std::unique_ptr<WebUIController> CreateWebUIControllerForURL( + WebUI* web_ui, + const GURL& url) const override { return nullptr; } WebUI::TypeID GetWebUIType(BrowserContext* browser_context, @@ -394,10 +400,9 @@ class RenderViewImplTest : public RenderViewTest { return view()->preferred_size_; } - void SetZoomLevel(double level) { - view()->OnSetZoomLevel( - PageMsg_SetZoomLevel_Command::USE_CURRENT_TEMPORARY_MODE, level); - } + void SetZoomLevel(double level) { view()->UpdateZoomLevel(level); } + + double GetZoomLevel() { return view()->page_zoom_level(); } int GetScrollbarWidth() { blink::WebView* webview = view()->webview(); @@ -437,8 +442,16 @@ class RenderViewImplBlinkSettingsTest : public RenderViewImplTest { void SetUp() override {} }; -class RenderViewImplScaleFactorTest : public RenderViewImplBlinkSettingsTest { +// This test class enables UseZoomForDSF based on the platform default value. +class RenderViewImplScaleFactorTest : public RenderViewImplTest { protected: + std::unique_ptr<CompositorDependencies> CreateCompositorDependencies() + override { + auto deps = std::make_unique<FakeCompositorDependencies>(); + deps->set_use_zoom_for_dsf_enabled(content::IsUseZoomForDSFEnabled()); + return deps; + } + void SetDeviceScaleFactor(float dsf) { VisualProperties visual_properties; visual_properties.screen_info.device_scale_factor = dsf; @@ -482,10 +495,32 @@ class RenderViewImplScaleFactorTest : public RenderViewImplBlinkSettingsTest { EXPECT_EQ(height, emulated_height); EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(get_dpr, &emulated_dpr)); EXPECT_EQ(static_cast<int>(dpr * 10), emulated_dpr); - EXPECT_EQ(compositor_dsf, view() - ->compositor() - ->layer_tree_host() - ->device_scale_factor()); + cc::LayerTreeHost* host = view()->layer_tree_view()->layer_tree_host(); + EXPECT_EQ(compositor_dsf, host->device_scale_factor()); + } +}; + +// This test class forces UseZoomForDSF to be on for all platforms. +class RenderViewImplEnableZoomForDSFTest + : public RenderViewImplScaleFactorTest { + protected: + std::unique_ptr<CompositorDependencies> CreateCompositorDependencies() + override { + auto deps = std::make_unique<FakeCompositorDependencies>(); + deps->set_use_zoom_for_dsf_enabled(true); + return deps; + } +}; + +// This test class forces UseZoomForDSF to be off for all platforms. +class RenderViewImplDisableZoomForDSFTest + : public RenderViewImplScaleFactorTest { + protected: + std::unique_ptr<CompositorDependencies> CreateCompositorDependencies() + override { + auto deps = std::make_unique<FakeCompositorDependencies>(); + deps->set_use_zoom_for_dsf_enabled(false); + return deps; } }; @@ -532,9 +567,8 @@ static blink::WebCoalescedInputEvent FatTap(int x, } TEST_F(RenderViewImplScaleFactorTest, TapDisambiguatorSize) { - DoSetUp(); - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kEnableUseZoomForDSF); + // 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()); @@ -689,7 +723,7 @@ TEST_F(RenderViewImplTest, DecideNavigationPolicy) { request.SetFetchRedirectMode(network::mojom::FetchRedirectMode::kManual); request.SetFrameType(network::mojom::RequestContextFrameType::kTopLevel); request.SetRequestContext(blink::WebURLRequest::kRequestContextInternal); - blink::WebFrameClient::NavigationPolicyInfo policy_info(request); + blink::WebLocalFrameClient::NavigationPolicyInfo policy_info(request); policy_info.navigation_type = blink::kWebNavigationTypeLinkClicked; policy_info.default_policy = blink::kWebNavigationPolicyCurrentTab; blink::WebNavigationPolicy policy = @@ -706,7 +740,8 @@ TEST_F(RenderViewImplTest, DecideNavigationPolicy) { // Verify that form posts to WebUI URLs will be sent to the browser process. blink::WebURLRequest form_request(GURL("chrome://foo")); - blink::WebFrameClient::NavigationPolicyInfo form_policy_info(form_request); + blink::WebLocalFrameClient::NavigationPolicyInfo form_policy_info( + form_request); form_policy_info.navigation_type = blink::kWebNavigationTypeFormSubmitted; form_policy_info.default_policy = blink::kWebNavigationPolicyCurrentTab; form_request.SetHTTPMethod("POST"); @@ -715,7 +750,8 @@ TEST_F(RenderViewImplTest, DecideNavigationPolicy) { // Verify that popup links to WebUI URLs also are sent to browser. blink::WebURLRequest popup_request(GURL("chrome://foo")); - blink::WebFrameClient::NavigationPolicyInfo popup_policy_info(popup_request); + blink::WebLocalFrameClient::NavigationPolicyInfo popup_policy_info( + popup_request); popup_policy_info.navigation_type = blink::kWebNavigationTypeLinkClicked; popup_policy_info.default_policy = blink::kWebNavigationPolicyNewForegroundTab; @@ -741,7 +777,7 @@ TEST_F(RenderViewImplTest, DecideNavigationPolicyHandlesAllTopLevel) { }; blink::WebURLRequest request(GURL("http://foo.com")); - blink::WebFrameClient::NavigationPolicyInfo policy_info(request); + blink::WebLocalFrameClient::NavigationPolicyInfo policy_info(request); policy_info.default_policy = blink::kWebNavigationPolicyCurrentTab; for (size_t i = 0; i < arraysize(kNavTypes); ++i) { @@ -762,7 +798,7 @@ TEST_F(RenderViewImplTest, DecideNavigationPolicyForWebUI) { // Navigations to normal HTTP URLs will be sent to browser process. blink::WebURLRequest request(GURL("http://foo.com")); - blink::WebFrameClient::NavigationPolicyInfo policy_info(request); + blink::WebLocalFrameClient::NavigationPolicyInfo policy_info(request); policy_info.navigation_type = blink::kWebNavigationTypeLinkClicked; policy_info.default_policy = blink::kWebNavigationPolicyCurrentTab; @@ -772,7 +808,8 @@ TEST_F(RenderViewImplTest, DecideNavigationPolicyForWebUI) { // Navigations to WebUI URLs will also be sent to browser process. blink::WebURLRequest webui_request(GURL("chrome://foo")); - blink::WebFrameClient::NavigationPolicyInfo webui_policy_info(webui_request); + blink::WebLocalFrameClient::NavigationPolicyInfo webui_policy_info( + webui_request); webui_policy_info.navigation_type = blink::kWebNavigationTypeLinkClicked; webui_policy_info.default_policy = blink::kWebNavigationPolicyCurrentTab; policy = frame()->DecidePolicyForNavigation(webui_policy_info); @@ -780,7 +817,8 @@ TEST_F(RenderViewImplTest, DecideNavigationPolicyForWebUI) { // Verify that form posts to data URLs will be sent to the browser process. blink::WebURLRequest data_request(GURL("data:text/html,foo")); - blink::WebFrameClient::NavigationPolicyInfo data_policy_info(data_request); + blink::WebLocalFrameClient::NavigationPolicyInfo data_policy_info( + data_request); data_policy_info.navigation_type = blink::kWebNavigationTypeFormSubmitted; data_policy_info.default_policy = blink::kWebNavigationPolicyCurrentTab; data_request.SetHTTPMethod("POST"); @@ -796,7 +834,8 @@ TEST_F(RenderViewImplTest, DecideNavigationPolicyForWebUI) { blink::kWebNavigationPolicyNewForegroundTab, false, blink::WebSandboxFlags::kNone); RenderViewImpl* new_view = RenderViewImpl::FromWebView(new_web_view); - blink::WebFrameClient::NavigationPolicyInfo popup_policy_info(popup_request); + blink::WebLocalFrameClient::NavigationPolicyInfo popup_policy_info( + popup_request); popup_policy_info.navigation_type = blink::kWebNavigationTypeLinkClicked; popup_policy_info.default_policy = blink::kWebNavigationPolicyNewForegroundTab; @@ -811,14 +850,13 @@ TEST_F(RenderViewImplTest, DecideNavigationPolicyForWebUI) { // continues to receive the original ScreenInfo and not the emualted // ScreenInfo. TEST_F(RenderViewImplScaleFactorTest, DeviceEmulationWithOOPIF) { - DoSetUp(); - // This test should only run with --site-per-process. if (!AreAllSitesIsolatedForTesting()) return; const float device_scale = 2.0f; - float compositor_dsf = IsUseZoomForDSFEnabled() ? 1.f : device_scale; + float compositor_dsf = + compositor_deps_->IsUseZoomForDSFEnabled() ? 1.f : device_scale; SetDeviceScaleFactor(device_scale); LoadHTML( @@ -909,11 +947,7 @@ TEST_F(RenderViewImplTest, OriginReplicationForSwapOut) { // a new tab looks fine, but visiting the second web page renders smaller DOM // elements. We can solve this by updating DSF after swapping in the main frame. // See crbug.com/737777#c37. -TEST_F(RenderViewImplScaleFactorTest, UpdateDSFAfterSwapIn) { - DoSetUp(); - // The bug reproduces if zoom is used for devices scale factor. - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kEnableUseZoomForDSF); +TEST_F(RenderViewImplEnableZoomForDSFTest, UpdateDSFAfterSwapIn) { const float device_scale = 3.0f; SetDeviceScaleFactor(device_scale); EXPECT_EQ(device_scale, view()->GetDeviceScaleFactor()); @@ -952,9 +986,23 @@ TEST_F(RenderViewImplScaleFactorTest, UpdateDSFAfterSwapIn) { common_params.transition = ui::PAGE_TRANSITION_TYPED; provisional_frame->Navigate(common_params, request_params); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(device_scale, view()->GetDeviceScaleFactor()); EXPECT_EQ(device_scale, view()->webview()->ZoomFactorForDeviceScaleFactor()); + + double device_pixel_ratio; + base::string16 get_dpr = + base::ASCIIToUTF16("Number(window.devicePixelRatio)"); + EXPECT_TRUE( + ExecuteJavaScriptAndReturnNumberValue(get_dpr, &device_pixel_ratio)); + EXPECT_EQ(device_scale, device_pixel_ratio); + + int width; + base::string16 get_width = + base::ASCIIToUTF16("Number(document.documentElement.clientWidth)"); + EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(get_width, &width)); + EXPECT_EQ(view()->webview()->Size().width, width * device_scale); } // Test that when a parent detaches a remote child after the provisional @@ -1016,11 +1064,8 @@ TEST_F(RenderViewImplTest, DetachingProxyAlsoDestroysProvisionalFrame) { // Verify that the renderer process doesn't crash when device scale factor // changes after a cross-process navigation has commited. // See https://crbug.com/571603. -TEST_F(RenderViewImplTest, SetZoomLevelAfterCrossProcessNavigation) { - // The bug reproduces if zoom is used for devices scale factor. - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kEnableUseZoomForDSF); - +TEST_F(RenderViewImplEnableZoomForDSFTest, + SetZoomLevelAfterCrossProcessNavigation) { LoadHTML("Hello world!"); // Swap the main frame out after which it should become a WebRemoteFrame. @@ -2312,7 +2357,6 @@ TEST_F(RenderViewImplTest, PreferredSizeZoomed) { } TEST_F(RenderViewImplScaleFactorTest, PreferredSizeWithScaleFactor) { - DoSetUp(); LoadHTML( "<body style='margin:0;'><div style='display:inline-block; " "width:400px; height:400px;'/></body>"); @@ -2523,13 +2567,11 @@ TEST_F(RenderViewImplBlinkSettingsTest, Negative) { EXPECT_TRUE(settings()->ViewportEnabled()); } -TEST_F(RenderViewImplScaleFactorTest, ConverViewportToWindowWithoutZoomForDSF) { - DoSetUp(); - if (IsUseZoomForDSFEnabled()) - return; +TEST_F(RenderViewImplDisableZoomForDSFTest, + ConverViewportToWindowWithoutZoomForDSF) { SetDeviceScaleFactor(2.f); blink::WebRect rect(20, 10, 200, 100); - view()->ConvertViewportToWindow(&rect); + view()->WidgetClient()->ConvertViewportToWindow(&rect); EXPECT_EQ(20, rect.x); EXPECT_EQ(10, rect.y); EXPECT_EQ(200, rect.width); @@ -2537,7 +2579,6 @@ TEST_F(RenderViewImplScaleFactorTest, ConverViewportToWindowWithoutZoomForDSF) { } TEST_F(RenderViewImplScaleFactorTest, ScreenMetricsEmulationWithOriginalDSF1) { - DoSetUp(); SetDeviceScaleFactor(1.f); LoadHTML("<body style='min-height:1000px;'></body>"); @@ -2566,10 +2607,8 @@ TEST_F(RenderViewImplScaleFactorTest, ScreenMetricsEmulationWithOriginalDSF1) { } TEST_F(RenderViewImplScaleFactorTest, ScreenMetricsEmulationWithOriginalDSF2) { - DoSetUp(); SetDeviceScaleFactor(2.f); - float compositor_dsf = - IsUseZoomForDSFEnabled() ? 1.f : 2.f; + float compositor_dsf = compositor_deps_->IsUseZoomForDSFEnabled() ? 1.f : 2.f; LoadHTML("<body style='min-height:1000px;'></body>"); { @@ -2596,14 +2635,12 @@ TEST_F(RenderViewImplScaleFactorTest, ScreenMetricsEmulationWithOriginalDSF2) { // Don't disable here to test that emulation is being shutdown properly. } -TEST_F(RenderViewImplScaleFactorTest, ConverViewportToWindowWithZoomForDSF) { - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kEnableUseZoomForDSF); - DoSetUp(); +TEST_F(RenderViewImplEnableZoomForDSFTest, + ConverViewportToWindowWithZoomForDSF) { SetDeviceScaleFactor(1.f); { blink::WebRect rect(20, 10, 200, 100); - view()->ConvertViewportToWindow(&rect); + view()->WidgetClient()->ConvertViewportToWindow(&rect); EXPECT_EQ(20, rect.x); EXPECT_EQ(10, rect.y); EXPECT_EQ(200, rect.width); @@ -2613,7 +2650,7 @@ TEST_F(RenderViewImplScaleFactorTest, ConverViewportToWindowWithZoomForDSF) { SetDeviceScaleFactor(2.f); { blink::WebRect rect(20, 10, 200, 100); - view()->ConvertViewportToWindow(&rect); + view()->WidgetClient()->ConvertViewportToWindow(&rect); EXPECT_EQ(10, rect.x); EXPECT_EQ(5, rect.y); EXPECT_EQ(100, rect.width); @@ -2622,11 +2659,8 @@ TEST_F(RenderViewImplScaleFactorTest, ConverViewportToWindowWithZoomForDSF) { } #if defined(OS_MACOSX) || defined(USE_AURA) -TEST_F(RenderViewImplScaleFactorTest, +TEST_F(RenderViewImplEnableZoomForDSFTest, DISABLED_GetCompositionCharacterBoundsTest) { // http://crbug.com/582016 - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kEnableUseZoomForDSF); - DoSetUp(); SetDeviceScaleFactor(1.f); #if defined(OS_WIN) // http://crbug.com/508747 @@ -2679,10 +2713,7 @@ const char kAutoResizeTestPage[] = } // namespace -TEST_F(RenderViewImplScaleFactorTest, AutoResizeWithZoomForDSF) { - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kEnableUseZoomForDSF); - DoSetUp(); +TEST_F(RenderViewImplEnableZoomForDSFTest, AutoResizeWithZoomForDSF) { view()->EnableAutoResizeForTesting(gfx::Size(5, 5), gfx::Size(1000, 1000)); LoadHTML(kAutoResizeTestPage); gfx::Size size_at_1x = view()->GetWidget()->size(); @@ -2695,7 +2726,6 @@ TEST_F(RenderViewImplScaleFactorTest, AutoResizeWithZoomForDSF) { } TEST_F(RenderViewImplScaleFactorTest, AutoResizeWithoutZoomForDSF) { - DoSetUp(); view()->EnableAutoResizeForTesting(gfx::Size(5, 5), gfx::Size(1000, 1000)); LoadHTML(kAutoResizeTestPage); gfx::Size size_at_1x = view()->GetWidget()->size(); @@ -2707,6 +2737,104 @@ TEST_F(RenderViewImplScaleFactorTest, AutoResizeWithoutZoomForDSF) { EXPECT_EQ(size_at_1x, size_at_2x); } +TEST_F(RenderViewImplScaleFactorTest, ZoomLevelUpdate) { + // 0 is the default zoom level, nothing will change. + SetZoomLevel(0); + EXPECT_NEAR(0.0, GetZoomLevel(), 0.01); + + // Change the zoom level to 25% and check if the view gets the change. + SetZoomLevel(content::ZoomFactorToZoomLevel(0.25)); + EXPECT_NEAR(content::ZoomFactorToZoomLevel(0.25), GetZoomLevel(), 0.01); +} + #endif +// Origin Trial Policy which vends the test public key so that the token +// can be validated. +class TestOriginTrialPolicy : public blink::OriginTrialPolicy { + bool IsOriginTrialsSupported() const override { return true; } + base::StringPiece GetPublicKey() const override { + // This is the public key which the test below will use to enable origin + // trial features. Trial tokens for use in tests can be created with the + // tool in /tools/origin_trials/generate_token.py, using the private key + // contained in /tools/origin_trials/eftest.key. + static const uint8_t kOriginTrialPublicKey[] = { + 0x75, 0x10, 0xac, 0xf9, 0x3a, 0x1c, 0xb8, 0xa9, 0x28, 0x70, 0xd2, + 0x9a, 0xd0, 0x0b, 0x59, 0xe1, 0xac, 0x2b, 0xb7, 0xd5, 0xca, 0x1f, + 0x64, 0x90, 0x08, 0x8e, 0xa8, 0xe0, 0x56, 0x3a, 0x04, 0xd0, + }; + return base::StringPiece( + reinterpret_cast<const char*>(kOriginTrialPublicKey), + base::size(kOriginTrialPublicKey)); + } + bool IsOriginSecure(const GURL& url) const override { return true; } +}; + +TEST_F(RenderViewImplTest, OriginTrialDisabled) { + // HTML Document with no origin trial. + const char kHTMLWithNoOriginTrial[] = + "<!DOCTYPE html>" + "<html>" + "<head>" + "<title>Origin Trial Test</title>" + "</head>" + "</html>"; + + // Override the origin trial policy to use the test keys. + TestOriginTrialPolicy policy; + blink::TrialTokenValidator::SetOriginTrialPolicyGetter(base::BindRepeating( + [](TestOriginTrialPolicy* policy_ptr) -> blink::OriginTrialPolicy* { + return policy_ptr; + }, + base::Unretained(&policy))); + + // Set the document URL. + LoadHTMLWithUrlOverride(kHTMLWithNoOriginTrial, "https://example.test/"); + blink::WebFrame* web_frame = frame()->GetWebFrame(); + ASSERT_TRUE(web_frame); + ASSERT_TRUE(web_frame->IsWebLocalFrame()); + blink::WebDocument web_doc = web_frame->ToWebLocalFrame()->GetDocument(); + EXPECT_FALSE(blink::WebOriginTrials::isTrialEnabled(&web_doc, "Frobulate")); + // Reset the origin trial policy. + blink::TrialTokenValidator::ResetOriginTrialPolicyGetter(); +} + +TEST_F(RenderViewImplTest, OriginTrialEnabled) { + // HTML Document with an origin trial. + // Note: The token below will expire in 2033. It was generated with the + // command: + // generate_token.py https://example.test Frobulate \ + // -expire-timestamp=2000000000 + const char kHTMLWithOriginTrial[] = + "<!DOCTYPE html>" + "<html>" + "<head>" + "<title>Origin Trial Test</title>" + "<meta http-equiv=\"origin-trial\" " + "content=\"AlrgXVXDH5RSr6sDZiO6/8Hejv3BIhODCSS/0zD8VmDDLNPn463JzEq/Cv/" + "wqt8cRHacGD3cUhKkibGIGQbaXAMAAABUeyJvcmlnaW4iOiAiaHR0cHM6Ly9leGFtcGxlLnR" + "lc3Q6NDQzIiwgImZlYXR1cmUiOiAiRnJvYnVsYXRlIiwgImV4cGlyeSI6IDIwMDAwMDAwMDB" + "9\">" + "</head>" + "</html>"; + + // Override the origin trial policy to use the test keys. + TestOriginTrialPolicy policy; + blink::TrialTokenValidator::SetOriginTrialPolicyGetter(base::BindRepeating( + [](TestOriginTrialPolicy* policy_ptr) -> blink::OriginTrialPolicy* { + return policy_ptr; + }, + base::Unretained(&policy))); + + // Set the document URL so the origin is correct for the trial. + LoadHTMLWithUrlOverride(kHTMLWithOriginTrial, "https://example.test/"); + blink::WebFrame* web_frame = frame()->GetWebFrame(); + ASSERT_TRUE(web_frame); + ASSERT_TRUE(web_frame->IsWebLocalFrame()); + blink::WebDocument web_doc = web_frame->ToWebLocalFrame()->GetDocument(); + EXPECT_TRUE(blink::WebOriginTrials::isTrialEnabled(&web_doc, "Frobulate")); + // Reset the origin trial policy. + blink::TrialTokenValidator::ResetOriginTrialPolicyGetter(); +} + } // namespace content diff --git a/chromium/content/renderer/render_view_impl.cc b/chromium/content/renderer/render_view_impl.cc index 4aba7a9e290..03d9cda9f95 100644 --- a/chromium/content/renderer/render_view_impl.cc +++ b/chromium/content/renderer/render_view_impl.cc @@ -39,6 +39,7 @@ #include "build/build_config.h" #include "cc/base/switches.h" #include "cc/paint/skia_paint_canvas.h" +#include "cc/trees/layer_tree_host.h" #include "content/common/content_constants_internal.h" #include "content/common/dom_storage/dom_storage_namespace_ids.h" #include "content/common/dom_storage/dom_storage_types.h" @@ -72,13 +73,13 @@ #include "content/renderer/browser_plugin/browser_plugin.h" #include "content/renderer/browser_plugin/browser_plugin_manager.h" #include "content/renderer/drop_data_builder.h" -#include "content/renderer/gpu/render_widget_compositor.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" -#include "content/renderer/media/audio_device_factory.h" +#include "content/renderer/media/audio/audio_device_factory.h" #include "content/renderer/media/stream/media_stream_device_observer.h" #include "content/renderer/media/video_capture_impl_manager.h" #include "content/renderer/media/webrtc/peer_connection_dependency_factory.h" @@ -109,6 +110,7 @@ #include "ppapi/buildflags/buildflags.h" #include "skia/ext/platform_canvas.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" +#include "third_party/blink/public/common/frame/user_activation_update_source.h" #include "third_party/blink/public/mojom/page/page_visibility_state.mojom.h" #include "third_party/blink/public/platform/file_path_conversion.h" #include "third_party/blink/public/platform/url_conversion.h" @@ -148,7 +150,6 @@ #include "third_party/blink/public/web/web_hit_test_result.h" #include "third_party/blink/public/web/web_input_element.h" #include "third_party/blink/public/web/web_local_frame.h" -#include "third_party/blink/public/web/web_media_player_action.h" #include "third_party/blink/public/web/web_navigation_policy.h" #include "third_party/blink/public/web/web_page_importance_signals.h" #include "third_party/blink/public/web/web_plugin.h" @@ -216,7 +217,6 @@ using blink::WebImage; using blink::WebInputElement; using blink::WebInputEvent; using blink::WebLocalFrame; -using blink::WebMediaPlayerAction; using blink::WebMouseEvent; using blink::WebNavigationPolicy; using blink::WebNavigationType; @@ -409,39 +409,6 @@ void ApplyBlinkSettings(const base::CommandLine& command_line, } } -// This class represents promise which is robust to (will not be broken by) -// |DidNotSwapReason::SWAP_FAILS| events. -class AlwaysDrawSwapPromise : public cc::SwapPromise { - public: - explicit AlwaysDrawSwapPromise(const ui::LatencyInfo& latency_info) - : latency_info_(latency_info) {} - - ~AlwaysDrawSwapPromise() override = default; - - void DidActivate() override {} - - void WillSwap(viz::CompositorFrameMetadata* metadata, - cc::FrameTokenAllocator* frame_token_allocator) override { - DCHECK(!latency_info_.terminated()); - metadata->latency_info.push_back(latency_info_); - } - - void DidSwap() override {} - - DidNotSwapAction DidNotSwap(DidNotSwapReason reason) override { - return reason == DidNotSwapReason::SWAP_FAILS - ? DidNotSwapAction::KEEP_ACTIVE - : DidNotSwapAction::BREAK_PROMISE; - } - - void OnCommit() override {} - - int64_t TraceId() const override { return latency_info_.trace_id(); } - - private: - ui::LatencyInfo latency_info_; -}; - content::mojom::WindowContainerType WindowFeaturesToContainerType( const blink::WebWindowFeatures& window_features) { if (window_features.background) { @@ -460,7 +427,7 @@ RenderViewImpl::RenderViewImpl( CompositorDependencies* compositor_deps, const mojom::CreateViewParams& params, scoped_refptr<base::SingleThreadTaskRunner> task_runner) - : RenderWidget(params.view_id, + : RenderWidget(params.main_frame_widget_routing_id, compositor_deps, blink::kWebPopupTypeNone, params.visual_properties.screen_info, @@ -468,6 +435,7 @@ RenderViewImpl::RenderViewImpl( params.hidden, params.never_visible, task_runner), + routing_id_(params.view_id), webkit_preferences_(params.web_preferences), send_content_state_immediately_(false), send_preferred_size_changes_(false), @@ -476,7 +444,6 @@ RenderViewImpl::RenderViewImpl( history_list_length_(0), frames_in_progress_(0), target_url_status_(TARGET_NONE), - uses_temporary_zoom_level_(false), #if defined(OS_ANDROID) top_controls_constraints_(BROWSER_CONTROLS_STATE_BOTH), #endif @@ -484,7 +451,7 @@ RenderViewImpl::RenderViewImpl( top_controls_height_(0.f), bottom_controls_height_(0.f), webview_(nullptr), - page_zoom_level_(params.page_zoom_level), + page_zoom_level_(0), main_render_frame_(nullptr), frame_widget_(nullptr), #if defined(OS_ANDROID) @@ -495,11 +462,12 @@ RenderViewImpl::RenderViewImpl( renderer_wide_named_frame_lookup_(false), weak_ptr_factory_(this) { GetWidget()->set_owner_delegate(this); + RenderThread::Get()->AddRoute(routing_id_, this); } void RenderViewImpl::Initialize( mojom::CreateViewParamsPtr params, - const RenderWidget::ShowCallback& show_callback, + RenderWidget::ShowCallback show_callback, scoped_refptr<base::SingleThreadTaskRunner> task_runner) { bool was_created_by_renderer = !show_callback.is_null(); #if defined(OS_ANDROID) @@ -513,12 +481,14 @@ void RenderViewImpl::Initialize( WebFrame* opener_frame = RenderFrameImpl::ResolveOpener(params->opener_frame_route_id); + // Pass WidgetClient(), not |this|, as the WebWidgetClient. The method may + // be overridden in layout tests to inject a test-only WebWidgetClient. webview_ = - WebView::Create(this, + WebView::Create(this, WidgetClient(), is_hidden() ? blink::mojom::PageVisibilityState::kHidden : blink::mojom::PageVisibilityState::kVisible, opener_frame ? opener_frame->View() : nullptr); - RenderWidget::Init(show_callback, webview_->GetWidget()); + RenderWidget::Init(std::move(show_callback), webview_->GetWidget()); g_view_map.Get().insert(std::make_pair(webview(), this)); g_routing_id_view_map.Get().insert(std::make_pair(GetRoutingID(), this)); @@ -535,7 +505,7 @@ void RenderViewImpl::Initialize( webview()->SetShowFPSCounter( command_line.HasSwitch(cc::switches::kShowFPSCounter)); - ApplyWebPreferencesInternal(webkit_preferences_, webview(), compositor_deps_); + ApplyWebPreferencesInternal(webkit_preferences_, webview()); if (switches::IsTouchDragDropEnabled()) webview()->GetSettings()->SetTouchDragDropEnabled(true); @@ -543,24 +513,34 @@ void RenderViewImpl::Initialize( WebSettings::SelectionStrategyType selection_strategy = WebSettings::SelectionStrategyType::kCharacter; const std::string selection_strategy_str = - base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( - switches::kTouchTextSelectionStrategy); + command_line.GetSwitchValueASCII(switches::kTouchTextSelectionStrategy); if (selection_strategy_str == "direction") selection_strategy = WebSettings::SelectionStrategyType::kDirection; webview()->GetSettings()->SetSelectionStrategy(selection_strategy); - std::string passiveListenersDefault = + std::string passive_listeners_default = command_line.GetSwitchValueASCII(switches::kPassiveListenersDefault); - if (!passiveListenersDefault.empty()) { + if (!passive_listeners_default.empty()) { WebSettings::PassiveEventListenerDefault passiveDefault = WebSettings::PassiveEventListenerDefault::kFalse; - if (passiveListenersDefault == "true") + if (passive_listeners_default == "true") passiveDefault = WebSettings::PassiveEventListenerDefault::kTrue; - else if (passiveListenersDefault == "forcealltrue") + else if (passive_listeners_default == "forcealltrue") passiveDefault = WebSettings::PassiveEventListenerDefault::kForceAllTrue; 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); + } + } + ApplyBlinkSettings(command_line, webview()->GetSettings()); if (params->main_frame_routing_id != MSG_ROUTING_NONE) { @@ -609,8 +589,7 @@ void RenderViewImpl::Initialize( idle_user_detector_.reset(new IdleUserDetector()); GetContentClient()->renderer()->RenderViewCreated(this); - - page_zoom_level_ = params->page_zoom_level; + page_zoom_level_ = 0; nav_state_sync_timer_.SetTaskRunner(task_runner); check_preferred_size_timer_.SetTaskRunner(std::move(task_runner)); @@ -618,6 +597,7 @@ void RenderViewImpl::Initialize( RenderViewImpl::~RenderViewImpl() { DCHECK(!frame_widget_); + RenderThread::Get()->RemoveRoute(routing_id_); #if defined(OS_ANDROID) // The date/time picker client is both a std::unique_ptr member of this class @@ -845,15 +825,16 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs, static_cast<WebSettings::SavePreviousDocumentResources>( prefs.save_previous_document_resources)); + settings->SetTextAutosizingEnabled(prefs.text_autosizing_enabled); + settings->SetDoubleTapToZoomEnabled(prefs.double_tap_to_zoom_enabled); + #if defined(OS_ANDROID) settings->SetAllowCustomScrollbarInMainFrame(false); - settings->SetTextAutosizingEnabled(prefs.text_autosizing_enabled); settings->SetAccessibilityFontScaleFactor(prefs.font_scale_factor); settings->SetDeviceScaleAdjustment(prefs.device_scale_adjustment); settings->SetFullscreenSupported(prefs.fullscreen_supported); web_view->SetIgnoreViewportTagScaleLimits(prefs.force_enable_zoom); settings->SetAutoZoomFocusedNodeToLegibleScale(true); - settings->SetDoubleTapToZoomEnabled(prefs.double_tap_to_zoom_enabled); settings->SetMediaPlaybackGestureWhitelistScope( blink::WebString::FromUTF8(prefs.media_playback_gesture_whitelist_scope)); settings->SetDefaultVideoPosterURL( @@ -961,13 +942,47 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs, static_cast<blink::WebEffectiveConnectionType>( prefs.low_priority_iframes_threshold)); - settings->SetPictureInPictureEnabled(prefs.picture_in_picture_enabled); + settings->SetPictureInPictureEnabled( + prefs.picture_in_picture_enabled && + MediaFactory::VideoSurfaceLayerEnabled()); settings->SetDataSaverHoldbackWebApi( prefs.data_saver_holdback_web_api_enabled); settings->SetDataSaverHoldbackMediaApi( prefs.data_saver_holdback_media_api_enabled); + for (const auto& ect_distance_pair : + prefs.lazy_frame_loading_distance_thresholds_px) { + switch (ect_distance_pair.first) { + case net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN: + settings->SetLazyFrameLoadingDistanceThresholdPxUnknown( + ect_distance_pair.second); + break; + case net::EFFECTIVE_CONNECTION_TYPE_OFFLINE: + settings->SetLazyFrameLoadingDistanceThresholdPxOffline( + ect_distance_pair.second); + break; + case net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G: + settings->SetLazyFrameLoadingDistanceThresholdPxSlow2G( + ect_distance_pair.second); + break; + case net::EFFECTIVE_CONNECTION_TYPE_2G: + settings->SetLazyFrameLoadingDistanceThresholdPx2G( + ect_distance_pair.second); + break; + case net::EFFECTIVE_CONNECTION_TYPE_3G: + settings->SetLazyFrameLoadingDistanceThresholdPx3G( + ect_distance_pair.second); + break; + case net::EFFECTIVE_CONNECTION_TYPE_4G: + settings->SetLazyFrameLoadingDistanceThresholdPx4G( + ect_distance_pair.second); + break; + default: + NOTREACHED(); + } + } + #if defined(OS_MACOSX) settings->SetDoubleTapToZoomEnabled(true); web_view->SetMaximumLegibleScale(prefs.default_maximum_page_scale_factor); @@ -982,16 +997,17 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs, RenderViewImpl* RenderViewImpl::Create( CompositorDependencies* compositor_deps, mojom::CreateViewParamsPtr params, - const RenderWidget::ShowCallback& show_callback, + RenderWidget::ShowCallback show_callback, scoped_refptr<base::SingleThreadTaskRunner> task_runner) { DCHECK(params->view_id != MSG_ROUTING_NONE); + DCHECK(params->main_frame_widget_routing_id != MSG_ROUTING_NONE); RenderViewImpl* render_view; 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->Initialize(std::move(params), show_callback, + render_view->Initialize(std::move(params), std::move(show_callback), std::move(task_runner)); return render_view; } @@ -1030,6 +1046,24 @@ bool RenderViewImpl::RenderWidgetWillHandleMouseEvent( return mouse_lock_dispatcher_->WillHandleMouseEvent(event); } +void RenderViewImpl::SetActive(bool active) { + if (webview()) + webview()->SetIsActive(active); +} + +void RenderViewImpl::SetBackgroundOpaque(bool opaque) { + if (!frame_widget_) + return; + + if (opaque) { + frame_widget_->ClearBaseBackgroundColorOverride(); + frame_widget_->ClearBackgroundColorOverride(); + } else { + frame_widget_->SetBaseBackgroundColorOverride(SK_ColorTRANSPARENT); + frame_widget_->SetBackgroundColorOverride(SK_ColorTRANSPARENT); + } +} + // IPC::Listener implementation ---------------------------------------------- bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) { @@ -1057,24 +1091,19 @@ bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) { OnEnumerateDirectoryResponse) IPC_MESSAGE_HANDLER(ViewMsg_ClosePage, OnClosePage) IPC_MESSAGE_HANDLER(ViewMsg_MoveOrResizeStarted, OnMoveOrResizeStarted) - IPC_MESSAGE_HANDLER(ViewMsg_SetBackgroundOpaque, OnSetBackgroundOpaque) IPC_MESSAGE_HANDLER(ViewMsg_EnablePreferredSizeChangedMode, OnEnablePreferredSizeChangedMode) IPC_MESSAGE_HANDLER(ViewMsg_DisableScrollbarsForSmallWindows, OnDisableScrollbarsForSmallWindows) IPC_MESSAGE_HANDLER(ViewMsg_SetRendererPrefs, OnSetRendererPrefs) - IPC_MESSAGE_HANDLER(ViewMsg_MediaPlayerActionAt, OnMediaPlayerActionAt) IPC_MESSAGE_HANDLER(ViewMsg_PluginActionAt, OnPluginActionAt) - IPC_MESSAGE_HANDLER(ViewMsg_SetActive, OnSetActive) IPC_MESSAGE_HANDLER(ViewMsg_ResolveTapDisambiguation, OnResolveTapDisambiguation) - IPC_MESSAGE_HANDLER(ViewMsg_ForceRedraw, OnForceRedraw) IPC_MESSAGE_HANDLER(ViewMsg_SelectWordAroundCaret, OnSelectWordAroundCaret) // Page messages. IPC_MESSAGE_HANDLER(PageMsg_UpdateWindowScreenRect, OnUpdateWindowScreenRect) - IPC_MESSAGE_HANDLER(PageMsg_SetZoomLevel, OnSetZoomLevel) IPC_MESSAGE_HANDLER(PageMsg_WasHidden, OnPageWasHidden) IPC_MESSAGE_HANDLER(PageMsg_WasShown, OnPageWasShown) IPC_MESSAGE_HANDLER(PageMsg_SetHistoryOffsetAndLength, @@ -1083,7 +1112,7 @@ bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(PageMsg_PausePageScheduledTasks, OnPausePageScheduledTasks) IPC_MESSAGE_HANDLER(PageMsg_UpdateScreenInfo, OnUpdateScreenInfo) - IPC_MESSAGE_HANDLER(PageMsg_FreezePage, OnFreezePage) + IPC_MESSAGE_HANDLER(PageMsg_SetPageFrozen, SetPageFrozen) #if defined(OS_MACOSX) IPC_MESSAGE_HANDLER(ViewMsg_Close, OnClose) @@ -1099,6 +1128,7 @@ bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) { } void RenderViewImpl::OnSelectWordAroundCaret() { + // TODO(ajwong): Move this into RenderWidget. http://crbug.com/545684 // Set default values for the ACK bool did_select = false; int start_adjust = 0; @@ -1120,8 +1150,8 @@ void RenderViewImpl::OnSelectWordAroundCaret() { input_handler_->set_handling_input_event(false); } } - Send(new ViewHostMsg_SelectWordAroundCaretAck(GetRoutingID(), did_select, - start_adjust, end_adjust)); + Send(new ViewHostMsg_SelectWordAroundCaretAck( + GetWidget()->routing_id(), did_select, start_adjust, end_adjust)); } void RenderViewImpl::OnUpdateTargetURLAck() { @@ -1189,25 +1219,16 @@ void RenderViewImpl::SendFrameStateUpdates() { frames_with_pending_state_.clear(); } -void RenderViewImpl::ApplyWebPreferencesInternal( - const WebPreferences& prefs, - blink::WebView* web_view, - CompositorDependencies* compositor_deps) { +void RenderViewImpl::ApplyWebPreferencesInternal(const WebPreferences& prefs, + blink::WebView* web_view) { ApplyWebPreferences(prefs, web_view); } -void RenderViewImpl::OnForceRedraw(const ui::LatencyInfo& latency_info) { - if (RenderWidgetCompositor* rwc = compositor()) { - rwc->QueueSwapPromise( - std::make_unique<AlwaysDrawSwapPromise>(latency_info)); - rwc->SetNeedsForcedRedraw(); - } -} - // blink::WebViewClient ------------------------------------------------------ -// TODO(csharrison): Migrate this method to WebFrameClient / RenderFrameImpl, as -// it is now serviced by a mojo interface scoped to the opener frame. +// TODO(csharrison): Migrate this method to WebLocalFrameClient / +// RenderFrameImpl, as it is now serviced by a mojo interface scoped to the +// opener frame. WebView* RenderViewImpl::CreateView(WebLocalFrame* creator, const WebURLRequest& request, const WebWindowFeatures& features, @@ -1217,10 +1238,16 @@ WebView* RenderViewImpl::CreateView(WebLocalFrame* creator, WebSandboxFlags sandbox_flags) { RenderFrameImpl* creator_frame = RenderFrameImpl::FromWebFrame(creator); mojom::CreateNewWindowParamsPtr params = mojom::CreateNewWindowParams::New(); - params->user_gesture = - WebUserGestureIndicator::IsProcessingUserGesture(creator); + + // User Activation v2 moves user gesture checks to the browser process, with + // the exception of the extensions case handled through the following |if|. + params->mimic_user_gesture = + base::FeatureList::IsEnabled(features::kUserActivationV2) + ? false + : WebUserGestureIndicator::IsProcessingUserGesture(creator); if (GetContentClient()->renderer()->AllowPopup()) - params->user_gesture = true; + params->mimic_user_gesture = true; + params->window_container_type = WindowFeaturesToContainerType(features); params->session_storage_namespace_id = AllocateSessionStorageNamespaceId(); @@ -1247,7 +1274,7 @@ WebView* RenderViewImpl::CreateView(WebLocalFrame* creator, // moved on send. bool is_background_tab = params->disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB; - bool opened_by_user_gesture = params->user_gesture; + bool opened_by_user_gesture = params->mimic_user_gesture; mojom::CreateNewWindowStatus status; mojom::CreateNewWindowReplyPtr reply; @@ -1273,7 +1300,10 @@ WebView* RenderViewImpl::CreateView(WebLocalFrame* creator, DCHECK_NE(MSG_ROUTING_NONE, reply->main_frame_route_id); DCHECK_NE(MSG_ROUTING_NONE, reply->main_frame_widget_route_id); - WebUserGestureIndicator::ConsumeUserGesture(creator); + // The browser allowed creation of a new window and consumed the user + // activation (UAv2 only). + WebUserGestureIndicator::ConsumeUserGesture( + creator, blink::UserActivationUpdateSource::kBrowser); // While this view may be a background extension page, it can spawn a visible // render view. So we just assume that the new one is not another background @@ -1314,13 +1344,12 @@ WebView* RenderViewImpl::CreateView(WebLocalFrame* creator, view_params->hidden = is_background_tab; view_params->never_visible = never_visible; view_params->visual_properties = visual_properties; - view_params->page_zoom_level = page_zoom_level_; // Unretained() is safe here because our calling function will also call // show(). RenderWidget::ShowCallback show_callback = - base::Bind(&RenderFrameImpl::ShowCreatedWindow, - base::Unretained(creator_frame), opened_by_user_gesture); + base::BindOnce(&RenderFrameImpl::ShowCreatedWindow, + base::Unretained(creator_frame), opened_by_user_gesture); RenderViewImpl* view = RenderViewImpl::Create( compositor_deps_, std::move(view_params), std::move(show_callback), @@ -1620,73 +1649,12 @@ void RenderViewImpl::DidHandleGestureEvent(const WebGestureEvent& event, } } -blink::WebLayerTreeView* RenderViewImpl::InitializeLayerTreeView() { - // TODO(!wjmaclean): We should be able to just remove this function, and - // expect the RenderWidget version of the function to be called instead. - // However, we have a diamond inheritance pattern going on: - // WebWidgetClient - // | | - // RenderWidget WebViewClient - // | | - // RenderViewImpl - // - // and this seems to prefer calling the empty version in WebWidgetClient - // or WebViewClient over the non-empty one in RenderWidget. - return RenderWidget::InitializeLayerTreeView(); -} - -void RenderViewImpl::CloseWidgetSoon() { - RenderWidget::CloseWidgetSoon(); -} - -void RenderViewImpl::ConvertViewportToWindow(blink::WebRect* rect) { - RenderWidget::ConvertViewportToWindow(rect); -} - -void RenderViewImpl::ConvertWindowToViewport(blink::WebFloatRect* rect) { - RenderWidget::ConvertWindowToViewport(rect); -} - -void RenderViewImpl::DidAutoResize(const blink::WebSize& newSize) { - RenderWidget::DidAutoResize(newSize); -} - -void RenderViewImpl::DidOverscroll( - const blink::WebFloatSize& overscrollDelta, - const blink::WebFloatSize& accumulatedOverscroll, - const blink::WebFloatPoint& positionInViewport, - const blink::WebFloatSize& velocityInViewport, - const cc::OverscrollBehavior& behavior) { - RenderWidget::DidOverscroll(overscrollDelta, accumulatedOverscroll, - positionInViewport, velocityInViewport, behavior); -} - -void RenderViewImpl::HasTouchEventHandlers(bool has_handlers) { - RenderWidget::HasTouchEventHandlers(has_handlers); -} - -blink::WebRect RenderViewImpl::RootWindowRect() { - return RenderWidget::WindowRect(); -} - -blink::WebScreenInfo RenderViewImpl::GetScreenInfo() { - return RenderWidget::GetScreenInfo(); -} - -void RenderViewImpl::SetToolTipText(const blink::WebString& text, - blink::WebTextDirection hint) { - RenderWidget::SetToolTipText(text, hint); -} - -void RenderViewImpl::SetTouchAction(blink::WebTouchAction touchAction) { - RenderWidget::SetTouchAction(touchAction); -} - blink::WebWidgetClient* RenderViewImpl::WidgetClient() { - return static_cast<RenderWidget*>(this); + return this; } -// blink::WebFrameClient ----------------------------------------------------- +// blink::WebLocalFrameClient +// ----------------------------------------------------- void RenderViewImpl::SetEditCommandForNextKeyEvent(const std::string& name, const std::string& value) { @@ -1702,13 +1670,13 @@ const std::string& RenderViewImpl::GetAcceptLanguages() const { } void RenderViewImpl::ConvertViewportToWindowViaWidget(blink::WebRect* rect) { - ConvertViewportToWindow(rect); + WidgetClient()->ConvertViewportToWindow(rect); } gfx::RectF RenderViewImpl::ElementBoundsInWindow( const blink::WebElement& element) { blink::WebRect bounding_box_in_window = element.BoundsInViewport(); - ConvertViewportToWindowViaWidget(&bounding_box_in_window); + WidgetClient()->ConvertViewportToWindow(&bounding_box_in_window); return gfx::RectF(bounding_box_in_window); } @@ -1720,7 +1688,7 @@ void RenderViewImpl::CheckPreferredSize() { return; blink::WebSize tmp_size = webview()->ContentsPreferredMinimumSize(); blink::WebRect tmp_rect(0, 0, tmp_size.width, tmp_size.height); - ConvertViewportToWindow(&tmp_rect); + WidgetClient()->ConvertViewportToWindow(&tmp_rect); gfx::Size size(tmp_rect.width, tmp_rect.height); if (size == preferred_size_) return; @@ -1749,7 +1717,7 @@ RenderFrameImpl* RenderViewImpl::GetMainRenderFrame() { } int RenderViewImpl::GetRoutingID() const { - return routing_id(); + return routing_id_; } gfx::Size RenderViewImpl::GetSize() const { @@ -1796,31 +1764,14 @@ void RenderViewImpl::OnSetPageScale(float page_scale_factor) { webview()->SetPageScaleFactor(page_scale_factor); } -void RenderViewImpl::OnSetZoomLevel( - PageMsg_SetZoomLevel_Command command, - double zoom_level) { - switch (command) { - case PageMsg_SetZoomLevel_Command::CLEAR_TEMPORARY: - uses_temporary_zoom_level_ = false; - break; - case PageMsg_SetZoomLevel_Command::SET_TEMPORARY: - uses_temporary_zoom_level_ = true; - break; - case PageMsg_SetZoomLevel_Command::USE_CURRENT_TEMPORARY_MODE: - // Don't override a temporary zoom level without an explicit SET. - if (uses_temporary_zoom_level_) - return; - break; - default: - NOTIMPLEMENTED(); - } +void RenderViewImpl::UpdateZoomLevel(double zoom_level) { webview()->HidePopups(); SetZoomLevel(zoom_level); } void RenderViewImpl::OnUpdateWebPreferences(const WebPreferences& prefs) { webkit_preferences_ = prefs; - ApplyWebPreferencesInternal(webkit_preferences_, webview(), compositor_deps_); + ApplyWebPreferencesInternal(webkit_preferences_, webview()); } void RenderViewImpl::OnEnumerateDirectoryResponse( @@ -1882,12 +1833,6 @@ void RenderViewImpl::OnSetRendererPrefs( } } -void RenderViewImpl::OnMediaPlayerActionAt(const gfx::Point& location, - const WebMediaPlayerAction& action) { - if (webview()) - webview()->PerformMediaPlayerAction(action, location); -} - void RenderViewImpl::OnPluginActionAt(const gfx::Point& location, const WebPluginAction& action) { if (webview()) @@ -1910,11 +1855,13 @@ void RenderViewImpl::OnClosePage() { Send(new ViewHostMsg_ClosePage_ACK(GetRoutingID())); } +#if defined(OS_MACOSX) void RenderViewImpl::OnClose() { if (closing_) RenderThread::Get()->Send(new ViewHostMsg_Close_ACK(GetRoutingID())); RenderWidget::OnClose(); } +#endif void RenderViewImpl::OnMoveOrResizeStarted() { if (webview()) @@ -1927,6 +1874,13 @@ void RenderViewImpl::ResizeWebWidget() { 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"); @@ -1998,24 +1952,6 @@ void RenderViewImpl::OnSynchronizeVisualProperties( } } -void RenderViewImpl::OnSetBackgroundOpaque(bool opaque) { - if (!frame_widget_) - return; - - if (opaque) { - frame_widget_->ClearBaseBackgroundColorOverride(); - frame_widget_->ClearBackgroundColorOverride(); - } else { - frame_widget_->SetBaseBackgroundColorOverride(SK_ColorTRANSPARENT); - frame_widget_->SetBackgroundColorOverride(SK_ColorTRANSPARENT); - } -} - -void RenderViewImpl::OnSetActive(bool active) { - if (webview()) - webview()->SetIsActive(active); -} - blink::WebWidget* RenderViewImpl::GetWebWidget() const { if (frame_widget_) return frame_widget_; @@ -2077,10 +2013,9 @@ void RenderViewImpl::OnUpdateScreenInfo(const ScreenInfo& screen_info) { screen_info_ = screen_info; } -void RenderViewImpl::OnFreezePage() { - if (webview()) { - webview()->FreezePage(); - } +void RenderViewImpl::SetPageFrozen(bool frozen) { + if (webview()) + webview()->SetPageFrozen(frozen); } GURL RenderViewImpl::GetURLForGraphicsContext3D() { @@ -2117,7 +2052,7 @@ void RenderViewImpl::DidCompletePageScaleAnimation() { void RenderViewImpl::SetScreenMetricsEmulationParameters( bool enabled, const blink::WebDeviceEmulationParams& params) { - if (webview() && compositor()) { + if (webview() && layer_tree_view()) { if (enabled) webview()->EnableDeviceEmulation(params); else @@ -2167,6 +2102,14 @@ void RenderViewImpl::PageImportanceSignalsChanged() { main_render_frame_->GetRoutingID(), signals)); } +void RenderViewImpl::DidAutoResize(const blink::WebSize& newSize) { + RenderWidget::DidAutoResize(newSize); +} + +blink::WebRect RenderViewImpl::RootWindowRect() { + return WidgetClient()->WindowRect(); +} + #if defined(OS_ANDROID) bool RenderViewImpl::OpenDateTimeChooser( const blink::WebDateTimeChooserParams& params, @@ -2246,7 +2189,7 @@ bool RenderViewImpl::DidTapMultipleTargets( DCHECK(webview_->IsAcceleratedCompositingActive()); webview_->UpdateAllLifecyclePhases(); - webview_->PaintIgnoringCompositing(&canvas, zoom_rect); + webview_->PaintContentIgnoringCompositing(&canvas, zoom_rect); } gfx::Rect zoom_rect_in_screen = @@ -2260,7 +2203,7 @@ bool RenderViewImpl::DidTapMultipleTargets( // A SharedMemoryHandle is sent to the browser process, which is // responsible for freeing the shared memory when no longer needed. Send(new ViewHostMsg_ShowDisambiguationPopup( - GetRoutingID(), physical_window_zoom_rect, canvas_size, + GetWidget()->routing_id(), physical_window_zoom_rect, canvas_size, shm->TakeHandle())); handled = true; @@ -2304,13 +2247,13 @@ void RenderViewImpl::SetFocusAndActivateForTesting(bool enable) { if (enable) { if (has_focus()) return; - OnSetActive(true); + SetActive(true); OnSetFocus(true); } else { if (!has_focus()) return; OnSetFocus(false); - OnSetActive(false); + SetActive(false); } } @@ -2331,8 +2274,8 @@ void RenderViewImpl::SetDeviceScaleFactorForTesting(float factor) { 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 (compositor_) - compositor_->RequestNewLocalSurfaceId(); + if (layer_tree_view()) + layer_tree_view()->RequestNewLocalSurfaceId(); OnSynchronizeVisualProperties(visual_properties); } @@ -2353,8 +2296,8 @@ void RenderViewImpl::SetDeviceColorSpaceForTesting( 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 (compositor_) - compositor_->RequestNewLocalSurfaceId(); + if (layer_tree_view()) + layer_tree_view()->RequestNewLocalSurfaceId(); OnSynchronizeVisualProperties(visual_properties); } diff --git a/chromium/content/renderer/render_view_impl.h b/chromium/content/renderer/render_view_impl.h index 77f18279cdd..bcd629c4386 100644 --- a/chromium/content/renderer/render_view_impl.h +++ b/chromium/content/renderer/render_view_impl.h @@ -28,7 +28,6 @@ #include "content/common/content_export.h" #include "content/common/frame_message_enums.h" #include "content/common/navigation_gesture.h" -#include "content/common/page_message_enums.h" #include "content/common/view_message_enums.h" #include "content/public/common/browser_controls_state.h" #include "content/public/common/drop_data.h" @@ -53,6 +52,7 @@ #include "third_party/blink/public/web/web_navigation_type.h" #include "third_party/blink/public/web/web_node.h" #include "third_party/blink/public/web/web_view_client.h" +#include "third_party/blink/public/web/web_widget_client.h" #include "ui/base/window_open_disposition.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect_f.h" @@ -62,20 +62,12 @@ #include "content/renderer/android/renderer_date_time_picker.h" #endif -#if defined(COMPILER_MSVC) -// RenderViewImpl is a diamond-shaped hierarchy, with WebWidgetClient at the -// root. VS warns when we inherit the WebWidgetClient method implementations -// from RenderWidget. It's safe to ignore that warning. -#pragma warning(disable: 4250) -#endif - namespace blink { class WebDateTimeChooserCompletion; class WebGestureEvent; class WebMouseEvent; class WebURLRequest; struct WebDateTimeChooserParams; -struct WebMediaPlayerAction; struct WebPluginAction; struct WebWindowFeatures; } // namespace blink @@ -107,7 +99,7 @@ class CreateViewParams; // // For context, please see https://crbug.com/467770 and // https://www.chromium.org/developers/design-documents/site-isolation. -class CONTENT_EXPORT RenderViewImpl : public RenderWidget, +class CONTENT_EXPORT RenderViewImpl : private RenderWidget, public blink::WebViewClient, public RenderWidgetOwnerDelegate, public RenderView { @@ -122,7 +114,7 @@ class CONTENT_EXPORT RenderViewImpl : public RenderWidget, static RenderViewImpl* Create( CompositorDependencies* compositor_deps, mojom::CreateViewParamsPtr params, - const RenderWidget::ShowCallback& show_callback, + RenderWidget::ShowCallback show_callback, scoped_refptr<base::SingleThreadTaskRunner> task_runner); // Used by content_layouttest_support to hook into the creation of @@ -243,34 +235,6 @@ class CONTENT_EXPORT RenderViewImpl : public RenderWidget, bool OnMessageReceived(const IPC::Message& msg) override; - // blink::WebWidgetClient implementation ------------------------------------ - - // Most methods are handled by RenderWidget. - void Show(blink::WebNavigationPolicy policy) override; - void DidHandleGestureEvent(const blink::WebGestureEvent& event, - bool event_cancelled) override; - blink::WebLayerTreeView* InitializeLayerTreeView() override; - - bool CanHandleGestureEvent() override; - bool CanUpdateLayout() override; - - // TODO(lfg): Remove once WebViewClient no longer inherits from - // WebWidgetClient. - void CloseWidgetSoon() override; - void ConvertViewportToWindow(blink::WebRect* rect) override; - void ConvertWindowToViewport(blink::WebFloatRect* rect) override; - void DidOverscroll(const blink::WebFloatSize& overscrollDelta, - const blink::WebFloatSize& accumulatedOverscroll, - const blink::WebFloatPoint& positionInViewport, - const blink::WebFloatSize& velocityInViewport, - const cc::OverscrollBehavior& behavior) override; - void HasTouchEventHandlers(bool has_handlers) override; - blink::WebScreenInfo GetScreenInfo() override; - void SetToolTipText(const blink::WebString&, - blink::WebTextDirection hint) override; - void SetTouchAction(cc::TouchAction touchAction) override; - blink::WebWidgetClient* WidgetClient() override; - // blink::WebViewClient implementation -------------------------------------- blink::WebView* CreateView(blink::WebLocalFrame* creator, @@ -298,6 +262,7 @@ class CONTENT_EXPORT RenderViewImpl : public RenderWidget, void FocusPrevious() override; 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. @@ -319,6 +284,8 @@ class CONTENT_EXPORT RenderViewImpl : public RenderWidget, void DidAutoResize(const blink::WebSize& newSize) override; blink::WebRect RootWindowRect() override; void DidFocus(blink::WebLocalFrame* calling_frame) override; + bool CanHandleGestureEvent() override; + WebWidgetClient* WidgetClient() override; #if defined(OS_ANDROID) // Only used on Android since all other platforms implement @@ -354,8 +321,6 @@ class CONTENT_EXPORT RenderViewImpl : public RenderWidget, void ConvertViewportToWindowViaWidget(blink::WebRect* rect) override; gfx::RectF ElementBoundsInWindow(const blink::WebElement& element) override; - bool uses_temporary_zoom_level() const { return uses_temporary_zoom_level_; } - // Please do not add your stuff randomly to the end here. If there is an // appropriate section, add it there. If not, there are some random functions // nearer to the top you can add it to. @@ -371,6 +336,7 @@ class CONTENT_EXPORT RenderViewImpl : public RenderWidget, bool renderer_wide_named_frame_lookup() { return renderer_wide_named_frame_lookup_; } + void UpdateZoomLevel(double zoom_level); protected: // RenderWidget overrides: @@ -383,13 +349,14 @@ class CONTENT_EXPORT RenderViewImpl : public RenderWidget, 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); void Initialize(mojom::CreateViewParamsPtr params, - const RenderWidget::ShowCallback& show_callback, + RenderWidget::ShowCallback show_callback, scoped_refptr<base::SingleThreadTaskRunner> task_runner); void SetScreenMetricsEmulationParameters( bool enabled, @@ -460,7 +427,7 @@ class CONTENT_EXPORT RenderViewImpl : public RenderWidget, SetZoomLevelAfterCrossProcessNavigation); FRIEND_TEST_ALL_PREFIXES(RenderViewImplScaleFactorTest, ConverViewportToScreenWithZoomForDSF); - FRIEND_TEST_ALL_PREFIXES(RenderViewImplScaleFactorTest, + FRIEND_TEST_ALL_PREFIXES(RenderViewImplEnableZoomForDSFTest, GetCompositionCharacterBoundsTest); enum ErrorPageType { @@ -469,17 +436,24 @@ class CONTENT_EXPORT RenderViewImpl : public RenderWidget, CONNECTION_ERROR, }; + // RenderWidget public API that should no longer go through RenderView. + using RenderWidget::routing_id; + // RenderWidgetOwnerDelegate implementation ---------------------------------- bool RenderWidgetWillHandleMouseEvent( const blink::WebMouseEvent& event) override; + void SetActive(bool active) override; + void SetBackgroundOpaque(bool opaque) override; - // Old WebFrameClient implementations ---------------------------------------- + // Old WebLocalFrameClient implementations + // ---------------------------------------- - // RenderViewImpl used to be a WebFrameClient, but now RenderFrameImpl is the - // WebFrameClient. However, many implementations of WebFrameClient methods - // still live here and are called from RenderFrameImpl. These implementations - // are to be moved to RenderFrameImpl <http://crbug.com/361761>. + // RenderViewImpl used to be a WebLocalFrameClient, but now RenderFrameImpl is + // the WebLocalFrameClient. However, many implementations of + // WebLocalFrameClient methods still live here and are called from + // RenderFrameImpl. These implementations are to be moved to RenderFrameImpl + // <http://crbug.com/361761>. static Referrer GetReferrerFromRequest( blink::WebFrame* frame, @@ -489,8 +463,13 @@ class CONTENT_EXPORT RenderViewImpl : public RenderWidget, blink::WebNavigationPolicy policy); void ApplyWebPreferencesInternal(const WebPreferences& prefs, - blink::WebView* web_view, - CompositorDependencies* compositor_deps); + 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 ------------------------------------------------------ // @@ -500,7 +479,9 @@ class CONTENT_EXPORT RenderViewImpl : public RenderWidget, void OnAllowScriptToClose(bool script_can_close); void OnCancelDownload(int32_t download_id); void OnClosePage(); +#if defined(OS_MACOSX) void OnClose(); +#endif void OnDeterminePageLanguage(); void OnDisableScrollbarsForSmallWindows( @@ -508,16 +489,12 @@ class CONTENT_EXPORT RenderViewImpl : public RenderWidget, void OnEnablePreferredSizeChangedMode(); void OnEnumerateDirectoryResponse(int id, const std::vector<base::FilePath>& paths); - void OnMediaPlayerActionAt(const gfx::Point& location, - const blink::WebMediaPlayerAction& action); 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 OnSetActive(bool active); - void OnSetBackgroundOpaque(bool opaque); void OnExitFullscreen(); void OnSetHistoryOffsetAndLength(int history_offset, int history_length); void OnSetInitialFocus(bool reverse); @@ -527,18 +504,16 @@ class CONTENT_EXPORT RenderViewImpl : public RenderWidget, void OnUpdateTargetURLAck(); void OnUpdateWebPreferences(const WebPreferences& prefs); void OnSetPageScale(float page_scale_factor); - void OnForceRedraw(const ui::LatencyInfo& latency_info); void OnSelectWordAroundCaret(); void OnAudioStateChanged(bool is_audio_playing); void OnPausePageScheduledTasks(bool paused); // Page message handlers ----------------------------------------------------- void OnUpdateWindowScreenRect(gfx::Rect window_screen_rect); - void OnSetZoomLevel(PageMsg_SetZoomLevel_Command command, double zoom_level); void OnPageWasHidden(); void OnPageWasShown(); void OnUpdateScreenInfo(const ScreenInfo& screen_info); - void OnFreezePage(); + void SetPageFrozen(bool frozen); // Adding a new message handler? Please add it in alphabetical order above // and put it in the same position in the .cc file. @@ -594,6 +569,10 @@ class CONTENT_EXPORT RenderViewImpl : public RenderWidget, // it in the same order in the .cc file as it was in the header. // --------------------------------------------------------------------------- + // Routing ID that allows us to communicate with the corresponding + // RenderViewHost in the parent browser process. + const int32_t routing_id_; + // Settings ------------------------------------------------------------------ WebPreferences webkit_preferences_; @@ -680,9 +659,6 @@ class CONTENT_EXPORT RenderViewImpl : public RenderWidget, // The next target URL we want to send to the browser. GURL pending_target_url_; - // Indicates whether this view overrides url-based zoom settings. - bool uses_temporary_zoom_level_; - #if defined(OS_ANDROID) // Cache the old browser controls state constraints. Used when updating // current value only without altering the constraints. diff --git a/chromium/content/renderer/render_view_impl_android.cc b/chromium/content/renderer/render_view_impl_android.cc index 2d9f48df496..f6835cd2ef5 100644 --- a/chromium/content/renderer/render_view_impl_android.cc +++ b/chromium/content/renderer/render_view_impl_android.cc @@ -7,35 +7,35 @@ #include "base/command_line.h" #include "cc/trees/layer_tree_host.h" #include "content/common/view_messages.h" -#include "content/renderer/gpu/render_widget_compositor.h" +#include "content/renderer/gpu/layer_tree_view.h" #include "third_party/blink/public/web/web_view.h" namespace content { -// Check content::BrowserControlsState, and -// blink::WebWidget::BrowserControlsState +// Check content::BrowserControlsState, and cc::BrowserControlsState // are kept in sync. static_assert(int(BROWSER_CONTROLS_STATE_SHOWN) == - int(blink::kWebBrowserControlsShown), + int(cc::BrowserControlsState::kShown), "mismatching enums: SHOWN"); static_assert(int(BROWSER_CONTROLS_STATE_HIDDEN) == - int(blink::kWebBrowserControlsHidden), + int(cc::BrowserControlsState::kHidden), "mismatching enums: HIDDEN"); static_assert(int(BROWSER_CONTROLS_STATE_BOTH) == - int(blink::kWebBrowserControlsBoth), + int(cc::BrowserControlsState::kBoth), "mismatching enums: BOTH"); -blink::WebBrowserControlsState ContentToBlink(BrowserControlsState state) { - return static_cast<blink::WebBrowserControlsState>(state); +cc::BrowserControlsState ContentToCc(BrowserControlsState state) { + return static_cast<cc::BrowserControlsState>(state); } void RenderViewImpl::UpdateBrowserControlsState( BrowserControlsState constraints, BrowserControlsState current, bool animate) { - if (GetWebWidget()) - GetWebWidget()->UpdateBrowserControlsState( - ContentToBlink(constraints), ContentToBlink(current), animate); + if (GetWebWidget()) { + GetWebWidget()->UpdateBrowserControlsState(ContentToCc(constraints), + ContentToCc(current), animate); + } top_controls_constraints_ = constraints; } diff --git a/chromium/content/renderer/render_widget.cc b/chromium/content/renderer/render_widget.cc index f0374259db0..560c7caaa74 100644 --- a/chromium/content/renderer/render_widget.cc +++ b/chromium/content/renderer/render_widget.cc @@ -4,10 +4,13 @@ #include "content/renderer/render_widget.h" +#include <cmath> +#include <limits> #include <memory> #include <utility> #include "base/auto_reset.h" +#include "base/base_switches.h" #include "base/bind.h" #include "base/command_line.h" #include "base/feature_list.h" @@ -17,22 +20,29 @@ #include "base/memory/singleton.h" #include "base/metrics/histogram_macros.h" #include "base/stl_util.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/sys_info.h" #include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" #include "cc/animation/animation_host.h" +#include "cc/base/switches.h" #include "cc/input/touch_action.h" #include "cc/trees/layer_tree_frame_sink.h" #include "cc/trees/layer_tree_host.h" +#include "cc/trees/ukm_manager.h" +#include "components/viz/common/features.h" #include "components/viz/common/frame_sinks/begin_frame_source.h" #include "components/viz/common/frame_sinks/copy_output_request.h" +#include "components/viz/common/switches.h" +#include "content/common/content_switches_internal.h" #include "content/common/drag_event_source_info.h" #include "content/common/drag_messages.h" #include "content/common/render_frame_metadata.mojom.h" #include "content/common/render_message_filter.mojom.h" #include "content/common/swapped_out_messages.h" +#include "content/common/tab_switching_time_callback.h" #include "content/common/text_input_state.h" #include "content/common/view_messages.h" #include "content/public/common/content_client.h" @@ -49,13 +59,14 @@ #include "content/renderer/drop_data_builder.h" #include "content/renderer/external_popup_menu.h" #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/gpu/render_widget_compositor.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" #include "content/renderer/pepper/pepper_plugin_instance_impl.h" #include "content/renderer/render_frame_impl.h" +#include "content/renderer/render_frame_metadata_observer_impl.h" #include "content/renderer/render_frame_proxy.h" #include "content/renderer/render_process.h" #include "content/renderer/render_thread_impl.h" @@ -63,14 +74,16 @@ #include "content/renderer/render_widget_owner_delegate.h" #include "content/renderer/renderer_blink_platform_impl.h" #include "content/renderer/resizing_mode_selector.h" +#include "gpu/command_buffer/service/gpu_switches.h" #include "ipc/ipc_message_start.h" #include "ipc/ipc_sync_message.h" #include "ipc/ipc_sync_message_filter.h" +#include "media/base/media_switches.h" #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/scheduler/web_main_thread_scheduler.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" #include "third_party/blink/public/platform/web_drag_data.h" #include "third_party/blink/public/platform/web_drag_operation.h" @@ -95,12 +108,16 @@ #include "third_party/skia/include/core/SkShader.h" #include "ui/base/clipboard/clipboard.h" #include "ui/base/ui_base_features.h" +#include "ui/base/ui_base_switches.h" #include "ui/events/base_event_utils.h" #include "ui/gfx/geometry/point_conversions.h" #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/geometry/size_conversions.h" #include "ui/gfx/skia_util.h" +#include "ui/gfx/switches.h" #include "ui/gl/gl_switches.h" +#include "ui/native_theme/native_theme_features.h" +#include "ui/native_theme/overlay_scrollbar_constants_aura.h" #include "ui/surface/transport_dib.h" #if defined(OS_ANDROID) @@ -129,7 +146,6 @@ using blink::WebDragOperationsMask; using blink::WebDragData; using blink::WebFrameWidget; using blink::WebGestureEvent; -using blink::WebImage; using blink::WebInputEvent; using blink::WebInputEventResult; using blink::WebInputMethodController; @@ -155,6 +171,13 @@ namespace content { namespace { +using RoutingIDWidgetMap = std::map<int32_t, RenderWidget*>; +base::LazyInstance<RoutingIDWidgetMap>::Leaky g_routing_id_widget_map = + LAZY_INSTANCE_INITIALIZER; + +const base::Feature kUnpremultiplyAndDitherLowBitDepthTiles = { + "UnpremultiplyAndDitherLowBitDepthTiles", base::FEATURE_ENABLED_BY_DEFAULT}; + typedef std::map<std::string, ui::TextInputMode> TextInputModeMap; static const int kInvalidNextPreviousFlagsValue = -1; @@ -412,6 +435,8 @@ RenderWidget::RenderWidget( 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 + // RenderFrames rather than RenderWidgets. if (!swapped_out) RenderProcess::current()->AddRefProcess(); DCHECK(RenderThread::Get()); @@ -425,13 +450,21 @@ RenderWidget::RenderWidget( } #if defined(USE_AURA) RendererWindowTreeClient::CreateIfNecessary(routing_id_); - if (features::IsMashEnabled()) + if (!features::IsAshInBrowserProcess()) RendererWindowTreeClient::Get(routing_id_)->SetVisible(!is_hidden_); #endif + + if (routing_id_ != MSG_ROUTING_NONE) + g_routing_id_widget_map.Get().emplace(routing_id_, this); } RenderWidget::~RenderWidget() { DCHECK(!webwidget_internal_) << "Leaking our WebWidget!"; + // TODO(ajwong): Add in check that routing_id_ has been removed from + // g_routing_id_widget_map once the shutdown semantics for RenderWidget + // and RenderViewImpl are rationalized. Currently, too many unit and + // browser tests delete a RenderWidget without correclty going through + // the shutdown. https://crbug.com/545684 if (input_event_queue_) input_event_queue_->ClearClient(); @@ -457,6 +490,13 @@ void RenderWidget::InstallCreateHook( } // static +RenderWidget* RenderWidget::FromRoutingID(int32_t routing_id) { + RoutingIDWidgetMap* widgets = g_routing_id_widget_map.Pointer(); + RoutingIDWidgetMap::iterator it = widgets->find(routing_id); + return it == widgets->end() ? NULL : it->second; +} + +// static RenderWidget* RenderWidget::CreateForPopup( RenderViewImpl* opener, CompositorDependencies* compositor_deps, @@ -478,8 +518,8 @@ RenderWidget* RenderWidget::CreateForPopup( scoped_refptr<RenderWidget> widget(new RenderWidget( routing_id, compositor_deps, popup_type, screen_info, false, false, false, task_runner, std::move(widget_channel_request))); - ShowCallback opener_callback = - base::Bind(&RenderViewImpl::ShowCreatedPopupWidget, opener->GetWeakPtr()); + ShowCallback opener_callback = base::BindOnce( + &RenderViewImpl::ShowCreatedPopupWidget, opener->GetWeakPtr()); widget->Init(std::move(opener_callback), RenderWidget::CreateWebWidget(widget.get())); DCHECK(!widget->HasOneRef()); // RenderWidget::Init() adds a reference. @@ -494,13 +534,19 @@ RenderWidget* RenderWidget::CreateForFrame( CompositorDependencies* compositor_deps, blink::WebLocalFrame* frame) { CHECK_NE(widget_routing_id, MSG_ROUTING_NONE); - // TODO(avi): Before RenderViewImpl has-a RenderWidget, the browser passes the - // same routing ID for both the view routing ID and the main frame widget - // routing ID. https://crbug.com/545684 - RenderViewImpl* view = RenderViewImpl::FromRoutingID(widget_routing_id); - if (view) { + RenderFrameImpl* render_frame = RenderFrameImpl::FromWebFrame(frame); + // For the mainframe, the RenderWidget is attached to the RenderView. + // TODO(ajwong): Remove this when the widget is always attached to a frame. + // https://crbug.com/545684 + if (!frame->Parent()) { + RenderViewImpl* view = + static_cast<RenderViewImpl*>(render_frame->GetRenderView()); + // Use the WidgetClient() from the RenderViewImpl, rather than getting its + // RenderWidget directly. Layout tests may inject a different + // WebWidgetClient on the RenderViewImpl that intercepts calls before they + // get to the RenderWidget. view->AttachWebFrameWidget( - RenderWidget::CreateWebFrameWidget(view->GetWidget(), frame)); + RenderWidget::CreateWebFrameWidget(view->WidgetClient(), frame)); view->GetWidget()->UpdateWebViewWithDeviceScaleFactor(); return view->GetWidget(); } @@ -517,7 +563,7 @@ RenderWidget* RenderWidget::CreateForFrame( widget->for_oopif_ = true; // Init increments the reference count on |widget|, keeping it alive after // this function returns. - widget->Init(RenderWidget::ShowCallback(), + widget->Init(base::NullCallback(), RenderWidget::CreateWebFrameWidget(widget.get(), frame)); widget->UpdateWebViewWithDeviceScaleFactor(); @@ -528,9 +574,9 @@ RenderWidget* RenderWidget::CreateForFrame( // static blink::WebFrameWidget* RenderWidget::CreateWebFrameWidget( - RenderWidget* render_widget, + blink::WebWidgetClient* widget_client, blink::WebLocalFrame* frame) { - return blink::WebFrameWidget::Create(render_widget, frame); + return blink::WebFrameWidget::Create(widget_client, frame); } // static @@ -554,18 +600,9 @@ void RenderWidget::SetSwappedOut(bool is_swapped_out) { // We should only toggle between states. DCHECK(is_swapped_out_ != is_swapped_out); is_swapped_out_ = is_swapped_out; - - // If we are swapping out, we will call ReleaseProcess, allowing the process - // to exit if all of its RenderViews are swapped out. We wait until the - // WasSwappedOut call to do this, to allow the unload handler to finish. - // If we are swapping in, we call AddRefProcess to prevent the process from - // exiting. - if (!is_swapped_out_) - RenderProcess::current()->AddRefProcess(); } -void RenderWidget::Init(const ShowCallback& show_callback, - WebWidget* web_widget) { +void RenderWidget::Init(ShowCallback show_callback, WebWidget* web_widget) { DCHECK(!webwidget_internal_); DCHECK_NE(routing_id_, MSG_ROUTING_NONE); @@ -573,15 +610,18 @@ void RenderWidget::Init(const ShowCallback& show_callback, RenderThreadImpl* render_thread_impl = RenderThreadImpl::current(); + blink::scheduler::WebThreadScheduler* compositor_thread_scheduler = + blink::scheduler::WebThreadScheduler::CompositorThreadScheduler(); + widget_input_handler_manager_ = WidgetInputHandlerManager::Create( weak_ptr_factory_.GetWeakPtr(), - render_thread_impl && compositor_ - ? render_thread_impl->compositor_task_runner() + compositor_thread_scheduler && layer_tree_view_ + ? compositor_thread_scheduler->InputTaskRunner() : nullptr, render_thread_impl ? render_thread_impl->GetWebMainThreadScheduler() : nullptr); - show_callback_ = show_callback; + show_callback_ = std::move(show_callback); webwidget_internal_ = web_widget; webwidget_mouse_lock_target_.reset( @@ -599,13 +639,6 @@ void RenderWidget::Init(const ShowCallback& show_callback, } } -void RenderWidget::WasSwappedOut() { - // If we have been swapped out and no one else is using this process, - // it's safe to exit now. - CHECK(is_swapped_out_); - RenderProcess::current()->ReleaseProcess(); -} - void RenderWidget::SetPopupOriginAdjustmentsForEmulation( RenderWidgetScreenMetricsEmulator* emulator) { popup_origin_scale_for_emulation_ = emulator->scale(); @@ -657,9 +690,12 @@ bool RenderWidget::OnMessageReceived(const IPC::Message& message) { OnDisableDeviceEmulation) IPC_MESSAGE_HANDLER(ViewMsg_WasHidden, OnWasHidden) IPC_MESSAGE_HANDLER(ViewMsg_WasShown, OnWasShown) + IPC_MESSAGE_HANDLER(ViewMsg_SetActive, OnSetActive) + IPC_MESSAGE_HANDLER(ViewMsg_SetBackgroundOpaque, OnSetBackgroundOpaque) IPC_MESSAGE_HANDLER(ViewMsg_SetTextDirection, OnSetTextDirection) - IPC_MESSAGE_HANDLER(ViewMsg_Move_ACK, OnRequestMoveAck) + IPC_MESSAGE_HANDLER(ViewMsg_SetBounds_ACK, OnRequestSetBoundsAck) IPC_MESSAGE_HANDLER(ViewMsg_UpdateScreenRects, OnUpdateScreenRects) + IPC_MESSAGE_HANDLER(ViewMsg_ForceRedraw, OnForceRedraw) IPC_MESSAGE_HANDLER(ViewMsg_SetViewportIntersection, OnSetViewportIntersection) IPC_MESSAGE_HANDLER(ViewMsg_SetIsInert, OnSetIsInert) @@ -726,8 +762,8 @@ void RenderWidget::SetWindowRectSynchronously( 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 (compositor_) - compositor_->RequestNewLocalSurfaceId(); + if (layer_tree_view_) + layer_tree_view_->RequestNewLocalSurfaceId(); SynchronizeVisualProperties(visual_properties); view_screen_rect_ = new_window_rect; @@ -746,6 +782,7 @@ void RenderWidget::OnClose() { // Browser correspondence is no longer needed at this point. if (routing_id_ != MSG_ROUTING_NONE) { RenderThread::Get()->RemoveRoute(routing_id_); + g_routing_id_widget_map.Get().erase(routing_id_); SetHidden(false); if (RenderThreadImpl::current()) RenderThreadImpl::current()->WidgetDestroyed(); @@ -825,7 +862,7 @@ void RenderWidget::OnWasHidden() { } void RenderWidget::OnWasShown(bool needs_repainting, - const ui::LatencyInfo& latency_info) { + base::TimeTicks show_request_timestamp) { TRACE_EVENT0("renderer", "RenderWidget::OnWasShown"); // During shutdown we can just ignore this message. if (!GetWebWidget()) @@ -840,20 +877,32 @@ void RenderWidget::OnWasShown(bool needs_repainting, if (!needs_repainting) return; - if (compositor_) { - ui::LatencyInfo swap_latency_info(latency_info); - std::unique_ptr<cc::SwapPromiseMonitor> latency_info_swap_promise_monitor = - compositor_->CreateLatencyInfoSwapPromiseMonitor(&swap_latency_info); - // Force this SwapPromiseMonitor to trigger and insert a SwapPromise. - compositor_->SetNeedsBeginFrame(); + if (layer_tree_view_ && !show_request_timestamp.is_null()) { + layer_tree_view_->layer_tree_host()->RequestPresentationTimeForNextFrame( + CreateTabSwitchingTimeRecorder(show_request_timestamp)); } } -void RenderWidget::OnRequestMoveAck() { +void RenderWidget::OnRequestSetBoundsAck() { DCHECK(pending_window_rect_count_); pending_window_rect_count_--; } +void RenderWidget::OnForceRedraw(int snapshot_id) { + if (LayerTreeView* ltv = layer_tree_view()) { + ltv->layer_tree_host()->RequestPresentationTimeForNextFrame( + base::BindOnce(&RenderWidget::DidPresentForceDrawFrame, + weak_ptr_factory_.GetWeakPtr(), snapshot_id)); + ltv->SetNeedsForcedRedraw(); + } +} + +void RenderWidget::DidPresentForceDrawFrame( + int snapshot_id, + const gfx::PresentationFeedback& feedback) { + Send(new ViewHostMsg_ForceRedrawComplete(routing_id(), snapshot_id)); +} + GURL RenderWidget::GetURLForGraphicsContext3D() { return GURL(); } @@ -889,6 +938,16 @@ void RenderWidget::OnSetEditCommandsForNextKeyEvent( edit_commands_ = edit_commands; } +void RenderWidget::OnSetActive(bool active) { + if (owner_delegate_) + owner_delegate_->SetActive(active); +} + +void RenderWidget::OnSetBackgroundOpaque(bool opaque) { + if (owner_delegate_) + owner_delegate_->SetBackgroundOpaque(opaque); +} + void RenderWidget::OnSetFocus(bool enable) { has_focus_ = enable; @@ -900,14 +959,14 @@ void RenderWidget::OnSetFocus(bool enable) { } void RenderWidget::SetNeedsMainFrame() { - RenderWidgetCompositor* rwc = compositor(); - if (!rwc) + LayerTreeView* ltv = layer_tree_view(); + if (!ltv) return; - rwc->SetNeedsBeginFrame(); + ltv->SetNeedsBeginFrame(); } /////////////////////////////////////////////////////////////////////////////// -// RenderWidgetCompositorDelegate +// LayerTreeViewDelegate void RenderWidget::ApplyViewportDeltas( const gfx::Vector2dF& inner_delta, @@ -941,7 +1000,7 @@ void RenderWidget::BeginMainFrame(base::TimeTicks frame_time) { } void RenderWidget::RequestNewLayerTreeFrameSink( - const LayerTreeFrameSinkCallback& callback) { + LayerTreeFrameSinkCallback callback) { DCHECK(GetWebWidget()); // For widgets that are never visible, we don't start the compositor, so we // never get a request for a cc::LayerTreeFrameSink. @@ -954,11 +1013,14 @@ void RenderWidget::RequestNewLayerTreeFrameSink( mojom::RenderFrameMetadataObserverClientPtrInfo client_info; mojom::RenderFrameMetadataObserverClientRequest client_request = mojo::MakeRequest(&client_info); - compositor_->CreateRenderFrameObserver(std::move(request), - std::move(client_info)); + auto render_frame_metadata_observer = + std::make_unique<RenderFrameMetadataObserverImpl>(std::move(request), + std::move(client_info)); + layer_tree_view_->SetRenderFrameObserver( + std::move(render_frame_metadata_observer)); RenderThreadImpl::current()->RequestNewLayerTreeFrameSink( routing_id_, frame_swap_message_queue_, GetURLForGraphicsContext3D(), - callback, std::move(client_request), std::move(ptr)); + std::move(callback), std::move(client_request), std::move(ptr)); } void RenderWidget::DidCommitAndDrawCompositorFrame() { @@ -982,7 +1044,22 @@ void RenderWidget::DidReceiveCompositorFrameAck() { } bool RenderWidget::IsClosing() const { - return host_closing_; + // TODO(ajwong): There is oddly 2 closing states. This API is used by + // LayerTreeView only as part of the LayerTreeViewDelegate interface and + // is the guard against creating new compositor frames unnecessarily. + // Historically, when RenderViewImpl and RenderWidget shared the same + // routing id, it was possible for |closing_| to be true, |host_closing_| to + // false, and for the code in + // RenderThreadImpl::RequestNewLayerTreeFrameSink() to still look up a valid + // RenderViewImpl from the routing id. This is actually a benign shutdown + // race in Android that can be triggered in the SynchronouslyComposite path + // via AwContentsGarbageCollectionTest#testCreateAndGcManyTimes. + // + // Once RenderViewImpl and RenderWidget are split, attempt to combine two + // states so the shutdown logic is cleaner. + // + // http://crbug.com/545684 + return host_closing_ || closing_; } void RenderWidget::RequestScheduleAnimation() { @@ -1228,8 +1305,8 @@ bool RenderWidget::WillHandleMouseEvent(const blink::WebMouseEvent& event) { // RenderWidgetScreenMetricsDelegate void RenderWidget::Redraw() { - if (compositor_) - compositor_->SetNeedsRedrawRect(gfx::Rect(size_)); + if (layer_tree_view_) + layer_tree_view_->SetNeedsRedrawRect(gfx::Rect(size_)); } void RenderWidget::ResizeWebWidget() { @@ -1237,7 +1314,7 @@ void RenderWidget::ResizeWebWidget() { } gfx::Size RenderWidget::GetSizeForWebWidget() const { - if (IsUseZoomForDSFEnabled()) { + if (compositor_deps_->IsUseZoomForDSFEnabled()) { return gfx::ScaleToCeiledSize(size_, GetOriginalScreenInfo().device_scale_factor); } @@ -1245,6 +1322,27 @@ gfx::Size RenderWidget::GetSizeForWebWidget() const { return size_; } +void RenderWidget::UpdateZoom(double zoom_level) { + blink::WebFrameWidget* frame_widget = GetFrameWidget(); + if (!frame_widget) + return; + RenderFrameImpl* render_frame = + RenderFrameImpl::FromWebFrame(frame_widget->LocalRoot()); + + // Return early if zoom level is unchanged. + if (render_frame->GetZoomLevel() == zoom_level) { + return; + } + + render_frame->SetZoomLevel(zoom_level); + + for (auto& observer : render_frame_proxies_) + observer.OnZoomLevelChanged(zoom_level); + + for (auto& plugin : browser_plugins_) + plugin.OnZoomLevelChanged(zoom_level); +} + void RenderWidget::SynchronizeVisualProperties(const VisualProperties& params) { // Inform the rendering thread of the color space indicate the presence of HDR // capabilities. @@ -1265,14 +1363,16 @@ void RenderWidget::SynchronizeVisualProperties(const VisualProperties& params) { params.local_surface_id.value_or(viz::LocalSurfaceId()), new_compositor_viewport_pixel_size, params.screen_info); UpdateCaptureSequenceNumber(params.capture_sequence_number); - if (compositor_) { - compositor_->SetBrowserControlsHeight( + if (layer_tree_view_) { + layer_tree_view_->SetBrowserControlsHeight( params.top_controls_height, params.bottom_controls_height, params.browser_controls_shrink_blink_size); - compositor_->SetRasterColorSpace( + layer_tree_view_->SetRasterColorSpace( screen_info_.color_space.GetRasterColorSpace()); } + UpdateZoom(params.zoom_level); + if (params.auto_resize_enabled) return; @@ -1289,7 +1389,7 @@ void RenderWidget::SynchronizeVisualProperties(const VisualProperties& params) { ResizeWebWidget(); WebSize visual_viewport_size; - if (IsUseZoomForDSFEnabled()) { + if (compositor_deps_->IsUseZoomForDSFEnabled()) { visual_viewport_size = gfx::ScaleToCeiledSize(params.visible_viewport_size, GetOriginalScreenInfo().device_scale_factor); @@ -1321,32 +1421,32 @@ void RenderWidget::SetScreenRects(const gfx::Rect& view_screen_rect, blink::WebLayerTreeView* RenderWidget::InitializeLayerTreeView() { DCHECK(!host_closing_); - compositor_ = RenderWidgetCompositor::Create(this, compositor_deps_); - auto animation_host = cc::AnimationHost::CreateMainInstance(); - - // Oopif status must be set before the LayerTreeHost is created. - compositor_->SetIsForOopif(for_oopif_); - auto layer_tree_host = RenderWidgetCompositor::CreateLayerTreeHost( - compositor_.get(), compositor_.get(), animation_host.get(), - compositor_deps_, screen_info_); - compositor_->Initialize(std::move(layer_tree_host), - std::move(animation_host)); + layer_tree_view_ = std::make_unique<LayerTreeView>( + this, compositor_deps_->GetCompositorMainThreadTaskRunner(), + compositor_deps_->GetCompositorImplThreadTaskRunner(), + compositor_deps_->GetTaskGraphRunner(), + compositor_deps_->GetWebMainThreadScheduler()); + layer_tree_view_->Initialize( + GenerateLayerTreeSettings(compositor_deps_, for_oopif_, + screen_info_.rect.size(), + screen_info_.device_scale_factor), + compositor_deps_->CreateUkmRecorderFactory()); UpdateSurfaceAndScreenInfo(local_surface_id_from_parent_, compositor_viewport_pixel_size_, screen_info_); - compositor_->SetRasterColorSpace( + layer_tree_view_->SetRasterColorSpace( screen_info_.color_space.GetRasterColorSpace()); - compositor_->SetContentSourceId(current_content_source_id_); + layer_tree_view_->SetContentSourceId(current_content_source_id_); // For background pages and certain tests, we don't want to trigger // LayerTreeFrameSink creation. bool should_generate_frame_sink = !compositor_never_visible_ && RenderThreadImpl::current(); if (!should_generate_frame_sink) - compositor_->SetNeverVisible(); + layer_tree_view_->SetNeverVisible(); StartCompositor(); DCHECK_NE(MSG_ROUTING_NONE, routing_id_); - compositor_->SetFrameSinkId( + layer_tree_view_->SetFrameSinkId( viz::FrameSinkId(RenderThread::Get()->GetClientId(), routing_id_)); RenderThreadImpl* render_thread = RenderThreadImpl::current(); @@ -1358,7 +1458,7 @@ blink::WebLayerTreeView* RenderWidget::InitializeLayerTreeView() { UpdateURLForCompositorUkm(); - return compositor_.get(); + return layer_tree_view_.get(); } void RenderWidget::IntrinsicSizingInfoChanged( @@ -1411,7 +1511,7 @@ std::unique_ptr<cc::SwapPromise> RenderWidget::QueueMessageImpl( void RenderWidget::QueueMessage(IPC::Message* msg, MessageDeliveryPolicy policy) { // RenderThreadImpl::current() is NULL in some tests. - if (!compositor_ || !RenderThreadImpl::current()) { + if (!layer_tree_view_ || !RenderThreadImpl::current()) { Send(msg); return; } @@ -1419,10 +1519,10 @@ void RenderWidget::QueueMessage(IPC::Message* msg, std::unique_ptr<cc::SwapPromise> swap_promise = QueueMessageImpl(msg, policy, frame_swap_message_queue_.get(), RenderThreadImpl::current()->sync_message_filter(), - compositor_->GetSourceFrameNumber()); + layer_tree_view_->GetSourceFrameNumber()); if (swap_promise) - compositor_->QueueSwapPromise(std::move(swap_promise)); + layer_tree_view_->QueueSwapPromise(std::move(swap_promise)); } void RenderWidget::DidChangeCursor(const WebCursorInfo& cursor_info) { @@ -1458,7 +1558,7 @@ void RenderWidget::AutoscrollEnd() { void RenderWidget::Show(WebNavigationPolicy policy) { DCHECK(!did_show_) << "received extraneous Show call"; DCHECK(routing_id_ != MSG_ROUTING_NONE); - DCHECK(!show_callback_.is_null()); + DCHECK(show_callback_); if (did_show_) return; @@ -1466,8 +1566,7 @@ void RenderWidget::Show(WebNavigationPolicy policy) { did_show_ = true; // The opener is responsible for actually showing this widget. - show_callback_.Run(this, policy, initial_rect_); - show_callback_.Reset(); + std::move(show_callback_).Run(this, policy, initial_rect_); // NOTE: initial_rect_ may still have its default values at this point, but // that's okay. It'll be ignored if as_popup is false, or the browser @@ -1510,7 +1609,7 @@ void RenderWidget::CloseWidgetSoon() { void RenderWidget::Close() { screen_metrics_emulator_.reset(); CloseWebWidget(); - compositor_.reset(); + layer_tree_view_.reset(); } void RenderWidget::CloseWebWidget() { @@ -1527,7 +1626,7 @@ void RenderWidget::UpdateWebViewWithDeviceScaleFactor() { frame_widget ? frame_widget->LocalRoot() : nullptr; blink::WebView* webview = current_frame ? current_frame->View() : nullptr; if (webview) { - if (IsUseZoomForDSFEnabled()) + if (compositor_deps_->IsUseZoomForDSFEnabled()) webview->SetZoomFactorForDeviceScaleFactor( GetWebScreenInfo().device_scale_factor); else @@ -1617,7 +1716,7 @@ void RenderWidget::SetWindowRect(const WebRect& rect_in_screen) { if (!resizing_mode_selector_->is_synchronous_mode()) { if (did_show_) { - Send(new ViewHostMsg_RequestMove(routing_id_, window_rect)); + Send(new ViewHostMsg_RequestSetBounds(routing_id_, window_rect)); SetPendingWindowRect(window_rect); } else { initial_rect_ = window_rect; @@ -1754,11 +1853,11 @@ void RenderWidget::UpdateSurfaceAndScreenInfo( compositor_viewport_pixel_size_ = new_compositor_viewport_pixel_size; screen_info_ = new_screen_info; - if (compositor_) { - compositor_->SetViewportVisibleRect(ViewportVisibleRect()); + if (layer_tree_view_) { + layer_tree_view_->SetViewportVisibleRect(ViewportVisibleRect()); // Note carefully that the DSF specified in |new_screen_info| is not the // DSF used by the compositor during device emulation! - compositor_->SetViewportSizeAndScale( + layer_tree_view_->SetViewportSizeAndScale( compositor_viewport_pixel_size_, GetOriginalScreenInfo().device_scale_factor, local_surface_id_from_parent_); @@ -1824,7 +1923,7 @@ void RenderWidget::OnSetViewportIntersection( DCHECK_EQ(popup_type_, WebPopupType::kWebPopupTypeNone); compositor_visible_rect_ = compositor_visible_rect; frame_widget->SetRemoteViewportIntersection(viewport_intersection); - compositor_->SetViewportVisibleRect(ViewportVisibleRect()); + layer_tree_view_->SetViewportVisibleRect(ViewportVisibleRect()); } } @@ -1983,7 +2082,7 @@ void RenderWidget::UpdateCompositionInfo(bool immediate_request) { } void RenderWidget::ConvertViewportToWindow(blink::WebRect* rect) { - if (IsUseZoomForDSFEnabled()) { + if (compositor_deps_->IsUseZoomForDSFEnabled()) { float reverse = 1 / GetOriginalScreenInfo().device_scale_factor; // TODO(oshima): We may need to allow pixel precision here as the the // anchor element can be placed at half pixel. @@ -1997,7 +2096,7 @@ void RenderWidget::ConvertViewportToWindow(blink::WebRect* rect) { } void RenderWidget::ConvertWindowToViewport(blink::WebFloatRect* rect) { - if (IsUseZoomForDSFEnabled()) { + if (compositor_deps_->IsUseZoomForDSFEnabled()) { rect->x *= GetOriginalScreenInfo().device_scale_factor; rect->y *= GetOriginalScreenInfo().device_scale_factor; rect->width *= GetOriginalScreenInfo().device_scale_factor; @@ -2043,7 +2142,7 @@ void RenderWidget::SetHidden(bool hidden) { is_hidden_ = hidden; #if defined(USE_AURA) - if (features::IsMashEnabled()) + if (!features::IsAshInBrowserProcess()) RendererWindowTreeClient::Get(routing_id_)->SetVisible(!hidden); #endif @@ -2177,8 +2276,8 @@ void RenderWidget::DidAutoResize(const gfx::Size& new_size) { // |size_| from |compositor_viewport_pixel_size_|. Also note that the // calculation of |new_compositor_viewport_pixel_size| does not appear to // take into account device emulation. - if (compositor_) - compositor_->RequestNewLocalSurfaceId(); + if (layer_tree_view_) + layer_tree_view_->RequestNewLocalSurfaceId(); gfx::Size new_compositor_viewport_pixel_size = gfx::ScaleToCeiledSize(size_, GetWebScreenInfo().device_scale_factor); UpdateSurfaceAndScreenInfo(local_surface_id_from_parent_, @@ -2334,13 +2433,434 @@ void RenderWidget::DidOverscroll( position, velocity, behavior); } -void RenderWidget::StartCompositor() { - if (!is_hidden()) - compositor_->SetVisible(true); +// static +cc::LayerTreeSettings RenderWidget::GenerateLayerTreeSettings( + CompositorDependencies* compositor_deps, + bool is_for_subframe, + const gfx::Size& initial_screen_size, + float initial_device_scale_factor) { + const bool is_threaded = + !!compositor_deps->GetCompositorImplThreadTaskRunner(); + + const base::CommandLine& cmd = *base::CommandLine::ForCurrentProcess(); + cc::LayerTreeSettings settings; + + settings.resource_settings.use_r16_texture = + base::FeatureList::IsEnabled(media::kUseR16Texture); + + settings.commit_to_active_tree = !is_threaded; + settings.is_layer_tree_for_subframe = is_for_subframe; + + // For web contents, layer transforms should scale up the contents of layers + // to keep content always crisp when possible. + settings.layer_transforms_should_scale_layer_contents = true; + + settings.main_frame_before_activation_enabled = + cmd.HasSwitch(cc::switches::kEnableMainFrameBeforeActivation); + + // Checkerimaging is not supported for synchronous single-threaded mode, which + // is what the renderer uses if its not threaded. + settings.enable_checker_imaging = + !cmd.HasSwitch(cc::switches::kDisableCheckerImaging) && is_threaded; + +#if defined(OS_ANDROID) + // We can use a more aggressive limit on Android since decodes tend to take + // longer on these devices. + settings.min_image_bytes_to_checker = 512 * 1024; // 512kB + + // Re-rasterization of checker-imaged content with software raster can be too + // costly on Android. + settings.only_checker_images_with_gpu_raster = true; +#endif + + auto switch_value_as_int = [](const base::CommandLine& command_line, + const std::string& switch_string, int min_value, + int max_value, int* result) { + std::string string_value = command_line.GetSwitchValueASCII(switch_string); + int int_value; + if (base::StringToInt(string_value, &int_value) && int_value >= min_value && + int_value <= max_value) { + *result = int_value; + return true; + } else { + LOG(WARNING) << "Failed to parse switch " << switch_string << ": " + << string_value; + return false; + } + }; + + int default_tile_size = 256; +#if defined(OS_ANDROID) + const gfx::Size screen_size = + gfx::ScaleToFlooredSize(initial_screen_size, initial_device_scale_factor); + int display_width = screen_size.width(); + int display_height = screen_size.height(); + int numTiles = (display_width * display_height) / (256 * 256); + if (numTiles > 16) + default_tile_size = 384; + if (numTiles >= 40) + default_tile_size = 512; + + // Adjust for some resolutions that barely straddle an extra + // tile when in portrait mode. This helps worst case scroll/raster + // by not needing a full extra tile for each row. + constexpr int tolerance = 10; // To avoid rounding errors. + int portrait_width = std::min(display_width, display_height); + if (default_tile_size == 256 && std::abs(portrait_width - 768) < tolerance) + default_tile_size += 32; + if (default_tile_size == 384 && std::abs(portrait_width - 1200) < tolerance) + default_tile_size += 32; +#elif defined(OS_CHROMEOS) || defined(OS_MACOSX) + // Use 512 for high DPI (dsf=2.0f) devices. + if (initial_device_scale_factor >= 2.0f) + default_tile_size = 512; +#endif + + // TODO(danakj): This should not be a setting O_O; it should change when the + // device scale factor on LayerTreeHost changes. + settings.default_tile_size = gfx::Size(default_tile_size, default_tile_size); + if (cmd.HasSwitch(switches::kDefaultTileWidth)) { + int tile_width = 0; + switch_value_as_int(cmd, switches::kDefaultTileWidth, 1, + std::numeric_limits<int>::max(), &tile_width); + settings.default_tile_size.set_width(tile_width); + } + if (cmd.HasSwitch(switches::kDefaultTileHeight)) { + int tile_height = 0; + switch_value_as_int(cmd, switches::kDefaultTileHeight, 1, + std::numeric_limits<int>::max(), &tile_height); + settings.default_tile_size.set_height(tile_height); + } + + int max_untiled_layer_width = settings.max_untiled_layer_size.width(); + if (cmd.HasSwitch(switches::kMaxUntiledLayerWidth)) { + switch_value_as_int(cmd, switches::kMaxUntiledLayerWidth, 1, + std::numeric_limits<int>::max(), + &max_untiled_layer_width); + } + int max_untiled_layer_height = settings.max_untiled_layer_size.height(); + if (cmd.HasSwitch(switches::kMaxUntiledLayerHeight)) { + switch_value_as_int(cmd, switches::kMaxUntiledLayerHeight, 1, + std::numeric_limits<int>::max(), + &max_untiled_layer_height); + } + + settings.max_untiled_layer_size = + gfx::Size(max_untiled_layer_width, max_untiled_layer_height); + + settings.gpu_rasterization_msaa_sample_count = + compositor_deps->GetGpuRasterizationMSAASampleCount(); + settings.gpu_rasterization_forced = + compositor_deps->IsGpuRasterizationForced(); + + settings.can_use_lcd_text = compositor_deps->IsLcdTextEnabled(); + settings.use_zero_copy = compositor_deps->IsZeroCopyEnabled(); + settings.use_partial_raster = compositor_deps->IsPartialRasterEnabled(); + settings.enable_elastic_overscroll = + compositor_deps->IsElasticOverscrollEnabled(); + settings.resource_settings.use_gpu_memory_buffer_resources = + compositor_deps->IsGpuMemoryBufferCompositorResourcesEnabled(); + settings.use_painted_device_scale_factor = + compositor_deps->IsUseZoomForDSFEnabled(); + + // Build LayerTreeSettings from command line args. + if (cmd.HasSwitch(cc::switches::kBrowserControlsShowThreshold)) { + std::string top_threshold_str = + cmd.GetSwitchValueASCII(cc::switches::kBrowserControlsShowThreshold); + double show_threshold; + if (base::StringToDouble(top_threshold_str, &show_threshold) && + show_threshold >= 0.f && show_threshold <= 1.f) + settings.top_controls_show_threshold = show_threshold; + } + + if (cmd.HasSwitch(cc::switches::kBrowserControlsHideThreshold)) { + std::string top_threshold_str = + cmd.GetSwitchValueASCII(cc::switches::kBrowserControlsHideThreshold); + double hide_threshold; + if (base::StringToDouble(top_threshold_str, &hide_threshold) && + hide_threshold >= 0.f && hide_threshold <= 1.f) + settings.top_controls_hide_threshold = hide_threshold; + } + + settings.use_layer_lists = cmd.HasSwitch(cc::switches::kEnableLayerLists); + + // The means the renderer compositor has 2 possible modes: + // - Threaded compositing with a scheduler. + // - Single threaded compositing without a scheduler (for layout tests only). + // Using the scheduler in layout tests introduces additional composite steps + // that create flakiness. + settings.single_thread_proxy_scheduler = false; + + // These flags should be mirrored by UI versions in ui/compositor/. + if (cmd.HasSwitch(cc::switches::kShowCompositedLayerBorders)) + settings.initial_debug_state.show_debug_borders.set(); + settings.initial_debug_state.show_layer_animation_bounds_rects = + cmd.HasSwitch(cc::switches::kShowLayerAnimationBounds); + settings.initial_debug_state.show_paint_rects = + cmd.HasSwitch(switches::kShowPaintRects); + settings.initial_debug_state.show_property_changed_rects = + cmd.HasSwitch(cc::switches::kShowPropertyChangedRects); + settings.initial_debug_state.show_surface_damage_rects = + cmd.HasSwitch(cc::switches::kShowSurfaceDamageRects); + settings.initial_debug_state.show_screen_space_rects = + cmd.HasSwitch(cc::switches::kShowScreenSpaceRects); + + settings.initial_debug_state.SetRecordRenderingStats( + cmd.HasSwitch(cc::switches::kEnableGpuBenchmarking)); + settings.enable_surface_synchronization = + features::IsSurfaceSynchronizationEnabled(); + settings.build_hit_test_data = features::IsVizHitTestingSurfaceLayerEnabled(); + + if (cmd.HasSwitch(cc::switches::kSlowDownRasterScaleFactor)) { + const int kMinSlowDownScaleFactor = 0; + const int kMaxSlowDownScaleFactor = INT_MAX; + switch_value_as_int( + cmd, cc::switches::kSlowDownRasterScaleFactor, kMinSlowDownScaleFactor, + kMaxSlowDownScaleFactor, + &settings.initial_debug_state.slow_down_raster_scale_factor); + } + + // This is default overlay scrollbar settings for Android and DevTools mobile + // emulator. Aura Overlay Scrollbar will override below. + settings.scrollbar_animator = cc::LayerTreeSettings::ANDROID_OVERLAY; + settings.solid_color_scrollbar_color = SkColorSetARGB(128, 128, 128, 128); + settings.scrollbar_fade_delay = base::TimeDelta::FromMilliseconds(300); + settings.scrollbar_fade_duration = base::TimeDelta::FromMilliseconds(300); + +#if defined(OS_ANDROID) + bool using_synchronous_compositor = + compositor_deps->UsingSynchronousCompositing(); + bool using_low_memory_policy = base::SysInfo::IsLowEndDevice(); + + settings.use_stream_video_draw_quad = true; + settings.using_synchronous_renderer_compositor = using_synchronous_compositor; + if (using_synchronous_compositor) { + // Android WebView uses system scrollbars, so make ours invisible. + // http://crbug.com/677348: This can't be done using hide_scrollbars + // setting because supporting -webkit custom scrollbars is still desired + // on sublayers. + settings.scrollbar_animator = cc::LayerTreeSettings::NO_ANIMATOR; + settings.solid_color_scrollbar_color = SK_ColorTRANSPARENT; + + settings.enable_early_damage_check = + cmd.HasSwitch(cc::switches::kCheckDamageEarly); + } + // Android WebView handles root layer flings itself. + settings.ignore_root_layer_flings = using_synchronous_compositor; + // Memory policy on Android WebView does not depend on whether device is + // low end, so always use default policy. + if (using_low_memory_policy && !using_synchronous_compositor) { + // On low-end we want to be very carefull about killing other + // apps. So initially we use 50% more memory to avoid flickering + // or raster-on-demand. + settings.max_memory_for_prepaint_percentage = 67; + } else { + // On other devices we have increased memory excessively to avoid + // raster-on-demand already, so now we reserve 50% _only_ to avoid + // raster-on-demand, and use 50% of the memory otherwise. + settings.max_memory_for_prepaint_percentage = 50; + } + + // TODO(danakj): Only do this on low end devices. + settings.create_low_res_tiling = true; + +#else // defined(OS_ANDROID) + bool using_synchronous_compositor = false; // Only for Android WebView. + // On desktop, we never use the low memory policy unless we are simulating + // low-end mode via a switch. + bool using_low_memory_policy = + cmd.HasSwitch(switches::kEnableLowEndDeviceMode); + + if (ui::IsOverlayScrollbarEnabled()) { + settings.scrollbar_animator = cc::LayerTreeSettings::AURA_OVERLAY; + settings.scrollbar_fade_delay = ui::kOverlayScrollbarFadeDelay; + settings.scrollbar_fade_duration = ui::kOverlayScrollbarFadeDuration; + settings.scrollbar_thinning_duration = + ui::kOverlayScrollbarThinningDuration; + settings.scrollbar_flash_after_any_scroll_update = + ui::OverlayScrollbarFlashAfterAnyScrollUpdate(); + settings.scrollbar_flash_when_mouse_enter = + ui::OverlayScrollbarFlashWhenMouseEnter(); + } + + // On desktop, if there's over 4GB of memory on the machine, increase the + // working set size to 256MB for both gpu and software. + const int kImageDecodeMemoryThresholdMB = 4 * 1024; + if (base::SysInfo::AmountOfPhysicalMemoryMB() >= + kImageDecodeMemoryThresholdMB) { + settings.decoded_image_working_set_budget_bytes = 256 * 1024 * 1024; + } else { + // This is the default, but recorded here as well. + settings.decoded_image_working_set_budget_bytes = 128 * 1024 * 1024; + } +#endif // defined(OS_ANDROID) + + if (using_low_memory_policy) { + // RGBA_4444 textures are only enabled: + // - If the user hasn't explicitly disabled them + // - If system ram is <= 512MB (1GB devices are sometimes low-end). + // - If we are not running in a WebView, where 4444 isn't supported. + if (!cmd.HasSwitch(switches::kDisableRGBA4444Textures) && + base::SysInfo::AmountOfPhysicalMemoryMB() <= 512 && + !using_synchronous_compositor) { + settings.use_rgba_4444 = viz::RGBA_4444; + + // If we are going to unpremultiply and dither these tiles, we need to + // allocate an additional RGBA_8888 intermediate for each tile + // rasterization when rastering to RGBA_4444 to allow for dithering. + // Setting a reasonable sized max tile size allows this intermediate to + // be consistently reused. + if (base::FeatureList::IsEnabled( + kUnpremultiplyAndDitherLowBitDepthTiles)) { + settings.max_gpu_raster_tile_size = gfx::Size(512, 256); + settings.unpremultiply_and_dither_low_bit_depth_tiles = true; + } + } + } + + if (cmd.HasSwitch(switches::kEnableLowResTiling)) + settings.create_low_res_tiling = true; + if (cmd.HasSwitch(switches::kDisableLowResTiling)) + settings.create_low_res_tiling = false; + + if (cmd.HasSwitch(switches::kEnableRGBA4444Textures) && + !cmd.HasSwitch(switches::kDisableRGBA4444Textures)) { + settings.use_rgba_4444 = true; + } + + settings.max_staging_buffer_usage_in_bytes = 32 * 1024 * 1024; // 32MB + // Use 1/4th of staging buffers on low-end devices. + if (base::SysInfo::IsLowEndDevice()) + settings.max_staging_buffer_usage_in_bytes /= 4; + + cc::ManagedMemoryPolicy defaults = settings.memory_policy; + settings.memory_policy = GetGpuMemoryPolicy(defaults, initial_screen_size, + initial_device_scale_factor); + + settings.disallow_non_exact_resource_reuse = + cmd.HasSwitch(switches::kDisallowNonExactResourceReuse); +#if defined(OS_ANDROID) + // TODO(crbug.com/746931): This feature appears to be causing visual + // corruption on certain android devices. Will investigate and re-enable. + settings.disallow_non_exact_resource_reuse = true; +#endif + + if (cmd.HasSwitch(switches::kRunAllCompositorStagesBeforeDraw)) { + settings.wait_for_all_pipeline_stages_before_draw = true; + settings.enable_latency_recovery = false; + } + + settings.enable_image_animation_resync = + !cmd.HasSwitch(switches::kDisableImageAnimationResync); + + settings.always_request_presentation_time = + cmd.HasSwitch(cc::switches::kAlwaysRequestPresentationTime); + return settings; +} + +// static +cc::ManagedMemoryPolicy RenderWidget::GetGpuMemoryPolicy( + const cc::ManagedMemoryPolicy& default_policy, + const gfx::Size& initial_screen_size, + float initial_device_scale_factor) { + cc::ManagedMemoryPolicy actual = default_policy; + actual.bytes_limit_when_visible = 0; + + // If the value was overridden on the command line, use the specified value. + static bool client_hard_limit_bytes_overridden = + base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kForceGpuMemAvailableMb); + if (client_hard_limit_bytes_overridden) { + if (base::StringToSizeT( + base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + switches::kForceGpuMemAvailableMb), + &actual.bytes_limit_when_visible)) + actual.bytes_limit_when_visible *= 1024 * 1024; + return actual; + } + +#if defined(OS_ANDROID) + // We can't query available GPU memory from the system on Android. + // Physical memory is also mis-reported sometimes (eg. Nexus 10 reports + // 1262MB when it actually has 2GB, while Razr M has 1GB but only reports + // 128MB java heap size). First we estimate physical memory using both. + size_t dalvik_mb = base::SysInfo::DalvikHeapSizeMB(); + size_t physical_mb = base::SysInfo::AmountOfPhysicalMemoryMB(); + size_t physical_memory_mb = 0; + if (base::SysInfo::IsLowEndDevice()) { + // TODO(crbug.com/742534): The code below appears to no longer work. + // |dalvik_mb| no longer follows the expected heuristic pattern, causing us + // to over-estimate memory on low-end devices. This entire section probably + // needs to be re-written, but for now we can address the low-end Android + // issues by ignoring |dalvik_mb|. + physical_memory_mb = physical_mb; + } else if (dalvik_mb >= 256) { + physical_memory_mb = dalvik_mb * 4; + } else { + physical_memory_mb = std::max(dalvik_mb * 4, (physical_mb * 4) / 3); + } + + // Now we take a default of 1/8th of memory on high-memory devices, + // and gradually scale that back for low-memory devices (to be nicer + // to other apps so they don't get killed). Examples: + // Nexus 4/10(2GB) 256MB (normally 128MB) + // Droid Razr M(1GB) 114MB (normally 57MB) + // Galaxy Nexus(1GB) 100MB (normally 50MB) + // Xoom(1GB) 100MB (normally 50MB) + // Nexus S(low-end) 8MB (normally 8MB) + // Note that the compositor now uses only some of this memory for + // pre-painting and uses the rest only for 'emergencies'. + if (actual.bytes_limit_when_visible == 0) { + // NOTE: Non-low-end devices use only 50% of these limits, + // except during 'emergencies' where 100% can be used. + if (physical_memory_mb >= 1536) + actual.bytes_limit_when_visible = physical_memory_mb / 8; // >192MB + else if (physical_memory_mb >= 1152) + actual.bytes_limit_when_visible = physical_memory_mb / 8; // >144MB + else if (physical_memory_mb >= 768) + actual.bytes_limit_when_visible = physical_memory_mb / 10; // >76MB + else if (physical_memory_mb >= 513) + actual.bytes_limit_when_visible = physical_memory_mb / 12; // <64MB + else + // Devices with this little RAM have very little headroom so we hardcode + // the limit rather than relying on the heuristics above. (They also use + // 4444 textures so we can use a lower limit.) + actual.bytes_limit_when_visible = 8; + + actual.bytes_limit_when_visible = + actual.bytes_limit_when_visible * 1024 * 1024; + // Clamp the observed value to a specific range on Android. + actual.bytes_limit_when_visible = std::max( + actual.bytes_limit_when_visible, static_cast<size_t>(8 * 1024 * 1024)); + actual.bytes_limit_when_visible = + std::min(actual.bytes_limit_when_visible, + static_cast<size_t>(256 * 1024 * 1024)); + } + actual.priority_cutoff_when_visible = + gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING; +#else + // Ignore what the system said and give all clients the same maximum + // allocation on desktop platforms. + actual.bytes_limit_when_visible = 512 * 1024 * 1024; + actual.priority_cutoff_when_visible = + gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE; + + // For large monitors (4k), double the tile memory to avoid frequent out of + // memory problems. 4k could mean a screen width of anywhere from 3840 to 4096 + // (see https://en.wikipedia.org/wiki/4K_resolution). We use 3500 as a proxy + // for "large enough". + static const int kLargeDisplayThreshold = 3500; + int display_width = + std::round(initial_screen_size.width() * initial_device_scale_factor); + if (display_width >= kLargeDisplayThreshold) + actual.bytes_limit_when_visible *= 2; +#endif + return actual; } -RenderWidgetCompositor* RenderWidget::compositor() const { - return compositor_.get(); +void RenderWidget::StartCompositor() { + if (!is_hidden()) + layer_tree_view_->SetVisible(true); } void RenderWidget::SetHandlingInputEventForTesting(bool handling_input_event) { @@ -2441,16 +2961,15 @@ bool RenderWidget::IsPointerLocked() { void RenderWidget::StartDragging(blink::WebReferrerPolicy policy, const WebDragData& data, WebDragOperationsMask mask, - const WebImage& image, - const WebPoint& webImageOffset) { - blink::WebRect offset_in_window(webImageOffset.x, webImageOffset.y, 0, 0); + const SkBitmap& drag_image, + const WebPoint& web_image_offset) { + blink::WebRect offset_in_window(web_image_offset.x, web_image_offset.y, 0, 0); ConvertViewportToWindow(&offset_in_window); DropData drop_data(DropDataBuilder::Build(data)); drop_data.referrer_policy = policy; - gfx::Vector2d imageOffset(offset_in_window.x, offset_in_window.y); - Send(new DragHostMsg_StartDragging(routing_id(), drop_data, mask, - image.GetSkBitmap(), imageOffset, - possible_drag_event_info_)); + gfx::Vector2d image_offset(offset_in_window.x, offset_in_window.y); + Send(new DragHostMsg_StartDragging(routing_id(), drop_data, mask, drag_image, + image_offset, possible_drag_event_info_)); } uint32_t RenderWidget::GetContentSourceId() { @@ -2459,9 +2978,10 @@ uint32_t RenderWidget::GetContentSourceId() { void RenderWidget::DidNavigate() { ++current_content_source_id_; - if (!compositor_) + if (!layer_tree_view_) return; - compositor_->SetContentSourceId(current_content_source_id_); + layer_tree_view_->SetContentSourceId(current_content_source_id_); + layer_tree_view_->ClearCachesOnNextCommit(); } blink::WebWidget* RenderWidget::GetWebWidget() const { @@ -2498,11 +3018,12 @@ void RenderWidget::SetMouseCapture(bool capture) { } bool RenderWidget::IsSurfaceSynchronizationEnabled() const { - return compositor_ && compositor_->IsSurfaceSynchronizationEnabled(); + return layer_tree_view_ && + layer_tree_view_->IsSurfaceSynchronizationEnabled(); } void RenderWidget::UpdateURLForCompositorUkm() { - DCHECK(compositor_); + DCHECK(layer_tree_view_); blink::WebFrameWidget* frame_widget = GetFrameWidget(); if (!frame_widget) return; @@ -2511,7 +3032,8 @@ void RenderWidget::UpdateURLForCompositorUkm() { if (!render_frame->IsMainFrame()) return; - compositor_->SetURLForUkm(render_frame->GetWebFrame()->GetDocument().Url()); + layer_tree_view_->SetURLForUkm( + render_frame->GetWebFrame()->GetDocument().Url()); } blink::WebLocalFrame* RenderWidget::GetFocusedWebLocalFrameInWidget() const { diff --git a/chromium/content/renderer/render_widget.h b/chromium/content/renderer/render_widget.h index 480c020d340..ab52a4efb1c 100644 --- a/chromium/content/renderer/render_widget.h +++ b/chromium/content/renderer/render_widget.h @@ -26,6 +26,8 @@ #include "build/build_config.h" #include "cc/input/overscroll_behavior.h" #include "cc/input/touch_action.h" +#include "cc/trees/layer_tree_settings.h" +#include "cc/trees/managed_memory_policy.h" #include "components/viz/common/surfaces/local_surface_id.h" #include "content/common/buildflags.h" #include "content/common/content_export.h" @@ -36,7 +38,7 @@ #include "content/public/common/drop_data.h" #include "content/public/common/screen_info.h" #include "content/renderer/devtools/render_widget_screen_metrics_emulator_delegate.h" -#include "content/renderer/gpu/render_widget_compositor_delegate.h" +#include "content/renderer/gpu/layer_tree_view_delegate.h" #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" @@ -81,7 +83,6 @@ struct WebDeviceEmulationParams; class WebDragData; class WebFrameWidget; class WebGestureEvent; -class WebImage; class WebInputMethodController; class WebLocalFrame; class WebMouseEvent; @@ -106,12 +107,12 @@ class CompositorDependencies; class ExternalPopupMenu; class FrameSwapMessageQueue; class ImeEventGuard; +class LayerTreeView; class MainThreadEventQueue; class PepperPluginInstanceImpl; class RenderFrameImpl; class RenderFrameProxy; class RenderViewImpl; -class RenderWidgetCompositor; class RenderWidgetOwnerDelegate; class RenderWidgetScreenMetricsEmulator; class ResizingModeSelector; @@ -131,14 +132,19 @@ struct VisualProperties; class CONTENT_EXPORT RenderWidget : public IPC::Listener, public IPC::Sender, - virtual public blink::WebWidgetClient, + public blink::WebWidgetClient, public mojom::Widget, - public RenderWidgetCompositorDelegate, + public LayerTreeViewDelegate, public RenderWidgetInputHandlerDelegate, public RenderWidgetScreenMetricsEmulatorDelegate, public base::RefCounted<RenderWidget>, public MainThreadEventQueueClient { public: + using ShowCallback = + base::OnceCallback<void(RenderWidget* widget_to_show, + blink::WebNavigationPolicy policy, + const gfx::Rect& initial_rect)>; + // Creates a new RenderWidget for a popup. |opener| is the RenderView that // this widget lives inside. static RenderWidget* CreateForPopup( @@ -165,13 +171,13 @@ class CONTENT_EXPORT RenderWidget bool, bool); using RenderWidgetInitializedCallback = void (*)(RenderWidget*); - using ShowCallback = base::Callback<void(RenderWidget* widget_to_show, - blink::WebNavigationPolicy policy, - const gfx::Rect& initial_rect)>; static void InstallCreateHook( CreateRenderWidgetFunction create_render_widget, RenderWidgetInitializedCallback render_widget_initialized_callback); + // 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 @@ -249,7 +255,7 @@ class CONTENT_EXPORT RenderWidget // IPC::Sender bool Send(IPC::Message* msg) override; - // RenderWidgetCompositorDelegate + // LayerTreeViewDelegate void ApplyViewportDeltas(const gfx::Vector2dF& inner_delta, const gfx::Vector2dF& outer_delta, const gfx::Vector2dF& elastic_overscroll_delta, @@ -259,7 +265,7 @@ class CONTENT_EXPORT RenderWidget bool has_scrolled_by_touch) override; void BeginMainFrame(base::TimeTicks frame_time) override; void RequestNewLayerTreeFrameSink( - const LayerTreeFrameSinkCallback& callback) override; + LayerTreeFrameSinkCallback callback) override; void DidCommitAndDrawCompositorFrame() override; void DidCommitCompositorFrame() override; void DidCompletePageScaleAnimation() override; @@ -331,20 +337,34 @@ class CONTENT_EXPORT RenderWidget void StartDragging(blink::WebReferrerPolicy policy, const blink::WebDragData& data, blink::WebDragOperationsMask mask, - const blink::WebImage& image, - const blink::WebPoint& imageOffset) override; + const SkBitmap& drag_image, + const blink::WebPoint& image_offset) override; // Override point to obtain that the current input method state and caret // position. virtual ui::TextInputType GetTextInputType(); + // Internal helper that generates the LayerTreeSettings to be given to the + // compositor in StartCompositor(). + static cc::LayerTreeSettings GenerateLayerTreeSettings( + CompositorDependencies* compositor_deps, + bool is_for_subframe, + const gfx::Size& initial_screen_size, + float initial_device_scale_factor); + // Internal helper that generates the ManagedMemoryPolicy to be given to the + // compositor in StartCompositor(). + static cc::ManagedMemoryPolicy GetGpuMemoryPolicy( + const cc::ManagedMemoryPolicy& policy, + const gfx::Size& initial_screen_size, + float initial_device_scale_factor); + // Begins the compositor's scheduler to start producing frames. void StartCompositor(); // Stop compositing. void WillCloseLayerTreeView(); - RenderWidgetCompositor* compositor() const; + LayerTreeView* layer_tree_view() const { return layer_tree_view_.get(); } WidgetInputHandlerManager* widget_input_handler_manager() { return widget_input_handler_manager_.get(); @@ -396,6 +416,9 @@ class CONTENT_EXPORT RenderWidget // Called when the Widget has changed size as a result of an auto-resize. void DidAutoResize(const gfx::Size& new_size); + void DidPresentForceDrawFrame(int snapshot_id, + const gfx::PresentationFeedback& feedback); + // Indicates whether this widget has focus. bool has_focus() const { return has_focus_; } @@ -447,7 +470,9 @@ class CONTENT_EXPORT RenderWidget scoped_refptr<MainThreadEventQueue> GetInputEventQueue(); + void OnSetActive(bool active); virtual void OnSetFocus(bool enable); + void OnSetBackgroundOpaque(bool opaque); void OnMouseCaptureLost(); void OnCursorVisibilityChange(bool is_visible); void OnSetEditCommandsForNextKeyEvent(const EditCommands& edit_commands); @@ -515,7 +540,7 @@ class CONTENT_EXPORT RenderWidget ~RenderWidget() override; static blink::WebFrameWidget* CreateWebFrameWidget( - RenderWidget* render_widget, + blink::WebWidgetClient* widget_client, blink::WebLocalFrame* frame); // Creates a WebWidget based on the popup type. @@ -524,11 +549,7 @@ class CONTENT_EXPORT RenderWidget // 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. - void Init(const ShowCallback& show_callback, blink::WebWidget* web_widget); - - // Allows the process to exit once the unload handler has finished, if there - // are no other active RenderWidgets. - void WasSwappedOut(); + void Init(ShowCallback show_callback, blink::WebWidget* web_widget); void DoDeferredClose(); void NotifyOnClose(); @@ -568,10 +589,11 @@ class CONTENT_EXPORT RenderWidget void OnDisableDeviceEmulation(); virtual void OnWasHidden(); virtual void OnWasShown(bool needs_repainting, - const ui::LatencyInfo& latency_info); + base::TimeTicks show_request_timestamp); void OnCreateVideoAck(int32_t video_id); void OnUpdateVideoAck(int32_t video_id); - void OnRequestMoveAck(); + 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); @@ -701,7 +723,7 @@ class CONTENT_EXPORT RenderWidget RenderWidgetOwnerDelegate* owner_delegate_; // This is lazily constructed and must not outlive webwidget_. - std::unique_ptr<RenderWidgetCompositor> compositor_; + std::unique_ptr<LayerTreeView> layer_tree_view_; // The rect where this view should be initially shown. gfx::Rect initial_rect_; @@ -906,6 +928,8 @@ class CONTENT_EXPORT RenderWidget 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 @@ -931,7 +955,7 @@ class CONTENT_EXPORT RenderWidget bool for_oopif_; // A callback into the creator/opener of this widget, to be executed when - // WebWidgetClient::show() occurs. + // WebWidgetClient::Show() occurs. ShowCallback show_callback_; #if defined(OS_MACOSX) diff --git a/chromium/content/renderer/render_widget_fullscreen_pepper.cc b/chromium/content/renderer/render_widget_fullscreen_pepper.cc index 1e908be6d0f..28bf42737ca 100644 --- a/chromium/content/renderer/render_widget_fullscreen_pepper.cc +++ b/chromium/content/renderer/render_widget_fullscreen_pepper.cc @@ -10,15 +10,15 @@ #include "base/command_line.h" #include "base/macros.h" #include "build/build_config.h" +#include "cc/paint/paint_canvas.h" #include "content/common/view_messages.h" #include "content/public/common/content_switches.h" #include "content/public/common/use_zoom_for_dsf_policy.h" -#include "content/renderer/gpu/render_widget_compositor.h" +#include "content/renderer/gpu/layer_tree_view.h" #include "content/renderer/pepper/pepper_plugin_instance_impl.h" #include "content/renderer/render_thread_impl.h" #include "gpu/ipc/client/gpu_channel_host.h" #include "skia/ext/platform_canvas.h" -#include "third_party/blink/public/platform/web_canvas.h" #include "third_party/blink/public/platform/web_cursor_info.h" #include "third_party/blink/public/platform/web_gesture_event.h" #include "third_party/blink/public/platform/web_mouse_wheel_event.h" @@ -28,7 +28,6 @@ #include "ui/gfx/geometry/size_conversions.h" #include "ui/gl/gpu_preference.h" -using blink::WebCanvas; using blink::WebCoalescedInputEvent; using blink::WebImeTextSpan; using blink::WebCursorInfo; @@ -254,19 +253,19 @@ class PepperWidget : public WebWidget { // static RenderWidgetFullscreenPepper* RenderWidgetFullscreenPepper::Create( int32_t routing_id, - const RenderWidget::ShowCallback& show_callback, + RenderWidget::ShowCallback show_callback, CompositorDependencies* compositor_deps, PepperPluginInstanceImpl* plugin, const GURL& active_url, const ScreenInfo& screen_info, mojom::WidgetRequest widget_request) { DCHECK_NE(MSG_ROUTING_NONE, routing_id); - DCHECK(!show_callback.is_null()); + DCHECK(show_callback); scoped_refptr<RenderWidgetFullscreenPepper> widget( new RenderWidgetFullscreenPepper(routing_id, compositor_deps, plugin, active_url, screen_info, std::move(widget_request))); - widget->Init(show_callback, new PepperWidget(widget.get())); + widget->Init(std::move(show_callback), new PepperWidget(widget.get())); widget->AddRef(); return widget.get(); } @@ -335,15 +334,15 @@ void RenderWidgetFullscreenPepper::PepperDidChangeCursor( void RenderWidgetFullscreenPepper::SetLayer(cc::Layer* layer) { layer_ = layer; if (!layer_) { - if (compositor_) - compositor_->ClearRootLayer(); + if (layer_tree_view()) + layer_tree_view()->ClearRootLayer(); return; } - if (!compositor()) + if (!layer_tree_view()) InitializeLayerTreeView(); UpdateLayerBounds(); layer_->SetIsDrawable(true); - compositor_->SetRootLayer(layer_); + layer_tree_view()->SetRootLayer(layer_); } bool RenderWidgetFullscreenPepper::OnMessageReceived(const IPC::Message& msg) { @@ -392,7 +391,7 @@ void RenderWidgetFullscreenPepper::UpdateLayerBounds() { if (!layer_) return; - if (IsUseZoomForDSFEnabled()) { + if (compositor_deps()->IsUseZoomForDSFEnabled()) { // Note that root cc::Layers' bounds are specified in pixels (in contrast // with non-root cc::Layers' bounds, which are specified in DIPs). layer_->SetBounds(blink::WebSize(compositor_viewport_pixel_size())); diff --git a/chromium/content/renderer/render_widget_fullscreen_pepper.h b/chromium/content/renderer/render_widget_fullscreen_pepper.h index 0faccb2ee7c..548bc9913a6 100644 --- a/chromium/content/renderer/render_widget_fullscreen_pepper.h +++ b/chromium/content/renderer/render_widget_fullscreen_pepper.h @@ -32,7 +32,7 @@ class RenderWidgetFullscreenPepper : public RenderWidget, public: static RenderWidgetFullscreenPepper* Create( int32_t routing_id, - const RenderWidget::ShowCallback& show_callback, + RenderWidget::ShowCallback show_callback, CompositorDependencies* compositor_deps, PepperPluginInstanceImpl* plugin, const GURL& active_url, diff --git a/chromium/content/renderer/render_widget_owner_delegate.h b/chromium/content/renderer/render_widget_owner_delegate.h index 22f573c9a7f..8438e9ac6a2 100644 --- a/chromium/content/renderer/render_widget_owner_delegate.h +++ b/chromium/content/renderer/render_widget_owner_delegate.h @@ -25,6 +25,12 @@ class CONTENT_EXPORT RenderWidgetOwnerDelegate { virtual bool RenderWidgetWillHandleMouseEvent( const blink::WebMouseEvent& event) = 0; + // See comment in RenderWidgetHost::SetActive(). + virtual void SetActive(bool active) = 0; + + // See comment in RenderWidgetHostImpl::SetBackgroundOpaque(). + virtual void SetBackgroundOpaque(bool opaque) = 0; + protected: virtual ~RenderWidgetOwnerDelegate() {} }; diff --git a/chromium/content/renderer/render_widget_unittest.cc b/chromium/content/renderer/render_widget_unittest.cc index 8a4a85433a9..91392d4c552 100644 --- a/chromium/content/renderer/render_widget_unittest.cc +++ b/chromium/content/renderer/render_widget_unittest.cc @@ -10,8 +10,10 @@ #include "base/macros.h" #include "base/optional.h" #include "base/run_loop.h" -#include "base/test/histogram_tester.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_task_environment.h" +#include "build/build_config.h" +#include "cc/trees/layer_tree_host.h" #include "components/viz/common/features.h" #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" #include "content/common/input/input_handler.mojom.h" @@ -22,7 +24,7 @@ #include "content/public/common/content_features.h" #include "content/public/test/mock_render_thread.h" #include "content/renderer/devtools/render_widget_screen_metrics_emulator.h" -#include "content/renderer/gpu/render_widget_compositor.h" +#include "content/renderer/gpu/layer_tree_view.h" #include "content/renderer/input/widget_input_handler_manager.h" #include "content/test/fake_compositor_dependencies.h" #include "content/test/mock_render_process.h" @@ -281,25 +283,6 @@ TEST_F(RenderWidgetUnittest, EventOverscroll) { widget()->SendInputEvent(scroll, handled_event.GetCallback()); } -TEST_F(RenderWidgetUnittest, FlingOverscroll) { - ui::DidOverscrollParams expected_overscroll; - expected_overscroll.latest_overscroll_delta = gfx::Vector2dF(10, 5); - expected_overscroll.accumulated_overscroll = gfx::Vector2dF(5, 5); - expected_overscroll.causal_event_viewport_point = gfx::PointF(1, 1); - expected_overscroll.current_fling_velocity = gfx::Vector2dF(10, 5); - - EXPECT_CALL(*widget()->mock_input_handler_host(), - DidOverscroll(expected_overscroll)) - .Times(1); - - // Overscroll notifications received outside of handling an input event should - // be sent as a separate IPC. - widget()->DidOverscroll(blink::WebFloatSize(10, 5), blink::WebFloatSize(5, 5), - blink::WebFloatPoint(1, 1), - blink::WebFloatSize(10, 5), cc::OverscrollBehavior()); - base::RunLoop().RunUntilIdle(); -} - TEST_F(RenderWidgetUnittest, RenderWidgetInputEventUmaMetrics) { SyntheticWebTouchEvent touch; touch.PressPoint(10, 10); @@ -385,13 +368,19 @@ TEST_F(RenderWidgetUnittest, AutoResizeAllocatedLocalSurfaceId) { widget()->SynchronizeVisualProperties(visual_properties); EXPECT_EQ(allocator.GetCurrentLocalSurfaceId(), widget()->local_surface_id_from_parent()); - EXPECT_FALSE(widget()->compositor()->HasNewLocalSurfaceIdRequest()); + EXPECT_FALSE(widget() + ->layer_tree_view() + ->layer_tree_host() + ->new_local_surface_id_request_for_testing()); constexpr gfx::Size size(200, 200); widget()->DidAutoResize(size); EXPECT_EQ(allocator.GetCurrentLocalSurfaceId(), widget()->local_surface_id_from_parent()); - EXPECT_TRUE(widget()->compositor()->HasNewLocalSurfaceIdRequest()); + EXPECT_TRUE(widget() + ->layer_tree_view() + ->layer_tree_host() + ->new_local_surface_id_request_for_testing()); } class PopupRenderWidget : public RenderWidget { @@ -520,4 +509,29 @@ TEST_F(RenderWidgetPopupUnittest, EmulatingPopupRect) { EXPECT_EQ(popup_emulated_rect.y, widget()->ViewRect().y); } +// Verify desktop memory limit calculations. +#if !defined(OS_ANDROID) +TEST(RenderWidgetTest, IgnoreGivenMemoryPolicy) { + auto policy = RenderWidget::GetGpuMemoryPolicy(cc::ManagedMemoryPolicy(256), + gfx::Size(), 1.f); + EXPECT_EQ(512u * 1024u * 1024u, policy.bytes_limit_when_visible); + EXPECT_EQ(gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE, + policy.priority_cutoff_when_visible); +} + +TEST(RenderWidgetTest, LargeScreensUseMoreMemory) { + auto policy = RenderWidget::GetGpuMemoryPolicy(cc::ManagedMemoryPolicy(256), + gfx::Size(4096, 2160), 1.f); + EXPECT_EQ(2u * 512u * 1024u * 1024u, policy.bytes_limit_when_visible); + EXPECT_EQ(gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE, + policy.priority_cutoff_when_visible); + + policy = RenderWidget::GetGpuMemoryPolicy(cc::ManagedMemoryPolicy(256), + gfx::Size(2048, 1080), 2.f); + EXPECT_EQ(2u * 512u * 1024u * 1024u, policy.bytes_limit_when_visible); + EXPECT_EQ(gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE, + policy.priority_cutoff_when_visible); +} +#endif // !defined(OS_ANDROID) + } // namespace content diff --git a/chromium/content/renderer/renderer_blink_platform_impl.cc b/chromium/content/renderer/renderer_blink_platform_impl.cc index 4205c92765a..a9b86c68fe5 100644 --- a/chromium/content/renderer/renderer_blink_platform_impl.cc +++ b/chromium/content/renderer/renderer_blink_platform_impl.cc @@ -37,28 +37,26 @@ #include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" #include "content/public/common/service_manager_connection.h" +#include "content/public/common/service_names.mojom.h" #include "content/public/common/webplugininfo.h" #include "content/public/renderer/content_renderer_client.h" #include "content/public/renderer/media_stream_utils.h" #include "content/public/renderer/render_frame.h" #include "content/renderer/blob_storage/webblobregistry_impl.h" -#include "content/renderer/device_sensors/device_motion_event_pump.h" -#include "content/renderer/device_sensors/device_orientation_event_pump.h" #include "content/renderer/dom_storage/local_storage_cached_areas.h" #include "content/renderer/dom_storage/local_storage_namespace.h" #include "content/renderer/dom_storage/session_web_storage_namespace_impl.h" #include "content/renderer/dom_storage/webstoragenamespace_impl.h" #include "content/renderer/file_info_util.h" #include "content/renderer/fileapi/webfilesystem_impl.h" -#include "content/renderer/gamepad_shared_memory_reader.h" #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/resource_dispatcher.h" #include "content/renderer/loader/web_data_consumer_handle_impl.h" #include "content/renderer/loader/web_url_loader_impl.h" +#include "content/renderer/media/audio/audio_device_factory.h" #include "content/renderer/media/audio_decoder.h" -#include "content/renderer/media/audio_device_factory.h" #include "content/renderer/media/midi/renderer_webmidiaccessor_impl.h" #include "content/renderer/media/renderer_webaudiodevice_impl.h" #include "content/renderer/media_capture_from_element/canvas_capture_handler.h" @@ -71,7 +69,6 @@ #include "content/renderer/storage_util.h" #include "content/renderer/web_database_observer_impl.h" #include "content/renderer/webgraphicscontext3d_provider_impl.h" -#include "content/renderer/webpublicsuffixlist_impl.h" #include "content/renderer/worker_thread_registry.h" #include "device/gamepad/public/cpp/gamepads.h" #include "gpu/command_buffer/client/gles2_interface.h" @@ -86,8 +83,8 @@ #include "mojo/public/cpp/bindings/strong_binding.h" #include "mojo/public/cpp/system/platform_handle.h" #include "ppapi/buildflags/buildflags.h" -#include "services/device/public/cpp/generic_sensor/motion_data.h" #include "services/network/public/cpp/features.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/cpp/wrapper_shared_url_loader_factory.h" #include "services/service_manager/public/cpp/connector.h" #include "services/service_manager/public/cpp/interface_provider.h" @@ -96,19 +93,15 @@ #include "third_party/blink/public/common/origin_trials/trial_token_validator.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/device_orientation/web_device_motion_listener.h" -#include "third_party/blink/public/platform/modules/device_orientation/web_device_orientation_listener.h" #include "third_party/blink/public/platform/modules/webmidi/web_midi_accessor.h" #include "third_party/blink/public/platform/scheduler/child/webthread_base.h" -#include "third_party/blink/public/platform/scheduler/web_main_thread_scheduler.h" +#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h" #include "third_party/blink/public/platform/url_conversion.h" #include "third_party/blink/public/platform/web_audio_latency_hint.h" #include "third_party/blink/public/platform/web_blob_registry.h" #include "third_party/blink/public/platform/web_file_info.h" #include "third_party/blink/public/platform/web_media_recorder_handler.h" #include "third_party/blink/public/platform/web_media_stream_center.h" -#include "third_party/blink/public/platform/web_media_stream_center_client.h" -#include "third_party/blink/public/platform/web_plugin_list_builder.h" #include "third_party/blink/public/platform/web_rtc_certificate_generator.h" #include "third_party/blink/public/platform/web_rtc_peer_connection_handler.h" #include "third_party/blink/public/platform/web_security_origin.h" @@ -125,7 +118,6 @@ #if defined(OS_MACOSX) #include "content/child/child_process_sandbox_support_impl_mac.h" #include "content/common/mac/font_loader.h" -#include "content/renderer/webscrollbarbehavior_impl_mac.h" #include "third_party/blink/public/platform/mac/web_sandbox_support.h" #endif @@ -143,13 +135,6 @@ #endif #endif -#if defined(USE_AURA) -#include "content/renderer/webscrollbarbehavior_impl_aura.h" -#elif !defined(OS_MACOSX) -#include "third_party/blink/public/platform/web_scrollbar_behavior.h" -#define WebScrollbarBehaviorImpl blink::WebScrollbarBehavior -#endif - #include "content/renderer/media/webrtc/peer_connection_dependency_factory.h" #include "content/renderer/media/webrtc/rtc_certificate_generator.h" #include "content/renderer/media/webrtc/webrtc_uma_histograms.h" @@ -168,7 +153,6 @@ using blink::WebMediaPlayer; using blink::WebMediaRecorderHandler; using blink::WebMediaStream; using blink::WebMediaStreamCenter; -using blink::WebMediaStreamCenterClient; using blink::WebMediaStreamTrack; using blink::WebRTCPeerConnectionHandler; using blink::WebRTCPeerConnectionHandlerClient; @@ -183,10 +167,6 @@ namespace content { namespace { bool g_sandbox_enabled = true; -base::LazyInstance<device::MotionData>::Leaky g_test_device_motion_data = - LAZY_INSTANCE_INITIALIZER; -base::LazyInstance<device::OrientationData>::Leaky - g_test_device_orientation_data = LAZY_INSTANCE_INITIALIZER; media::AudioParameters GetAudioHardwareParams() { blink::WebLocalFrame* const web_frame = @@ -200,19 +180,14 @@ media::AudioParameters GetAudioHardwareParams() { .output_params(); } -network::mojom::URLLoaderFactoryPtr GetBlobURLLoaderFactoryGetter() { - network::mojom::URLLoaderFactoryPtr blob_loader_factory; - RenderThreadImpl::current()->GetRendererHost()->GetBlobURLLoaderFactory( - mojo::MakeRequest(&blob_loader_factory)); - return blob_loader_factory; -} - gpu::ContextType ToGpuContextType(blink::Platform::ContextType type) { switch (type) { case blink::Platform::kWebGL1ContextType: return gpu::CONTEXT_TYPE_WEBGL1; case blink::Platform::kWebGL2ContextType: return gpu::CONTEXT_TYPE_WEBGL2; + case blink::Platform::kWebGL2ComputeContextType: + return gpu::CONTEXT_TYPE_WEBGL2_COMPUTE; case blink::Platform::kGLES2ContextType: return gpu::CONTEXT_TYPE_OPENGLES2; case blink::Platform::kGLES3ContextType: @@ -230,19 +205,26 @@ gpu::ContextType ToGpuContextType(blink::Platform::ContextType type) { class RendererBlinkPlatformImpl::SandboxSupport : public blink::WebSandboxSupport { public: +#if defined(OS_LINUX) + explicit SandboxSupport(sk_sp<font_service::FontLoader> font_loader) + : font_loader_(std::move(font_loader)) {} +#endif ~SandboxSupport() override {} #if defined(OS_MACOSX) bool LoadFont(CTFontRef src_font, CGFontRef* container, uint32_t* font_id) override; -#elif defined(OS_POSIX) +#elif defined(OS_LINUX) void GetFallbackFontForCharacter( blink::WebUChar32 character, const char* preferred_locale, blink::WebFallbackFont* fallbackFont) override; void GetWebFontRenderStyleForStrike(const char* family, - int sizeAndStyle, + int size, + bool is_bold, + bool is_italic, + float device_scale_factor, blink::WebFontRenderStyle* out) override; private: @@ -251,6 +233,7 @@ class RendererBlinkPlatformImpl::SandboxSupport // here. base::Lock unicode_font_families_mutex_; std::map<int32_t, blink::WebFallbackFont> unicode_font_families_; + sk_sp<font_service::FontLoader> font_loader_; #endif }; #endif // !defined(OS_ANDROID) && !defined(OS_WIN) @@ -258,7 +241,7 @@ class RendererBlinkPlatformImpl::SandboxSupport //------------------------------------------------------------------------------ RendererBlinkPlatformImpl::RendererBlinkPlatformImpl( - blink::scheduler::WebMainThreadScheduler* main_thread_scheduler) + blink::scheduler::WebThreadScheduler* main_thread_scheduler) : BlinkPlatformImpl(main_thread_scheduler->DefaultTaskRunner(), RenderThreadImpl::current() ? RenderThreadImpl::current()->GetIOTaskRunner() @@ -266,17 +249,9 @@ RendererBlinkPlatformImpl::RendererBlinkPlatformImpl( compositor_thread_(nullptr), main_thread_(main_thread_scheduler->CreateMainThread()), sudden_termination_disables_(0), - plugin_refresh_allowed_(true), + is_locked_to_site_(false), default_task_runner_(main_thread_scheduler->DefaultTaskRunner()), - web_scrollbar_behavior_(new WebScrollbarBehaviorImpl), main_thread_scheduler_(main_thread_scheduler) { -#if !defined(OS_ANDROID) && !defined(OS_WIN) && !defined(OS_FUCHSIA) - if (g_sandbox_enabled && sandboxEnabled()) { - sandbox_support_.reset(new RendererBlinkPlatformImpl::SandboxSupport); - } else { - DVLOG(1) << "Disabling sandbox support for testing."; - } -#endif // RenderThread may not exist in some tests. if (RenderThreadImpl::current()) { @@ -290,11 +265,28 @@ RendererBlinkPlatformImpl::RendererBlinkPlatformImpl( 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_); +#endif } else { service_manager::mojom::ConnectorRequest request; connector_ = service_manager::Connector::Create(&request); } +#if !defined(OS_ANDROID) && !defined(OS_WIN) && !defined(OS_FUCHSIA) + if (g_sandbox_enabled && sandboxEnabled()) { +#if defined(OS_MACOSX) + sandbox_support_.reset(new RendererBlinkPlatformImpl::SandboxSupport()); +#else + sandbox_support_.reset( + new RendererBlinkPlatformImpl::SandboxSupport(font_loader_)); +#endif + } else { + DVLOG(1) << "Disabling sandbox support for testing."; + } +#endif + blink_interface_provider_.reset( new BlinkInterfaceProviderImpl(connector_.get())); top_level_blame_context_.Initialize(); @@ -344,6 +336,14 @@ RendererBlinkPlatformImpl::WrapURLLoaderFactory( network::mojom::URLLoaderFactory::Version_))); } +std::unique_ptr<blink::WebURLLoaderFactory> +RendererBlinkPlatformImpl::WrapSharedURLLoaderFactory( + scoped_refptr<network::SharedURLLoaderFactory> factory) { + return std::make_unique<WebURLLoaderFactoryImpl>( + RenderThreadImpl::current()->resource_dispatcher()->GetWeakPtr(), + std::move(factory)); +} + std::unique_ptr<blink::WebDataConsumerHandle> RendererBlinkPlatformImpl::CreateDataConsumerHandle( mojo::ScopedDataPipeConsumerHandle handle) { @@ -354,10 +354,7 @@ scoped_refptr<ChildURLLoaderFactoryBundle> RendererBlinkPlatformImpl::CreateDefaultURLLoaderFactoryBundle() { return base::MakeRefCounted<ChildURLLoaderFactoryBundle>( base::BindOnce(&RendererBlinkPlatformImpl::CreateNetworkURLLoaderFactory, - base::Unretained(this)), - base::FeatureList::IsEnabled(network::features::kNetworkService) - ? base::BindOnce(&GetBlobURLLoaderFactoryGetter) - : ChildURLLoaderFactoryBundle::FactoryGetterCallback()); + base::Unretained(this))); } PossiblyAssociatedInterfacePtr<network::mojom::URLLoaderFactory> @@ -406,7 +403,7 @@ blink::WebSandboxSupport* RendererBlinkPlatformImpl::GetSandboxSupport() { } blink::WebCookieJar* RendererBlinkPlatformImpl::CookieJar() { - NOTREACHED() << "Use WebFrameClient::cookieJar() instead!"; + NOTREACHED() << "Use WebLocalFrameClient::cookieJar() instead!"; return nullptr; } @@ -590,7 +587,7 @@ bool RendererBlinkPlatformImpl::SandboxSupport::LoadFont(CTFontRef src_font, return content::LoadFont(src_font, out, font_id); } -#elif defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA) +#elif defined(OS_POSIX) && !defined(OS_ANDROID) void RendererBlinkPlatformImpl::SandboxSupport::GetFallbackFontForCharacter( blink::WebUChar32 character, @@ -610,16 +607,20 @@ void RendererBlinkPlatformImpl::SandboxSupport::GetFallbackFontForCharacter( return; } - content::GetFallbackFontForCharacter(character, preferred_locale, - fallbackFont); + content::GetFallbackFontForCharacter(font_loader_, character, + preferred_locale, fallbackFont); unicode_font_families_.insert(std::make_pair(character, *fallbackFont)); } void RendererBlinkPlatformImpl::SandboxSupport::GetWebFontRenderStyleForStrike( const char* family, - int sizeAndStyle, + int size, + bool is_bold, + bool is_italic, + float device_scale_factor, blink::WebFontRenderStyle* out) { - GetRenderStyleForStrike(family, sizeAndStyle, out); + GetRenderStyleForStrike(font_loader_, family, size, is_bold, is_italic, + device_scale_factor, out); } #endif @@ -682,10 +683,12 @@ viz::FrameSinkId RendererBlinkPlatformImpl::GenerateFrameSinkId() { RenderThread::Get()->GenerateRoutingID()); } -bool RendererBlinkPlatformImpl::IsThreadedCompositingEnabled() { - RenderThreadImpl* thread = RenderThreadImpl::current(); - // thread can be NULL in tests. - return thread && thread->compositor_task_runner().get(); +bool RendererBlinkPlatformImpl::IsLockedToSite() const { + return is_locked_to_site_; +} + +void RendererBlinkPlatformImpl::SetIsLockedToSite() { + is_locked_to_site_ = true; } bool RendererBlinkPlatformImpl::IsGpuCompositingDisabled() { @@ -765,48 +768,6 @@ RendererBlinkPlatformImpl::CreateMIDIAccessor( return std::make_unique<RendererWebMIDIAccessorImpl>(client); } -void RendererBlinkPlatformImpl::GetPluginList( - bool refresh, - const blink::WebSecurityOrigin& mainFrameOrigin, - blink::WebPluginListBuilder* builder) { -#if BUILDFLAG(ENABLE_PLUGINS) - std::vector<WebPluginInfo> plugins; - if (!plugin_refresh_allowed_) - refresh = false; - RenderThread::Get()->Send( - new FrameHostMsg_GetPlugins(refresh, mainFrameOrigin, &plugins)); - for (const WebPluginInfo& plugin : plugins) { - builder->AddPlugin(WebString::FromUTF16(plugin.name), - WebString::FromUTF16(plugin.desc), - blink::FilePathToWebString(plugin.path.BaseName()), - plugin.background_color); - - for (const WebPluginMimeType& mime_type : plugin.mime_types) { - builder->AddMediaTypeToLastPlugin( - WebString::FromUTF8(mime_type.mime_type), - WebString::FromUTF16(mime_type.description)); - - for (const auto& extension : mime_type.file_extensions) { - builder->AddFileExtensionToLastMediaType( - WebString::FromUTF8(extension)); - } - } - } -#endif -} - -//------------------------------------------------------------------------------ - -blink::WebPublicSuffixList* RendererBlinkPlatformImpl::PublicSuffixList() { - return &public_suffix_list_; -} - -//------------------------------------------------------------------------------ - -blink::WebScrollbarBehavior* RendererBlinkPlatformImpl::ScrollbarBehavior() { - return web_scrollbar_behavior_.get(); -} - //------------------------------------------------------------------------------ WebBlobRegistry* RendererBlinkPlatformImpl::GetBlobRegistry() { @@ -817,11 +778,6 @@ WebBlobRegistry* RendererBlinkPlatformImpl::GetBlobRegistry() { //------------------------------------------------------------------------------ void RendererBlinkPlatformImpl::SampleGamepads(device::Gamepads& gamepads) { - PlatformEventObserverBase* observer = - platform_event_observers_.Lookup(blink::kWebPlatformEventTypeGamepad); - if (!observer) - return; - static_cast<RendererGamepadProvider*>(observer)->SampleGamepads(gamepads); } //------------------------------------------------------------------------------ @@ -860,13 +816,12 @@ RendererBlinkPlatformImpl::CreateRTCCertificateGenerator() { //------------------------------------------------------------------------------ std::unique_ptr<WebMediaStreamCenter> -RendererBlinkPlatformImpl::CreateMediaStreamCenter( - WebMediaStreamCenterClient* client) { +RendererBlinkPlatformImpl::CreateMediaStreamCenter() { RenderThreadImpl* render_thread = RenderThreadImpl::current(); DCHECK(render_thread); if (!render_thread) return nullptr; - return render_thread->CreateMediaStreamCenter(client); + return render_thread->CreateMediaStreamCenter(); } // static @@ -943,6 +898,28 @@ RendererBlinkPlatformImpl::CreateImageCaptureFrameGrabber() { return std::make_unique<ImageCaptureFrameGrabber>(); } +//------------------------------------------------------------------------------ + +std::unique_ptr<webrtc::RtpCapabilities> +RendererBlinkPlatformImpl::GetRtpSenderCapabilities( + const blink::WebString& kind) { + PeerConnectionDependencyFactory* pc_dependency_factory = + RenderThreadImpl::current()->GetPeerConnectionDependencyFactory(); + pc_dependency_factory->EnsureInitialized(); + return pc_dependency_factory->GetSenderCapabilities(kind.Utf8()); +} + +std::unique_ptr<webrtc::RtpCapabilities> +RendererBlinkPlatformImpl::GetRtpReceiverCapabilities( + const blink::WebString& kind) { + PeerConnectionDependencyFactory* pc_dependency_factory = + RenderThreadImpl::current()->GetPeerConnectionDependencyFactory(); + pc_dependency_factory->EnsureInitialized(); + return pc_dependency_factory->GetReceiverCapabilities(kind.Utf8()); +} + +//------------------------------------------------------------------------------ + void RendererBlinkPlatformImpl::UpdateWebRTCAPICount( blink::WebRTCAPIName api_name) { UpdateWebRTCMethodCount(api_name); @@ -969,11 +946,12 @@ static void Collect3DContextInformation( blink::Platform::GraphicsInfo* gl_info, const gpu::GPUInfo& gpu_info) { DCHECK(gl_info); - gl_info->vendor_id = gpu_info.gpu.vendor_id; - gl_info->device_id = gpu_info.gpu.device_id; + const gpu::GPUInfo::GPUDevice& active_gpu = gpu_info.active_gpu(); + gl_info->vendor_id = active_gpu.vendor_id; + gl_info->device_id = active_gpu.device_id; gl_info->renderer_info = WebString::FromUTF8(gpu_info.gl_renderer); gl_info->vendor_info = WebString::FromUTF8(gpu_info.gl_vendor); - gl_info->driver_version = WebString::FromUTF8(gpu_info.driver_version); + gl_info->driver_version = WebString::FromUTF8(active_gpu.driver_version); gl_info->reset_notification_strategy = gpu_info.gl_reset_notification_strategy; gl_info->sandboxed = gpu_info.sandboxed; @@ -1003,8 +981,6 @@ RendererBlinkPlatformImpl::CreateOffscreenGraphicsContext3DProvider( } Collect3DContextInformation(gl_info, gpu_channel_host->gpu_info()); - bool is_software_rendering = gpu_channel_host->gpu_info().software_rendering; - // This is an offscreen context. Generally it won't use the default // frame buffer, in that case don't request any alpha, depth, stencil, // antialiasing. But we do need those attributes for the "own @@ -1040,9 +1016,9 @@ RendererBlinkPlatformImpl::CreateOffscreenGraphicsContext3DProvider( gpu::kNullSurfaceHandle, GURL(top_document_web_url), automatic_flushes, support_locking, web_attributes.support_grcontext, gpu::SharedMemoryLimits(), attributes, - ui::command_buffer_metrics::OFFSCREEN_CONTEXT_FOR_WEBGL)); + ui::command_buffer_metrics::ContextType::WEBGL)); return std::make_unique<WebGraphicsContext3DProviderImpl>( - std::move(provider), is_software_rendering); + std::move(provider)); } //------------------------------------------------------------------------------ @@ -1061,15 +1037,12 @@ RendererBlinkPlatformImpl::CreateSharedOffscreenGraphicsContext3DProvider() { // channel can become lost on the IO thread since then. It is important that // this happens after getting |provider|. In the case that this GpuChannelHost // is not the same one backing |provider|, the context behind the |provider| - // will be already lost/dead on arrival, so the value we get for - // |is_software_rendering| will never be wrong. + // will be already lost/dead on arrival. if (!host) return nullptr; - bool is_software_rendering = host->gpu_info().software_rendering; - return std::make_unique<WebGraphicsContext3DProviderImpl>( - std::move(provider), is_software_rendering); + std::move(provider)); } //------------------------------------------------------------------------------ @@ -1099,65 +1072,6 @@ void RendererBlinkPlatformImpl::RecordRapporURL(const char* metric, GetContentClient()->renderer()->RecordRapporURL(metric, url); } -//------------------------------------------------------------------------------ - -// static -void RendererBlinkPlatformImpl::SetMockDeviceMotionDataForTesting( - const device::MotionData& data) { - g_test_device_motion_data.Get() = data; -} - -//------------------------------------------------------------------------------ - -// static -void RendererBlinkPlatformImpl::SetMockDeviceOrientationDataForTesting( - const device::OrientationData& data) { - g_test_device_orientation_data.Get() = data; -} - -//------------------------------------------------------------------------------ - -// static -std::unique_ptr<PlatformEventObserverBase> -RendererBlinkPlatformImpl::CreatePlatformEventObserverFromType( - blink::WebPlatformEventType type) { - RenderThread* thread = RenderThreadImpl::current(); - - // When running layout tests, those observers should not listen to the actual - // hardware changes. In order to make that happen, they will receive a null - // thread. - if (thread && RenderThreadImpl::current()->layout_test_mode()) - thread = nullptr; - - switch (type) { - case blink::kWebPlatformEventTypeDeviceMotion: - return std::make_unique<DeviceMotionEventPump>(thread); - case blink::kWebPlatformEventTypeDeviceOrientation: - return std::make_unique<DeviceOrientationEventPump>(thread, - false /* absolute */); - case blink::kWebPlatformEventTypeDeviceOrientationAbsolute: - return std::make_unique<DeviceOrientationEventPump>(thread, - true /* absolute */); - case blink::kWebPlatformEventTypeGamepad: - return std::make_unique<GamepadSharedMemoryReader>(thread); - default: - // A default statement is required to prevent compilation errors when - // Blink adds a new type. - DVLOG(1) << "RendererBlinkPlatformImpl::startListening() with " - "unknown type."; - } - - return nullptr; -} - -void RendererBlinkPlatformImpl::SetPlatformEventObserverForTesting( - blink::WebPlatformEventType type, - std::unique_ptr<PlatformEventObserverBase> observer) { - if (platform_event_observers_.Lookup(type)) - platform_event_observers_.Remove(type); - platform_event_observers_.AddWithID(std::move(observer), type); -} - service_manager::Connector* RendererBlinkPlatformImpl::GetConnector() { return connector_.get(); } @@ -1169,68 +1083,11 @@ blink::InterfaceProvider* RendererBlinkPlatformImpl::GetInterfaceProvider() { void RendererBlinkPlatformImpl::StartListening( blink::WebPlatformEventType type, blink::WebPlatformEventListener* listener) { - PlatformEventObserverBase* observer = platform_event_observers_.Lookup(type); - if (!observer) { - std::unique_ptr<PlatformEventObserverBase> new_observer = - CreatePlatformEventObserverFromType(type); - if (!new_observer) - return; - observer = new_observer.get(); - platform_event_observers_.AddWithID(std::move(new_observer), - static_cast<int32_t>(type)); - } - observer->Start(listener); - - // Device events (motion and orientation) expect to get an event fired - // as soon as a listener is registered if a fake data was passed before. - // TODO(mlamouri,timvolodine): make those send mock values directly instead of - // using this broken pattern. - if (RenderThreadImpl::current() && - RenderThreadImpl::current()->layout_test_mode() && - (type == blink::kWebPlatformEventTypeDeviceMotion || - type == blink::kWebPlatformEventTypeDeviceOrientation || - type == blink::kWebPlatformEventTypeDeviceOrientationAbsolute)) { - SendFakeDeviceEventDataForTesting(type); - } -} - -void RendererBlinkPlatformImpl::SendFakeDeviceEventDataForTesting( - blink::WebPlatformEventType type) { - PlatformEventObserverBase* observer = platform_event_observers_.Lookup(type); - CHECK(observer); - - void* data = nullptr; - switch (type) { - case blink::kWebPlatformEventTypeDeviceMotion: - if (g_test_device_motion_data.IsCreated()) - data = &g_test_device_motion_data.Get(); - break; - case blink::kWebPlatformEventTypeDeviceOrientation: - case blink::kWebPlatformEventTypeDeviceOrientationAbsolute: - if (g_test_device_orientation_data.IsCreated()) - data = &g_test_device_orientation_data.Get(); - break; - default: - NOTREACHED(); - break; - } - - if (!data) - return; - - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce(&PlatformEventObserverBase::SendFakeDataForTesting, - base::Unretained(observer), data)); } void RendererBlinkPlatformImpl::StopListening( blink::WebPlatformEventType type) { - PlatformEventObserverBase* observer = platform_event_observers_.Lookup(type); - if (!observer) - return; - observer->Stop(); } //------------------------------------------------------------------------------ diff --git a/chromium/content/renderer/renderer_blink_platform_impl.h b/chromium/content/renderer/renderer_blink_platform_impl.h index ecb5ce6d6aa..bebcd933b8c 100644 --- a/chromium/content/renderer/renderer_blink_platform_impl.h +++ b/chromium/content/renderer/renderer_blink_platform_impl.h @@ -22,7 +22,6 @@ #include "content/common/content_export.h" #include "content/common/possibly_associated_interface_ptr.h" #include "content/renderer/top_level_blame_context.h" -#include "content/renderer/webpublicsuffixlist_impl.h" #include "services/network/public/mojom/url_loader_factory.mojom.h" #include "services/service_manager/public/cpp/interface_provider.h" #include "third_party/blink/public/common/screen_orientation/web_screen_orientation_type.h" @@ -30,13 +29,18 @@ #include "third_party/blink/public/platform/modules/indexeddb/web_idb_factory.h" #include "third_party/blink/public/platform/modules/webdatabase/web_database.mojom.h" +#if defined(OS_LINUX) +#include "components/services/font/public/cpp/font_loader.h" // nogncheck +#include "third_party/skia/include/core/SkRefCnt.h" // nogncheck +#endif + namespace IPC { class SyncMessageFilter; } namespace blink { namespace scheduler { -class WebMainThreadScheduler; +class WebThreadScheduler; class WebThreadBase; } class WebCanvasCaptureHandler; @@ -47,32 +51,26 @@ class WebMediaStream; class WebSecurityOrigin; } // namespace blink -namespace device { -class Gamepads; -class MotionData; -class OrientationData; +namespace network { +class SharedURLLoaderFactory; } namespace content { class BlinkInterfaceProviderImpl; class ChildURLLoaderFactoryBundle; class LocalStorageCachedAreas; -class PlatformEventObserverBase; class ThreadSafeSender; class WebDatabaseObserverImpl; class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl { public: explicit RendererBlinkPlatformImpl( - blink::scheduler::WebMainThreadScheduler* main_thread_scheduler); + blink::scheduler::WebThreadScheduler* main_thread_scheduler); ~RendererBlinkPlatformImpl() override; // Shutdown must be called just prior to shutting down blink. void Shutdown(); - void set_plugin_refresh_allowed(bool plugin_refresh_allowed) { - plugin_refresh_allowed_ = plugin_refresh_allowed; - } // Platform methods: blink::WebSandboxSupport* GetSandboxSupport() override; blink::WebCookieJar* CookieJar() override; @@ -120,18 +118,13 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl { blink::WebString DatabaseCreateOriginIdentifier( const blink::WebSecurityOrigin& origin) override; viz::FrameSinkId GenerateFrameSinkId() override; + bool IsLockedToSite() const override; - void GetPluginList(bool refresh, - const blink::WebSecurityOrigin& mainFrameOrigin, - blink::WebPluginListBuilder* builder) override; - blink::WebPublicSuffixList* PublicSuffixList() override; - blink::WebScrollbarBehavior* ScrollbarBehavior() override; blink::WebIDBFactory* IdbFactory() override; blink::WebFileSystem* FileSystem() override; blink::WebString FileSystemCreateOriginIdentifier( const blink::WebSecurityOrigin& origin) override; - bool IsThreadedCompositingEnabled() override; bool IsThreadedAnimationEnabled() override; bool IsGpuCompositingDisabled() override; double AudioHardwareSampleRate() override; @@ -163,8 +156,8 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl { CreateRTCCertificateGenerator() override; std::unique_ptr<blink::WebMediaRecorderHandler> CreateMediaRecorderHandler( scoped_refptr<base::SingleThreadTaskRunner> task_runner) override; - std::unique_ptr<blink::WebMediaStreamCenter> CreateMediaStreamCenter( - blink::WebMediaStreamCenterClient* client) override; + std::unique_ptr<blink::WebMediaStreamCenter> CreateMediaStreamCenter() + override; std::unique_ptr<blink::WebCanvasCaptureHandler> CreateCanvasCaptureHandler( const blink::WebSize& size, double frame_rate, @@ -178,6 +171,10 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl { blink::WebMediaPlayer* web_media_player) override; std::unique_ptr<blink::WebImageCaptureFrameGrabber> CreateImageCaptureFrameGrabber() override; + std::unique_ptr<webrtc::RtpCapabilities> GetRtpSenderCapabilities( + const blink::WebString& kind) override; + std::unique_ptr<webrtc::RtpCapabilities> GetRtpReceiverCapabilities( + const blink::WebString& kind) override; void UpdateWebRTCAPICount(blink::WebRTCAPIName api_name) override; std::unique_ptr<blink::WebSocketHandshakeThrottle> CreateWebSocketHandshakeThrottle() override; @@ -205,14 +202,6 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl { void WillStopWorkerThread() override; void WorkerContextCreated(const v8::Local<v8::Context>& worker) override; - // Set the PlatformEventObserverBase in |platform_event_observers_| associated - // with |type| to |observer|. If there was already an observer associated to - // the given |type|, it will be replaced. - // Note that |observer| will be owned by this object after the call. - void SetPlatformEventObserverForTesting( - blink::WebPlatformEventType type, - std::unique_ptr<PlatformEventObserverBase> observer); - // Disables the WebSandboxSupport implementation for testing. // Tests that do not set up a full sandbox environment should call // SetSandboxEnabledForTesting(false) _before_ creating any instances @@ -222,13 +211,6 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl { // Returns the previous |enable| value. static bool SetSandboxEnabledForTesting(bool enable); - // Set MotionData to return when setDeviceMotionListener is invoked. - static void SetMockDeviceMotionDataForTesting(const device::MotionData& data); - // Set OrientationData to return when setDeviceOrientationListener - // is invoked. - static void SetMockDeviceOrientationDataForTesting( - const device::OrientationData& data); - WebDatabaseObserverImpl* web_database_observer_impl() { return web_database_observer_impl_.get(); } @@ -237,6 +219,8 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl { override; std::unique_ptr<blink::WebURLLoaderFactory> WrapURLLoaderFactory( mojo::ScopedMessagePipeHandle url_loader_factory_handle) override; + std::unique_ptr<blink::WebURLLoaderFactory> WrapSharedURLLoaderFactory( + scoped_refptr<network::SharedURLLoaderFactory> factory) override; std::unique_ptr<blink::WebDataConsumerHandle> CreateDataConsumerHandle( mojo::ScopedDataPipeConsumerHandle handle) override; void RequestPurgeMemory() override; @@ -259,17 +243,16 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl { void CloneSessionStorageNamespace(const std::string& source_namespace, const std::string& destination_namespace); + // Tells this platform that the renderer is locked to a site (i.e., a scheme + // plus eTLD+1, such as https://google.com), or to a more specific origin. + void SetIsLockedToSite(); + private: bool CheckPreparsedJsCachingEnabled() const; - // Factory that takes a type and return PlatformEventObserverBase that matches - // it. - static std::unique_ptr<PlatformEventObserverBase> - CreatePlatformEventObserverFromType(blink::WebPlatformEventType type); - - // Use the data previously set via SetMockDevice...DataForTesting() and send - // them to the registered listener. - void SendFakeDeviceEventDataForTesting(blink::WebPlatformEventType type); + // 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(); @@ -293,28 +276,21 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl { // we tell the browser to enable fast termination. int sudden_termination_disables_; - // If true, then a GetPlugins call is allowed to rescan the disk. - bool plugin_refresh_allowed_; + // 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_; - WebPublicSuffixListImpl public_suffix_list_; - 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_; - std::unique_ptr<blink::WebScrollbarBehavior> web_scrollbar_behavior_; - - base::IDMap<std::unique_ptr<PlatformEventObserverBase>> - platform_event_observers_; - // NOT OWNED - blink::scheduler::WebMainThreadScheduler* main_thread_scheduler_; + blink::scheduler::WebThreadScheduler* main_thread_scheduler_; TopLevelBlameContext top_level_blame_context_; @@ -325,6 +301,10 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl { blink::mojom::WebDatabaseHostPtrInfo web_database_host_info_; scoped_refptr<blink::mojom::ThreadSafeWebDatabaseHostPtr> web_database_host_; +#if defined(OS_LINUX) + sk_sp<font_service::FontLoader> font_loader_; +#endif + THREAD_CHECKER(main_thread_checker_); DISALLOW_COPY_AND_ASSIGN(RendererBlinkPlatformImpl); diff --git a/chromium/content/renderer/renderer_main.cc b/chromium/content/renderer/renderer_main.cc index f3664c6e0eb..0b722923ba6 100644 --- a/chromium/content/renderer/renderer_main.cc +++ b/chromium/content/renderer/renderer_main.cc @@ -25,6 +25,7 @@ #include "content/common/content_constants_internal.h" #include "content/common/content_switches_internal.h" #include "content/common/service_manager/service_manager_connection_impl.h" +#include "content/common/skia_utils.h" #include "content/public/common/content_switches.h" #include "content/public/common/main_function_params.h" #include "content/public/renderer/content_renderer_client.h" @@ -34,8 +35,7 @@ #include "media/media_buildflags.h" #include "ppapi/buildflags/buildflags.h" #include "services/service_manager/sandbox/switches.h" -#include "third_party/blink/public/platform/scheduler/web_main_thread_scheduler.h" -#include "third_party/skia/include/core/SkGraphics.h" +#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h" #include "third_party/webrtc_overrides/init_webrtc.h" // nogncheck #include "ui/base/ui_base_switches.h" @@ -43,14 +43,6 @@ #include "base/android/library_loader/library_loader_hooks.h" #endif // OS_ANDROID -#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) && \ - !defined(OS_FUCHSIA) -#include "content/common/font_config_ipc_linux.h" -#include "services/service_manager/sandbox/linux/sandbox_linux.h" -#include "services/service_manager/zygote/common/common_sandbox_support_linux.h" -#include "third_party/skia/include/ports/SkFontConfigInterface.h" -#endif - #if defined(OS_MACOSX) #include <Carbon/Carbon.h> #include <signal.h> @@ -121,46 +113,7 @@ int RendererMain(const MainFunctionParams& parameters) { } #endif - const base::CommandLine& process_command_line = - *base::CommandLine::ForCurrentProcess(); - -#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) && \ - !defined(OS_FUCHSIA) - // This call could already have been made from zygote_main_linux.cc. However - // we need to do it here if Zygote is disabled. - if (process_command_line.HasSwitch(switches::kNoZygote)) { - SkFontConfigInterface::SetGlobal( - sk_make_sp<FontConfigIPC>(service_manager::GetSandboxFD())); - } -#endif - - if (!process_command_line.HasSwitch(switches::kDisableSkiaRuntimeOpts)) { - SkGraphics::Init(); - } - - const int kMB = 1024 * 1024; - size_t font_cache_limit; -#if defined(OS_ANDROID) - font_cache_limit = base::SysInfo::IsLowEndDevice() ? kMB : 8 * kMB; - SkGraphics::SetFontCacheLimit(font_cache_limit); -#else - if (process_command_line.HasSwitch(switches::kSkiaFontCacheLimitMb)) { - if (base::StringToSizeT(process_command_line.GetSwitchValueASCII( - switches::kSkiaFontCacheLimitMb), - &font_cache_limit)) { - SkGraphics::SetFontCacheLimit(font_cache_limit * kMB); - } - } - - size_t resource_cache_limit; - if (process_command_line.HasSwitch(switches::kSkiaResourceCacheLimitMb)) { - if (base::StringToSizeT(process_command_line.GetSwitchValueASCII( - switches::kSkiaResourceCacheLimitMb), - &resource_cache_limit)) { - SkGraphics::SetResourceCacheTotalByteLimit(resource_cache_limit * kMB); - } - } -#endif + InitializeSkia(); // This function allows pausing execution using the --renderer-startup-dialog // flag allowing us to attach a debugger. @@ -183,9 +136,6 @@ int RendererMain(const MainFunctionParams& parameters) { base::PlatformThread::SetName("CrRendererMain"); - bool no_sandbox = - command_line.HasSwitch(service_manager::switches::kNoSandbox); - #if defined(OS_ANDROID) // If we have any pending LibraryLoader histograms, record them. base::android::RecordLibraryLoaderRendererHistograms(); @@ -200,8 +150,8 @@ int RendererMain(const MainFunctionParams& parameters) { initial_virtual_time = base::Time::FromDoubleT(initial_time); } } - std::unique_ptr<blink::scheduler::WebMainThreadScheduler> - main_thread_scheduler(blink::scheduler::WebMainThreadScheduler::Create( + std::unique_ptr<blink::scheduler::WebThreadScheduler> main_thread_scheduler( + blink::scheduler::WebThreadScheduler::CreateMainThreadScheduler( initial_virtual_time)); // PlatformInitialize uses FieldTrials, so this must happen later. @@ -218,21 +168,26 @@ int RendererMain(const MainFunctionParams& parameters) { InitializeWebRtcModule(); { -#if defined(OS_WIN) || defined(OS_MACOSX) - // TODO(markus): Check if it is OK to unconditionally move this - // instruction down. - auto render_process = RenderProcessImpl::Create(); - RenderThreadImpl::Create(std::move(main_message_loop), - std::move(main_thread_scheduler)); -#endif bool run_loop = true; - if (!no_sandbox) + bool need_sandbox = + !command_line.HasSwitch(service_manager::switches::kNoSandbox); + +#if !defined(OS_WIN) && !defined(OS_MACOSX) + // Sandbox is enabled before RenderProcess initialization on all platforms, + // except Windows and Mac. + // TODO(markus): Check if it is OK to remove ifdefs for Windows and Mac. + if (need_sandbox) { run_loop = platform.EnableSandbox(); -#if defined(OS_POSIX) && !defined(OS_MACOSX) + need_sandbox = false; + } +#endif + auto render_process = RenderProcessImpl::Create(); RenderThreadImpl::Create(std::move(main_message_loop), std::move(main_thread_scheduler)); -#endif + + if (need_sandbox) + run_loop = platform.EnableSandbox(); base::HighResolutionTimerManager hi_res_timer_manager; diff --git a/chromium/content/renderer/renderer_main_platform_delegate_win.cc b/chromium/content/renderer/renderer_main_platform_delegate_win.cc index d121f97ad00..f59a53dbc38 100644 --- a/chromium/content/renderer/renderer_main_platform_delegate_win.cc +++ b/chromium/content/renderer/renderer_main_platform_delegate_win.cc @@ -55,9 +55,6 @@ void RendererMainPlatformDelegate::PlatformInitialize() { } InitializeDWriteFontProxy(); - - // TODO(robliao): This should use WebScreenInfo. See http://crbug.com/604555. - blink::WebFontRendering::SetDeviceScaleFactor(display::win::GetDPIScale()); } void RendererMainPlatformDelegate::PlatformUninitialize() { diff --git a/chromium/content/renderer/sad_plugin.cc b/chromium/content/renderer/sad_plugin.cc index 5437685fae8..f68f8f481a9 100644 --- a/chromium/content/renderer/sad_plugin.cc +++ b/chromium/content/renderer/sad_plugin.cc @@ -13,9 +13,9 @@ namespace content { -void PaintSadPlugin(blink::WebCanvas* webcanvas, +void PaintSadPlugin(cc::PaintCanvas* webcanvas, const gfx::Rect& plugin_rect, - const SkBitmap& sad_plugin_bitmap) { + const cc::PaintImage& sad_plugin_image) { const int width = plugin_rect.width(); const int height = plugin_rect.height(); @@ -29,10 +29,10 @@ void PaintSadPlugin(blink::WebCanvas* webcanvas, flags.setStyle(cc::PaintFlags::kFill_Style); flags.setColor(SK_ColorBLACK); canvas->drawRect(SkRect::MakeIWH(width, height), flags); - canvas->drawBitmap( - sad_plugin_bitmap, - SkIntToScalar(std::max(0, (width - sad_plugin_bitmap.width()) / 2)), - SkIntToScalar(std::max(0, (height - sad_plugin_bitmap.height()) / 2))); + canvas->drawImage( + sad_plugin_image, + SkIntToScalar(std::max(0, (width - sad_plugin_image.width()) / 2)), + SkIntToScalar(std::max(0, (height - sad_plugin_image.height()) / 2))); } } // namespace content diff --git a/chromium/content/renderer/sad_plugin.h b/chromium/content/renderer/sad_plugin.h index b14808b9f89..b619734266a 100644 --- a/chromium/content/renderer/sad_plugin.h +++ b/chromium/content/renderer/sad_plugin.h @@ -5,9 +5,11 @@ #ifndef CONTENT_RENDERER_SAD_PLUGIN_H_ #define CONTENT_RENDERER_SAD_PLUGIN_H_ -#include "third_party/blink/public/platform/web_canvas.h" +#include "cc/paint/paint_canvas.h" -class SkBitmap; +namespace cc { +class PaintImage; +} namespace gfx { class Rect; @@ -17,9 +19,9 @@ namespace content { // Paints the sad plugin to the given canvas for the given plugin bounds. This // is used by PPAPI out-of-process plugin impls. -void PaintSadPlugin(blink::WebCanvas* canvas, +void PaintSadPlugin(cc::PaintCanvas* canvas, const gfx::Rect& plugin_rect, - const SkBitmap& sad_plugin_bitmap); + const cc::PaintImage& sad_plugin_image); } // namespace content diff --git a/chromium/content/renderer/service_worker/controller_service_worker_connector.cc b/chromium/content/renderer/service_worker/controller_service_worker_connector.cc index c1677a25c30..b9900a2e686 100644 --- a/chromium/content/renderer/service_worker/controller_service_worker_connector.cc +++ b/chromium/content/renderer/service_worker/controller_service_worker_connector.cc @@ -11,23 +11,15 @@ namespace content { ControllerServiceWorkerConnector::ControllerServiceWorkerConnector( - mojom::ServiceWorkerContainerHost* container_host, - mojom::ControllerServiceWorkerPtr controller_ptr, - const std::string& client_id) - : container_host_(container_host), client_id_(client_id) { - SetControllerServiceWorkerPtr(std::move(controller_ptr)); -} - -ControllerServiceWorkerConnector::ControllerServiceWorkerConnector( mojom::ServiceWorkerContainerHostPtrInfo container_host_info, + mojom::ControllerServiceWorkerPtr controller_ptr, const std::string& client_id) : client_id_(client_id) { container_host_ptr_.Bind(std::move(container_host_info)); container_host_ptr_.set_connection_error_handler(base::BindOnce( &ControllerServiceWorkerConnector::OnContainerHostConnectionClosed, base::Unretained(this))); - container_host_ = container_host_ptr_.get(); - SetControllerServiceWorkerPtr(nullptr /* controller_ptr */); + SetControllerServiceWorkerPtr(std::move(controller_ptr)); } mojom::ControllerServiceWorker* @@ -36,9 +28,9 @@ ControllerServiceWorkerConnector::GetControllerServiceWorker( switch (state_) { case State::kDisconnected: { DCHECK(!controller_service_worker_); - DCHECK(container_host_); + DCHECK(container_host_ptr_); mojom::ControllerServiceWorkerPtr controller_ptr; - container_host_->EnsureControllerServiceWorker( + container_host_ptr_->EnsureControllerServiceWorker( mojo::MakeRequest(&controller_ptr), purpose); SetControllerServiceWorkerPtr(std::move(controller_ptr)); return controller_service_worker_.get(); @@ -51,7 +43,7 @@ ControllerServiceWorkerConnector::GetControllerServiceWorker( return nullptr; case State::kNoContainerHost: DCHECK(!controller_service_worker_); - DCHECK(!container_host_); + DCHECK(!container_host_ptr_); return nullptr; } NOTREACHED(); @@ -68,7 +60,6 @@ void ControllerServiceWorkerConnector::RemoveObserver(Observer* observer) { void ControllerServiceWorkerConnector::OnContainerHostConnectionClosed() { state_ = State::kNoContainerHost; - container_host_ = nullptr; container_host_ptr_.reset(); controller_service_worker_.reset(); } @@ -81,7 +72,12 @@ void ControllerServiceWorkerConnector::OnControllerConnectionClosed() { observer.OnConnectionClosed(); } -void ControllerServiceWorkerConnector::ResetControllerConnection( +void ControllerServiceWorkerConnector::AddBinding( + mojom::ControllerServiceWorkerConnectorRequest request) { + bindings_.AddBinding(this, std::move(request)); +} + +void ControllerServiceWorkerConnector::UpdateController( mojom::ControllerServiceWorkerPtr controller_ptr) { if (state_ == State::kNoContainerHost) return; 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 9be6d162087..e24bbdac674 100644 --- a/chromium/content/renderer/service_worker/controller_service_worker_connector.h +++ b/chromium/content/renderer/service_worker/controller_service_worker_connector.h @@ -11,6 +11,7 @@ #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 "mojo/public/cpp/bindings/binding_set.h" namespace content { @@ -23,7 +24,8 @@ class ServiceWorkerContainerHost; // ServiceWorkerProviderContext::ControlleeState and // ServiceWorkerSubresourceLoader{,Factory}. class CONTENT_EXPORT ControllerServiceWorkerConnector - : public base::RefCounted<ControllerServiceWorkerConnector> { + : public mojom::ControllerServiceWorkerConnector, + public base::RefCounted<ControllerServiceWorkerConnector> { public: // Observes the connection to the controller. class Observer { @@ -55,17 +57,12 @@ class CONTENT_EXPORT ControllerServiceWorkerConnector // |controller_ptr| may be nullptr if the caller does not yet have a Mojo // connection to the controller. |state_| is set to kDisconnected in that // case. - ControllerServiceWorkerConnector( - mojom::ServiceWorkerContainerHost* container_host, - mojom::ControllerServiceWorkerPtr controller_ptr, - const std::string& client_id); - - // Used by service worker clients that are workers (i.e., dedicated workers - // and shared workers). Creates and holds the ownership of - // |container_host_ptr_| (as |this| will be created on a different thread from - // the worker thread that has the original |container_host|). + // Creates and holds the ownership of |container_host_ptr_| (as |this| + // will be created on a different thread from the thread that has the + // original |container_host|). ControllerServiceWorkerConnector( mojom::ServiceWorkerContainerHostPtrInfo container_host_info, + mojom::ControllerServiceWorkerPtr controller_ptr, const std::string& client_id); // This may return nullptr if the connection to the ContainerHost (in the @@ -79,10 +76,11 @@ class CONTENT_EXPORT ControllerServiceWorkerConnector void OnContainerHostConnectionClosed(); void OnControllerConnectionClosed(); - // Resets the controller connection with the given |controller_ptr|, this - // can be called when a new controller is given, e.g. due to claim(). - void ResetControllerConnection( - mojom::ControllerServiceWorkerPtr controller_ptr); + void AddBinding(mojom::ControllerServiceWorkerConnectorRequest request); + + // mojom::ControllerServiceWorkerConnector: + void UpdateController( + mojom::ControllerServiceWorkerPtr controller_ptr) override; State state() const { return state_; } @@ -95,13 +93,9 @@ class CONTENT_EXPORT ControllerServiceWorkerConnector State state_ = State::kDisconnected; friend class base::RefCounted<ControllerServiceWorkerConnector>; - ~ControllerServiceWorkerConnector(); + ~ControllerServiceWorkerConnector() override; - // Connection to the ServiceWorkerProviderHost that lives in the - // browser process. This is used to (re-)obtain Mojo connection to - // |controller_service_worker_| when it is not established. - // Cleared when the connection is dropped. - mojom::ServiceWorkerContainerHost* container_host_; + mojo::BindingSet<mojom::ControllerServiceWorkerConnector> bindings_; // Keeps the mojo end to the browser process on its own. // Non-null only for the service worker clients that are workers (i.e., only 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 691fe701daa..a90ae551b9b 100644 --- a/chromium/content/renderer/service_worker/controller_service_worker_impl.cc +++ b/chromium/content/renderer/service_worker/controller_service_worker_impl.cc @@ -4,8 +4,8 @@ #include "content/renderer/service_worker/controller_service_worker_impl.h" -#include "content/common/service_worker/service_worker_utils.h" #include "content/renderer/service_worker/service_worker_context_client.h" +#include "third_party/blink/public/common/service_worker/service_worker_utils.h" namespace content { @@ -13,7 +13,7 @@ ControllerServiceWorkerImpl::ControllerServiceWorkerImpl( mojom::ControllerServiceWorkerRequest request, base::WeakPtr<ServiceWorkerContextClient> context_client) : context_client_(std::move(context_client)) { - CHECK(ServiceWorkerUtils::IsServicificationEnabled()); + CHECK(blink::ServiceWorkerUtils::IsServicificationEnabled()); bindings_.AddBinding(this, std::move(request)); } @@ -25,7 +25,7 @@ void ControllerServiceWorkerImpl::Clone( } void ControllerServiceWorkerImpl::DispatchFetchEvent( - mojom::DispatchFetchEventParamsPtr params, + blink::mojom::DispatchFetchEventParamsPtr params, mojom::ServiceWorkerFetchResponseCallbackPtr response_callback, DispatchFetchEventCallback callback) { DCHECK(context_client_); 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 f2ea0ce06c5..308fa39d3cb 100644 --- a/chromium/content/renderer/service_worker/controller_service_worker_impl.h +++ b/chromium/content/renderer/service_worker/controller_service_worker_impl.h @@ -39,7 +39,7 @@ class ControllerServiceWorkerImpl : public mojom::ControllerServiceWorker { // mojom::ControllerServiceWorker: void DispatchFetchEvent( - mojom::DispatchFetchEventParamsPtr params, + blink::mojom::DispatchFetchEventParamsPtr params, 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 5b7ceb07604..6c0ee47de40 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 @@ -15,7 +15,7 @@ #include "content/renderer/service_worker/service_worker_context_client.h" #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/serviceworker/web_service_worker_installed_scripts_manager.h" +#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_installed_scripts_manager.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" @@ -32,15 +32,12 @@ EmbeddedWorkerInstanceClientImpl::WorkerWrapper::~WorkerWrapper() = default; // static void EmbeddedWorkerInstanceClientImpl::Create( - base::TimeTicks blink_initialized_time, scoped_refptr<base::SingleThreadTaskRunner> io_thread_runner, mojom::EmbeddedWorkerInstanceClientRequest request) { // This won't be leaked because the lifetime will be managed internally. // See the class documentation for detail. - EmbeddedWorkerInstanceClientImpl* client = - new EmbeddedWorkerInstanceClientImpl(std::move(io_thread_runner), - std::move(request)); - client->blink_initialized_time_ = blink_initialized_time; + new EmbeddedWorkerInstanceClientImpl(std::move(io_thread_runner), + std::move(request)); } void EmbeddedWorkerInstanceClientImpl::WorkerContextDestroyed() { @@ -57,6 +54,8 @@ void EmbeddedWorkerInstanceClientImpl::StartWorker( DCHECK(!wrapper_); TRACE_EVENT0("ServiceWorker", "EmbeddedWorkerInstanceClientImpl::StartWorker"); + auto start_timing = mojom::EmbeddedWorkerStartTiming::New(); + start_timing->start_worker_received_time = base::TimeTicks::Now(); DCHECK(!params->provider_info->cache_storage || base::FeatureList::IsEnabled( blink::features::kEagerCacheStorageSetupForServiceWorkers)); @@ -64,19 +63,22 @@ void EmbeddedWorkerInstanceClientImpl::StartWorker( std::move(params->provider_info->cache_storage); service_manager::mojom::InterfaceProviderPtrInfo interface_provider = std::move(params->provider_info->interface_provider); + blink::PrivacyPreferences privacy_preferences( + params->renderer_preferences.enable_do_not_track, + params->renderer_preferences.enable_referrers); auto client = std::make_unique<ServiceWorkerContextClient>( params->embedded_worker_id, params->service_worker_version_id, params->scope, params->script_url, !params->installed_scripts_info.is_null(), - std::move(params->dispatcher_request), + std::move(params->renderer_preferences), + 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), RenderThreadImpl::current() ->GetWebMainThreadScheduler() ->DefaultTaskRunner()); - client->set_blink_initialized_time(blink_initialized_time_); - client->set_start_worker_received_time(base::TimeTicks::Now()); // Record UMA to indicate StartWorker is received on renderer. StartWorkerHistogramEnum metric = params->is_installed ? StartWorkerHistogramEnum::RECEIVED_ON_INSTALLED @@ -86,7 +88,8 @@ void EmbeddedWorkerInstanceClientImpl::StartWorker( StartWorkerHistogramEnum::NUM_TYPES); wrapper_ = StartWorkerContext(std::move(params), std::move(client), std::move(cache_storage), - std::move(interface_provider)); + std::move(interface_provider), + std::move(privacy_preferences)); } void EmbeddedWorkerInstanceClientImpl::StopWorker() { @@ -143,7 +146,8 @@ EmbeddedWorkerInstanceClientImpl::StartWorkerContext( mojom::EmbeddedWorkerStartParamsPtr params, std::unique_ptr<ServiceWorkerContextClient> context_client, blink::mojom::CacheStoragePtrInfo cache_storage, - service_manager::mojom::InterfaceProviderPtrInfo interface_provider) { + service_manager::mojom::InterfaceProviderPtrInfo interface_provider, + blink::PrivacyPreferences privacy_preferences) { std::unique_ptr<blink::WebServiceWorkerInstalledScriptsManager> manager; // |installed_scripts_info| is null if scripts should be served by net layer, // when the worker is not installed, or the worker is launched for checking @@ -174,6 +178,7 @@ EmbeddedWorkerInstanceClientImpl::StartWorkerContext( params->pause_after_download ? blink::WebEmbeddedWorkerStartData::kPauseAfterDownload : blink::WebEmbeddedWorkerStartData::kDontPauseAfterDownload; + start_data.privacy_preferences = std::move(privacy_preferences); wrapper->worker()->StartWorkerContext(start_data); return wrapper; 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 e755302db45..d86d3387c6b 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 @@ -13,6 +13,7 @@ #include "content/child/scoped_child_process_reference.h" #include "content/common/service_worker/embedded_worker.mojom.h" #include "mojo/public/cpp/bindings/binding.h" +#include "third_party/blink/public/common/privacy_preferences.h" #include "third_party/blink/public/mojom/service_worker/service_worker_installed_scripts_manager.mojom.h" #include "third_party/blink/public/web/worker_content_settings_proxy.mojom.h" @@ -59,7 +60,6 @@ class EmbeddedWorkerInstanceClientImpl // TODO(shimazu): Create a service worker's execution context by this method // instead of just creating an instance of EmbeddedWorkerInstanceClient. static void Create( - base::TimeTicks blink_initialized_time, scoped_refptr<base::SingleThreadTaskRunner> io_thread_runner, mojom::EmbeddedWorkerInstanceClientRequest request); @@ -103,7 +103,8 @@ class EmbeddedWorkerInstanceClientImpl mojom::EmbeddedWorkerStartParamsPtr params, std::unique_ptr<ServiceWorkerContextClient> context_client, blink::mojom::CacheStoragePtrInfo cache_storage, - service_manager::mojom::InterfaceProviderPtrInfo interface_provider); + service_manager::mojom::InterfaceProviderPtrInfo interface_provider, + blink::PrivacyPreferences privacy_preferences); mojo::Binding<mojom::EmbeddedWorkerInstanceClient> binding_; @@ -114,9 +115,6 @@ class EmbeddedWorkerInstanceClientImpl // nullptr means the worker is not running. std::unique_ptr<WorkerWrapper> wrapper_; - // For UMA. - base::TimeTicks blink_initialized_time_; - scoped_refptr<base::SingleThreadTaskRunner> io_thread_runner_; DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerInstanceClientImpl); 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 31065358f6e..fecbaf9bea3 100644 --- a/chromium/content/renderer/service_worker/service_worker_context_client.cc +++ b/chromium/content/renderer/service_worker/service_worker_context_client.cc @@ -19,9 +19,8 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "base/trace_event/trace_event.h" -#include "content/common/service_worker/service_worker_event_dispatcher.mojom.h" +#include "content/common/service_worker/service_worker.mojom.h" #include "content/common/service_worker/service_worker_messages.h" -#include "content/common/service_worker/service_worker_status_code.h" #include "content/common/service_worker/service_worker_utils.h" #include "content/public/common/content_features.h" #include "content/public/common/push_event_payload.h" @@ -57,6 +56,8 @@ #include "services/network/public/mojom/request_context_frame_type.mojom.h" #include "storage/common/blob_storage/blob_handle.h" #include "third_party/blink/public/common/message_port/message_port_channel.h" +#include "third_party/blink/public/common/service_worker/service_worker_status_code.h" +#include "third_party/blink/public/common/service_worker/service_worker_utils.h" #include "third_party/blink/public/mojom/blob/blob.mojom.h" #include "third_party/blink/public/mojom/blob/blob_registry.mojom.h" #include "third_party/blink/public/mojom/service_worker/service_worker_client.mojom.h" @@ -69,20 +70,21 @@ #include "third_party/blink/public/platform/modules/notifications/web_notification_data.h" #include "third_party/blink/public/platform/modules/payments/web_payment_handler_response.h" #include "third_party/blink/public/platform/modules/payments/web_payment_request_event_data.h" -#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_client_query_options.h" -#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_error.h" -#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_network_provider.h" -#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_request.h" -#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_response.h" +#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_client_query_options.h" +#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_error.h" +#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h" +#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_request.h" +#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_response.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/url_conversion.h" #include "third_party/blink/public/platform/web_blob_registry.h" +#include "third_party/blink/public/platform/web_http_body.h" #include "third_party/blink/public/platform/web_referrer_policy.h" #include "third_party/blink/public/platform/web_security_origin.h" #include "third_party/blink/public/platform/web_string.h" #include "third_party/blink/public/platform/web_url_response.h" -#include "third_party/blink/public/web/modules/serviceworker/web_service_worker_context_client.h" -#include "third_party/blink/public/web/modules/serviceworker/web_service_worker_context_proxy.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" using blink::WebURLRequest; using blink::MessagePortChannel; @@ -117,21 +119,26 @@ class WebServiceWorkerNetworkProviderImpl std::unique_ptr<blink::WebURLLoader> CreateURLLoader( const WebURLRequest& request, - scoped_refptr<base::SingleThreadTaskRunner> task_runner) override { + std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle> + task_runner_handle) override { RenderThreadImpl* render_thread = RenderThreadImpl::current(); if (render_thread && provider_->script_loader_factory() && - ServiceWorkerUtils::IsServicificationEnabled() && + blink::ServiceWorkerUtils::IsServicificationEnabled() && IsScriptRequest(request)) { // TODO(crbug.com/796425): Temporarily wrap the raw // mojom::URLLoaderFactory pointer into SharedURLLoaderFactory. return std::make_unique<WebURLLoaderImpl>( - render_thread->resource_dispatcher(), std::move(task_runner), + render_thread->resource_dispatcher(), std::move(task_runner_handle), base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( provider_->script_loader_factory())); } return nullptr; } + network::mojom::URLLoaderFactory* script_loader_factory() { + return provider_->script_loader_factory(); + } + int ProviderID() const override { return provider_->provider_id(); } private: @@ -208,7 +215,7 @@ void ToWebServiceWorkerRequest(const network::ResourceRequest& request, } // S13nServiceWorker: The body is provided in |request|. else if (request.request_body) { - DCHECK(ServiceWorkerUtils::IsServicificationEnabled()); + DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled()); // |blob_ptrs| should be empty when Network Service is enabled. DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService) || blob_ptrs.empty()); @@ -238,6 +245,8 @@ void ToWebServiceWorkerRequest(const network::ResourceRequest& request, web_request->SetIntegrity( blink::WebString::FromUTF8(request.fetch_integrity)); 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. @@ -267,6 +276,7 @@ void ToWebServiceWorkerRequest(const ServiceWorkerFetchRequest& request, 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. @@ -453,7 +463,7 @@ void DidNavigateClient( // worker thread. struct ServiceWorkerContextClient::WorkerContextData { explicit WorkerContextData(ServiceWorkerContextClient* owner) - : event_dispatcher_binding(owner), + : service_worker_binding(owner), weak_factory(owner), proxy_weak_factory(owner->proxy_) {} @@ -464,10 +474,10 @@ struct ServiceWorkerContextClient::WorkerContextData { // Map from version id to JavaScript ServiceWorker object. std::map<int64_t, WebServiceWorkerImpl*> workers_; - mojo::Binding<mojom::ServiceWorkerEventDispatcher> event_dispatcher_binding; + mojo::Binding<mojom::ServiceWorker> service_worker_binding; // Bound by the first Mojo call received on the service worker thread - // ServiceWorkerEventDispatcher::InitializeGlobalScope(). + // ServiceWorker::InitializeGlobalScope(). blink::mojom::ServiceWorkerHostAssociatedPtr service_worker_host; // Maps for inflight event callbacks. @@ -535,9 +545,10 @@ struct ServiceWorkerContextClient::WorkerContextData { class ServiceWorkerContextClient::NavigationPreloadRequest final : public network::mojom::URLLoaderClient { public: - NavigationPreloadRequest(int fetch_event_id, - const GURL& url, - mojom::FetchEventPreloadHandlePtr preload_handle) + NavigationPreloadRequest( + int fetch_event_id, + const GURL& url, + blink::mojom::FetchEventPreloadHandlePtr preload_handle) : fetch_event_id_(fetch_event_id), url_(url), url_loader_(std::move(preload_handle->url_loader)), @@ -546,10 +557,8 @@ class ServiceWorkerContextClient::NavigationPreloadRequest final ~NavigationPreloadRequest() override {} void OnReceiveResponse( - const network::ResourceResponseHead& response_head, - network::mojom::DownloadedTempFilePtr downloaded_file) override { + const network::ResourceResponseHead& response_head) override { DCHECK(!response_); - DCHECK(!downloaded_file); response_ = std::make_unique<blink::WebURLResponse>(); // TODO(horo): Set report_security_info to true when DevTools is attached. const bool report_security_info = false; @@ -581,11 +590,6 @@ class ServiceWorkerContextClient::NavigationPreloadRequest final 0 /* decoded_body_length */); } - void OnDataDownloaded(int64_t data_length, - int64_t encoded_data_length) override { - NOTREACHED(); - } - void OnUploadProgress(int64_t current_position, int64_t total_size, OnUploadProgressCallback ack_callback) override { @@ -693,22 +697,27 @@ ServiceWorkerContextClient::ServiceWorkerContextClient( int64_t service_worker_version_id, const GURL& service_worker_scope, const GURL& script_url, - bool is_script_streaming, - mojom::ServiceWorkerEventDispatcherRequest dispatcher_request, + bool is_starting_installed_worker, + RendererPreferences renderer_preferences, + mojom::ServiceWorkerRequest service_worker_request, mojom::ControllerServiceWorkerRequest controller_request, mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host, mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info, std::unique_ptr<EmbeddedWorkerInstanceClientImpl> embedded_worker_client, + mojom::EmbeddedWorkerStartTimingPtr start_timing, scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner) : embedded_worker_id_(embedded_worker_id), service_worker_version_id_(service_worker_version_id), service_worker_scope_(service_worker_scope), script_url_(script_url), + is_starting_installed_worker_(is_starting_installed_worker), + renderer_preferences_(std::move(renderer_preferences)), main_thread_task_runner_(std::move(main_thread_task_runner)), proxy_(nullptr), - pending_dispatcher_request_(std::move(dispatcher_request)), + pending_service_worker_request_(std::move(service_worker_request)), pending_controller_request_(std::move(controller_request)), - embedded_worker_client_(std::move(embedded_worker_client)) { + embedded_worker_client_(std::move(embedded_worker_client)), + start_timing_(std::move(start_timing)) { instance_host_ = mojom::ThreadSafeEmbeddedWorkerInstanceHostAssociatedPtr::Create( std::move(instance_host), main_thread_task_runner_); @@ -724,7 +733,8 @@ ServiceWorkerContextClient::ServiceWorkerContextClient( "script_url", script_url_.spec()); TRACE_EVENT_NESTABLE_ASYNC_BEGIN1( "ServiceWorker", "LOAD_SCRIPT", this, "Source", - (is_script_streaming ? "InstalledScriptsManager" : "ResourceLoader")); + (is_starting_installed_worker_ ? "InstalledScriptsManager" + : "ResourceLoader")); } ServiceWorkerContextClient::~ServiceWorkerContextClient() {} @@ -798,7 +808,6 @@ void ServiceWorkerContextClient::WorkerContextFailedToStart() { DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence()); DCHECK(!proxy_); - (*instance_host_)->OnScriptLoadFailed(); (*instance_host_)->OnStopped(); TRACE_EVENT_NESTABLE_ASYNC_END1("ServiceWorker", "ServiceWorkerContextClient", @@ -809,7 +818,8 @@ void ServiceWorkerContextClient::WorkerContextFailedToStart() { } void ServiceWorkerContextClient::WorkerScriptLoaded() { - (*instance_host_)->OnScriptLoaded(); + if (!is_starting_installed_worker_) + (*instance_host_)->OnScriptLoaded(); TRACE_EVENT_NESTABLE_ASYNC_END0("ServiceWorker", "LOAD_SCRIPT", this); TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("ServiceWorker", "START_WORKER_CONTEXT", this); @@ -832,38 +842,48 @@ void ServiceWorkerContextClient::WorkerContextStarted( // willDestroyWorkerContext. context_.reset(new WorkerContextData(this)); - DCHECK(pending_dispatcher_request_.is_pending()); + DCHECK(pending_service_worker_request_.is_pending()); DCHECK(pending_controller_request_.is_pending()); - DCHECK(!context_->event_dispatcher_binding.is_bound()); + DCHECK(!context_->service_worker_binding.is_bound()); DCHECK(!context_->controller_impl); - context_->event_dispatcher_binding.Bind( - std::move(pending_dispatcher_request_)); + context_->service_worker_binding.Bind( + std::move(pending_service_worker_request_)); - if (ServiceWorkerUtils::IsServicificationEnabled()) { + if (blink::ServiceWorkerUtils::IsServicificationEnabled()) { context_->controller_impl = std::make_unique<ControllerServiceWorkerImpl>( std::move(pending_controller_request_), GetWeakPtr()); } - (*instance_host_)->OnThreadStarted(WorkerThread::GetCurrentId()); - TRACE_EVENT_NESTABLE_ASYNC_END0("ServiceWorker", "START_WORKER_CONTEXT", this); TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("ServiceWorker", "EVALUATE_SCRIPT", this); } +void ServiceWorkerContextClient::WillEvaluateClassicScript() { + DCHECK(worker_task_runner_->RunsTasksInCurrentSequence()); + start_timing_->script_evaluation_start_time = base::TimeTicks::Now(); + (*instance_host_)->OnScriptEvaluationStart(); +} + void ServiceWorkerContextClient::DidEvaluateClassicScript(bool success) { DCHECK(worker_task_runner_->RunsTasksInCurrentSequence()); - (*instance_host_)->OnScriptEvaluated(success); + start_timing_->script_evaluation_end_time = base::TimeTicks::Now(); - // Schedule a task to send back WorkerStarted asynchronously, - // so that at the time we send it we can be sure that the - // worker run loop has been started. + blink::mojom::ServiceWorkerStartStatus status = + success ? blink::mojom::ServiceWorkerStartStatus::kNormalCompletion + : blink::mojom::ServiceWorkerStartStatus::kAbruptCompletion; + + // Schedule a task to send back WorkerStarted asynchronously, so we can be + // sure that the worker is really started. + // TODO(falken): Is this really needed? Probably if kNormalCompletion, the + // worker is definitely running so we can SendStartWorker immediately. worker_task_runner_->PostTask( FROM_HERE, base::BindOnce(&ServiceWorkerContextClient::SendWorkerStarted, - GetWeakPtr())); + GetWeakPtr(), status)); TRACE_EVENT_NESTABLE_ASYNC_END1("ServiceWorker", "EVALUATE_SCRIPT", this, - "Status", success ? "Success" : "Failure"); + "Status", + ServiceWorkerUtils::MojoEnumToString(status)); } void ServiceWorkerContextClient::DidInitializeWorkerContext( @@ -951,6 +971,10 @@ 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)); RunEventCallback(&context_->activate_event_callbacks, context_->timeout_timer.get(), request_id, status, base::Time::FromDoubleT(event_dispatch_time)); @@ -960,6 +984,10 @@ 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)); RunEventCallback(&context_->background_fetch_abort_event_callbacks, context_->timeout_timer.get(), request_id, status, base::Time::FromDoubleT(event_dispatch_time)); @@ -969,6 +997,10 @@ 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)); RunEventCallback(&context_->background_fetch_click_event_callbacks, context_->timeout_timer.get(), request_id, status, base::Time::FromDoubleT(event_dispatch_time)); @@ -978,6 +1010,10 @@ 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)); RunEventCallback(&context_->background_fetch_fail_event_callbacks, context_->timeout_timer.get(), request_id, status, base::Time::FromDoubleT(event_dispatch_time)); @@ -987,6 +1023,10 @@ void ServiceWorkerContextClient::DidHandleBackgroundFetchedEvent( int request_id, blink::mojom::ServiceWorkerEventStatus status, double event_dispatch_time) { + TRACE_EVENT2("ServiceWorker", + "ServiceWorkerContextClient::DidHandleBackgroundFetchedEvent", + "event_id", request_id, "status", + ServiceWorkerUtils::MojoEnumToString(status)); RunEventCallback(&context_->background_fetched_event_callbacks, context_->timeout_timer.get(), request_id, status, base::Time::FromDoubleT(event_dispatch_time)); @@ -996,6 +1036,10 @@ 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)); RunEventCallback(&context_->cookie_change_event_callbacks, context_->timeout_timer.get(), request_id, status, base::Time::FromDoubleT(event_dispatch_time)); @@ -1005,6 +1049,10 @@ 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)); RunEventCallback(&context_->message_event_callbacks, context_->timeout_timer.get(), request_id, status, base::Time::FromDoubleT(event_dispatch_time)); @@ -1014,6 +1062,10 @@ 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)); RunEventCallback(&context_->install_event_callbacks, context_->timeout_timer.get(), event_id, status, proxy_->HasFetchEventHandler(), @@ -1023,6 +1075,9 @@ void ServiceWorkerContextClient::DidHandleInstallEvent( void ServiceWorkerContextClient::RespondToFetchEventWithNoResponse( int fetch_event_id, double event_dispatch_time) { + TRACE_EVENT1("ServiceWorker", + "ServiceWorkerContextClient::RespondToFetchEventWithNoResponse", + "event_id", fetch_event_id); DCHECK(base::ContainsKey(context_->fetch_response_callbacks, fetch_event_id)); const mojom::ServiceWorkerFetchResponseCallbackPtr& response_callback = context_->fetch_response_callbacks[fetch_event_id]; @@ -1035,6 +1090,9 @@ 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); DCHECK(base::ContainsKey(context_->fetch_response_callbacks, fetch_event_id)); ServiceWorkerResponse response( GetServiceWorkerResponseFromWebResponse(web_response)); @@ -1063,6 +1121,10 @@ void ServiceWorkerContextClient::RespondToFetchEventWithResponseStream( const blink::WebServiceWorkerResponse& web_response, blink::WebServiceWorkerStreamHandle* web_body_as_stream, double event_dispatch_time) { + TRACE_EVENT1( + "ServiceWorker", + "ServiceWorkerContextClient::RespondToFetchEventWithResponseStream", + "event_id", fetch_event_id); DCHECK(base::ContainsKey(context_->fetch_response_callbacks, fetch_event_id)); ServiceWorkerResponse response( GetServiceWorkerResponseFromWebResponse(web_response)); @@ -1090,9 +1152,10 @@ 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_EVENT1("ServiceWorker", + TRACE_EVENT2("ServiceWorker", "ServiceWorkerContextClient::DidHandleFetchEvent", "event_id", - event_id); + event_id, "status", + ServiceWorkerUtils::MojoEnumToString(status)); if (RunEventCallback(&context_->fetch_event_callbacks, context_->timeout_timer.get(), event_id, status, base::Time::FromDoubleT(event_dispatch_time))) { @@ -1104,6 +1167,10 @@ 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)); RunEventCallback(&context_->notification_click_event_callbacks, context_->timeout_timer.get(), request_id, status, base::Time::FromDoubleT(event_dispatch_time)); @@ -1113,6 +1180,10 @@ 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)); RunEventCallback(&context_->notification_close_event_callbacks, context_->timeout_timer.get(), request_id, status, base::Time::FromDoubleT(event_dispatch_time)); @@ -1122,6 +1193,10 @@ 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)); RunEventCallback(&context_->push_event_callbacks, context_->timeout_timer.get(), request_id, status, base::Time::FromDoubleT(event_dispatch_time)); @@ -1131,6 +1206,10 @@ 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)); RunEventCallback(&context_->sync_event_callbacks, context_->timeout_timer.get(), request_id, status, base::Time::FromDoubleT(event_dispatch_time)); @@ -1140,6 +1219,9 @@ void ServiceWorkerContextClient::RespondToAbortPaymentEvent( int event_id, bool payment_aborted, double dispatch_event_time) { + TRACE_EVENT1("ServiceWorker", + "ServiceWorkerContextClient::RespondToAbortPaymentEvent", + "event_id", event_id); DCHECK(base::ContainsKey(context_->abort_payment_result_callbacks, event_id)); const payments::mojom::PaymentHandlerResponseCallbackPtr& result_callback = context_->abort_payment_result_callbacks[event_id]; @@ -1152,6 +1234,10 @@ 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)); if (RunEventCallback(&context_->abort_payment_event_callbacks, context_->timeout_timer.get(), event_id, status, base::Time::FromDoubleT(dispatch_event_time))) { @@ -1163,6 +1249,9 @@ void ServiceWorkerContextClient::RespondToCanMakePaymentEvent( int event_id, bool can_make_payment, double dispatch_event_time) { + TRACE_EVENT1("ServiceWorker", + "ServiceWorkerContextClient::RespondToCanMakePaymentEvent", + "event_id", event_id); DCHECK( base::ContainsKey(context_->can_make_payment_result_callbacks, event_id)); const payments::mojom::PaymentHandlerResponseCallbackPtr& result_callback = @@ -1176,6 +1265,10 @@ 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)); if (RunEventCallback(&context_->can_make_payment_event_callbacks, context_->timeout_timer.get(), event_id, status, base::Time::FromDoubleT(dispatch_event_time))) { @@ -1187,6 +1280,9 @@ 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); DCHECK(base::ContainsKey(context_->payment_response_callbacks, payment_request_id)); const payments::mojom::PaymentHandlerResponseCallbackPtr& response_callback = @@ -1204,6 +1300,10 @@ 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)); if (RunEventCallback(&context_->payment_request_event_callbacks, context_->timeout_timer.get(), payment_request_id, status, base::Time::FromDoubleT(event_dispatch_time))) { @@ -1219,7 +1319,8 @@ ServiceWorkerContextClient::CreateServiceWorkerNetworkProvider() { } std::unique_ptr<blink::WebWorkerFetchContext> -ServiceWorkerContextClient::CreateServiceWorkerFetchContext() { +ServiceWorkerContextClient::CreateServiceWorkerFetchContext( + blink::WebServiceWorkerNetworkProvider* provider) { DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence()); scoped_refptr<ChildURLLoaderFactoryBundle> url_loader_factory_bundle = @@ -1227,9 +1328,22 @@ ServiceWorkerContextClient::CreateServiceWorkerFetchContext() { ->blink_platform_impl() ->CreateDefaultURLLoaderFactoryBundle(); DCHECK(url_loader_factory_bundle); + + std::unique_ptr<network::SharedURLLoaderFactoryInfo> + script_loader_factory_info; + if (blink::ServiceWorkerUtils::IsServicificationEnabled()) { + // TODO(crbug.com/796425): Temporarily wrap the raw + // mojom::URLLoaderFactory pointer into SharedURLLoaderFactory. + script_loader_factory_info = + base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( + static_cast<WebServiceWorkerNetworkProviderImpl*>(provider) + ->script_loader_factory()) + ->Clone(); + } + return std::make_unique<ServiceWorkerFetchContextImpl>( - script_url_, url_loader_factory_bundle->Clone(), - provider_context_->provider_id(), + renderer_preferences_, script_url_, url_loader_factory_bundle->Clone(), + std::move(script_loader_factory_info), provider_context_->provider_id(), GetContentClient()->renderer()->CreateURLLoaderThrottleProvider( URLLoaderThrottleProviderType::kWorker), GetContentClient() @@ -1286,9 +1400,13 @@ void ServiceWorkerContextClient::Claim( } void ServiceWorkerContextClient::DispatchOrQueueFetchEvent( - mojom::DispatchFetchEventParamsPtr params, + blink::mojom::DispatchFetchEventParamsPtr params, mojom::ServiceWorkerFetchResponseCallbackPtr response_callback, DispatchFetchEventCallback callback) { + TRACE_EVENT2("ServiceWorker", + "ServiceWorkerContextClient::DispatchOrQueueFetchEvent", "url", + params->request.url.spec(), "queued", + RequestedTermination() ? "true" : "false"); if (RequestedTermination()) { context_->timeout_timer->PushPendingTask(base::BindOnce( &ServiceWorkerContextClient::DispatchFetchEvent, GetWeakPtr(), @@ -1304,11 +1422,11 @@ void ServiceWorkerContextClient::DispatchSyncEvent( bool last_chance, base::TimeDelta timeout, DispatchSyncEventCallback callback) { - TRACE_EVENT0("ServiceWorker", - "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); // TODO(jkarlin): Make this blink::WebString::FromUTF8Lenient once // https://crrev.com/1768063002/ lands. @@ -1317,33 +1435,33 @@ void ServiceWorkerContextClient::DispatchSyncEvent( } void ServiceWorkerContextClient::DispatchAbortPaymentEvent( - int /* event_id */, // TODO(shimazu): Remove this. payments::mojom::PaymentHandlerResponseCallbackPtr response_callback, DispatchAbortPaymentEventCallback callback) { - TRACE_EVENT0("ServiceWorker", - "ServiceWorkerContextClient::DispatchAbortPaymentEvent"); int event_id = context_->timeout_timer->StartEvent( CreateAbortCallback(&context_->abort_payment_event_callbacks)); context_->abort_payment_event_callbacks.emplace(event_id, std::move(callback)); context_->abort_payment_result_callbacks.emplace( event_id, std::move(response_callback)); + TRACE_EVENT1("ServiceWorker", + "ServiceWorkerContextClient::DispatchAbortPaymentEvent", + "event_id", event_id); proxy_->DispatchAbortPaymentEvent(event_id); } void ServiceWorkerContextClient::DispatchCanMakePaymentEvent( - int /* event_id */, // TODO(shimazu): Remove this. payments::mojom::CanMakePaymentEventDataPtr eventData, payments::mojom::PaymentHandlerResponseCallbackPtr response_callback, DispatchCanMakePaymentEventCallback callback) { - TRACE_EVENT0("ServiceWorker", - "ServiceWorkerContextClient::DispatchCanMakePaymentEvent"); int event_id = context_->timeout_timer->StartEvent( CreateAbortCallback(&context_->can_make_payment_event_callbacks)); context_->can_make_payment_event_callbacks.emplace(event_id, std::move(callback)); context_->can_make_payment_result_callbacks.emplace( event_id, std::move(response_callback)); + TRACE_EVENT1("ServiceWorker", + "ServiceWorkerContextClient::DispatchCanMakePaymentEvent", + "event_id", event_id); blink::WebCanMakePaymentEventData webEventData = mojo::ConvertTo<blink::WebCanMakePaymentEventData>(std::move(eventData)); @@ -1351,31 +1469,31 @@ void ServiceWorkerContextClient::DispatchCanMakePaymentEvent( } void ServiceWorkerContextClient::DispatchPaymentRequestEvent( - int /* payment_request_id */, // TODO(shimazu): Remove this. payments::mojom::PaymentRequestEventDataPtr eventData, payments::mojom::PaymentHandlerResponseCallbackPtr response_callback, DispatchPaymentRequestEventCallback callback) { - TRACE_EVENT0("ServiceWorker", - "ServiceWorkerContextClient::DispatchPaymentRequestEvent"); int event_id = context_->timeout_timer->StartEvent( CreateAbortCallback(&context_->payment_request_event_callbacks)); context_->payment_request_event_callbacks.emplace(event_id, std::move(callback)); context_->payment_response_callbacks.emplace(event_id, std::move(response_callback)); + TRACE_EVENT1("ServiceWorker", + "ServiceWorkerContextClient::DispatchPaymentRequestEvent", + "event_id", event_id); blink::WebPaymentRequestEventData webEventData = mojo::ConvertTo<blink::WebPaymentRequestEventData>(std::move(eventData)); proxy_->DispatchPaymentRequestEvent(event_id, webEventData); } -void ServiceWorkerContextClient::SendWorkerStarted() { +void ServiceWorkerContextClient::SendWorkerStarted( + blink::mojom::ServiceWorkerStartStatus status) { DCHECK(worker_task_runner_->RunsTasksInCurrentSequence()); - mojom::EmbeddedWorkerStartTimingPtr timing = - mojom::EmbeddedWorkerStartTiming::New(); - timing->start_worker_received_time = start_worker_received_time_; - timing->blink_initialized_time = blink_initialized_time_; - (*instance_host_)->OnStarted(std::move(timing)); + + (*instance_host_) + ->OnStarted(status, WorkerThread::GetCurrentId(), + std::move(start_timing_)); TRACE_EVENT_NESTABLE_ASYNC_END0("ServiceWorker", "ServiceWorkerContextClient", this); @@ -1387,11 +1505,12 @@ void ServiceWorkerContextClient::SendWorkerStarted() { void ServiceWorkerContextClient::DispatchActivateEvent( DispatchActivateEventCallback callback) { - TRACE_EVENT0("ServiceWorker", - "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); proxy_->DispatchActivateEvent(request_id); } @@ -1400,12 +1519,13 @@ void ServiceWorkerContextClient::DispatchBackgroundFetchAbortEvent( const std::string& unique_id, const std::vector<BackgroundFetchSettledFetch>& fetches, DispatchBackgroundFetchAbortEventCallback callback) { - TRACE_EVENT0("ServiceWorker", - "ServiceWorkerContextClient::DispatchBackgroundFetchAbortEvent"); 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()); @@ -1423,12 +1543,13 @@ void ServiceWorkerContextClient::DispatchBackgroundFetchClickEvent( const std::string& developer_id, mojom::BackgroundFetchState state, DispatchBackgroundFetchClickEventCallback callback) { - TRACE_EVENT0("ServiceWorker", - "ServiceWorkerContextClient::DispatchBackgroundFetchClickEvent"); 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); // TODO(peter): Use typemap when this is moved to blink-side. blink::WebServiceWorkerContextProxy::BackgroundFetchState web_state = @@ -1443,12 +1564,13 @@ void ServiceWorkerContextClient::DispatchBackgroundFetchFailEvent( const std::string& unique_id, const std::vector<BackgroundFetchSettledFetch>& fetches, DispatchBackgroundFetchFailEventCallback callback) { - TRACE_EVENT0("ServiceWorker", - "ServiceWorkerContextClient::DispatchBackgroundFetchFailEvent"); 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()); @@ -1467,12 +1589,13 @@ void ServiceWorkerContextClient::DispatchBackgroundFetchedEvent( const std::string& unique_id, const std::vector<BackgroundFetchSettledFetch>& fetches, DispatchBackgroundFetchedEventCallback callback) { - TRACE_EVENT0("ServiceWorker", - "ServiceWorkerContextClient::DispatchBackgroundFetchedEvent"); 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()); @@ -1507,23 +1630,25 @@ void ServiceWorkerContextClient::InitializeGlobalScope( void ServiceWorkerContextClient::DispatchInstallEvent( DispatchInstallEventCallback callback) { - TRACE_EVENT0("ServiceWorker", - "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); + proxy_->DispatchInstallEvent(event_id); } void ServiceWorkerContextClient::DispatchExtendableMessageEvent( mojom::ExtendableMessageEventPtr event, DispatchExtendableMessageEventCallback callback) { - TRACE_EVENT0("ServiceWorker", - "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_EVENT1("ServiceWorker", + "ServiceWorkerContextClient::DispatchExtendableMessageEvent", + "request_id", request_id); if (event->source_info_for_client) { blink::WebServiceWorkerClientInfo web_client = @@ -1545,7 +1670,7 @@ void ServiceWorkerContextClient::DispatchExtendableMessageEvent( // S13nServiceWorker void ServiceWorkerContextClient::DispatchFetchEvent( - mojom::DispatchFetchEventParamsPtr params, + blink::mojom::DispatchFetchEventParamsPtr params, mojom::ServiceWorkerFetchResponseCallbackPtr response_callback, DispatchFetchEventCallback callback) { int event_id = context_->timeout_timer->StartEvent( @@ -1556,9 +1681,9 @@ void ServiceWorkerContextClient::DispatchFetchEvent( // This TRACE_EVENT is used for perf benchmark to confirm if all of fetch // events have completed. (crbug.com/736697) - TRACE_EVENT1("ServiceWorker", + TRACE_EVENT2("ServiceWorker", "ServiceWorkerContextClient::DispatchFetchEvent", "event_id", - event_id); + event_id, "url", params->request.url.spec()); // Set up for navigation preload (FetchEvent#preloadResponse) if needed. const bool navigation_preload_sent = !!params->preload_handle; @@ -1583,13 +1708,13 @@ void ServiceWorkerContextClient::DispatchNotificationClickEvent( int action_index, const base::Optional<base::string16>& reply, DispatchNotificationClickEventCallback callback) { - TRACE_EVENT0("ServiceWorker", - "ServiceWorkerContextClient::DispatchNotificationClickEvent"); - int request_id = context_->timeout_timer->StartEvent( CreateAbortCallback(&context_->notification_click_event_callbacks)); context_->notification_click_event_callbacks.emplace(request_id, std::move(callback)); + TRACE_EVENT1("ServiceWorker", + "ServiceWorkerContextClient::DispatchNotificationClickEvent", + "request_id", request_id); blink::WebString web_reply; if (reply) @@ -1604,13 +1729,13 @@ void ServiceWorkerContextClient::DispatchNotificationCloseEvent( const std::string& notification_id, const PlatformNotificationData& notification_data, DispatchNotificationCloseEventCallback callback) { - TRACE_EVENT0("ServiceWorker", - "ServiceWorkerContextClient::DispatchNotificationCloseEvent"); - int request_id = context_->timeout_timer->StartEvent( CreateAbortCallback(&context_->notification_close_event_callbacks)); context_->notification_close_event_callbacks.emplace(request_id, std::move(callback)); + TRACE_EVENT1("ServiceWorker", + "ServiceWorkerContextClient::DispatchNotificationCloseEvent", + "request_id", request_id); proxy_->DispatchNotificationCloseEvent( request_id, blink::WebString::FromUTF8(notification_id), ToWebNotificationData(notification_data)); @@ -1619,13 +1744,12 @@ void ServiceWorkerContextClient::DispatchNotificationCloseEvent( void ServiceWorkerContextClient::DispatchPushEvent( const PushEventPayload& payload, DispatchPushEventCallback callback) { - TRACE_EVENT0("ServiceWorker", - "ServiceWorkerContextClient::DispatchPushEvent"); - 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); // Only set data to be a valid string if the payload had decrypted data. blink::WebString data; @@ -1638,21 +1762,29 @@ void ServiceWorkerContextClient::DispatchCookieChangeEvent( const net::CanonicalCookie& cookie, ::network::mojom::CookieChangeCause cause, DispatchCookieChangeEventCallback callback) { - TRACE_EVENT0("ServiceWorker", - "ServiceWorkerContextClient::DispatchCookieChangeEvent"); - int request_id = context_->timeout_timer->StartEvent( CreateAbortCallback(&context_->cookie_change_event_callbacks)); context_->cookie_change_event_callbacks.emplace(request_id, std::move(callback)); - - // TODO(pwnall): Map |cause| to a blink enum. Currently, a cookie overwrite - // shows up as delete + insert. - bool is_cookie_delete = - cause != ::network::mojom::CookieChangeCause::INSERTED; - proxy_->DispatchCookieChangeEvent( - request_id, blink::WebString::FromUTF8(cookie.Name()), - blink::WebString::FromUTF8(cookie.Value()), is_cookie_delete); + TRACE_EVENT1("ServiceWorker", + "ServiceWorkerContextClient::DispatchCookieChangeEvent", + "request_id", request_id); + + // After onion-souping, the conversion below will be done by mojo directly. + DCHECK(!cookie.IsHttpOnly()); + base::Optional<blink::WebCanonicalCookie> web_cookie_opt = + blink::WebCanonicalCookie::Create( + blink::WebString::FromUTF8(cookie.Name()), + blink::WebString::FromUTF8(cookie.Value()), + blink::WebString::FromUTF8(cookie.Domain()), + blink::WebString::FromUTF8(cookie.Path()), cookie.CreationDate(), + cookie.ExpiryDate(), cookie.LastAccessDate(), cookie.IsSecure(), + false /* cookie.IsHttpOnly() */, + static_cast<network::mojom::CookieSameSite>(cookie.SameSite()), + static_cast<network::mojom::CookiePriority>(cookie.Priority())); + DCHECK(web_cookie_opt.has_value()); + + proxy_->DispatchCookieChangeEvent(request_id, web_cookie_opt.value(), cause); } void ServiceWorkerContextClient::Ping(PingCallback callback) { @@ -1660,7 +1792,7 @@ void ServiceWorkerContextClient::Ping(PingCallback callback) { } void ServiceWorkerContextClient::SetIdleTimerDelayToZero() { - DCHECK(ServiceWorkerUtils::IsServicificationEnabled()); + DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled()); DCHECK(context_); DCHECK(context_->timeout_timer); context_->timeout_timer->SetIdleTimerDelayToZero(); @@ -1670,6 +1802,9 @@ 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); proxy_->OnNavigationPreloadResponse(fetch_event_id, std::move(response), std::move(data_consumer_handle)); } @@ -1677,6 +1812,9 @@ 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); proxy_->OnNavigationPreloadError(fetch_event_id, std::move(error)); context_->preload_requests.Remove(fetch_event_id); } @@ -1687,6 +1825,9 @@ 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); proxy_->OnNavigationPreloadComplete(fetch_event_id, completion_time, encoded_data_length, encoded_body_length, decoded_body_length); @@ -1696,7 +1837,7 @@ void ServiceWorkerContextClient::OnNavigationPreloadComplete( void ServiceWorkerContextClient::SetupNavigationPreload( int fetch_event_id, const GURL& url, - mojom::FetchEventPreloadHandlePtr preload_handle) { + blink::mojom::FetchEventPreloadHandlePtr preload_handle) { auto preload_request = std::make_unique<NavigationPreloadRequest>( fetch_event_id, url, std::move(preload_handle)); context_->preload_requests.AddWithID(std::move(preload_request), 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 61085729f81..b48aa9a8847 100644 --- a/chromium/content/renderer/service_worker/service_worker_context_client.h +++ b/chromium/content/renderer/service_worker/service_worker_context_client.h @@ -21,21 +21,21 @@ #include "base/time/time.h" #include "content/common/service_worker/controller_service_worker.mojom.h" #include "content/common/service_worker/embedded_worker.mojom.h" -#include "content/common/service_worker/service_worker_event_dispatcher.mojom.h" +#include "content/common/service_worker/service_worker.mojom.h" #include "content/common/service_worker/service_worker_provider.mojom.h" -#include "content/common/service_worker/service_worker_status_code.h" #include "content/common/service_worker/service_worker_types.h" #include "ipc/ipc_listener.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/mojom/blob/blob_registry.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/serviceworker/web_service_worker_error.h" -#include "third_party/blink/public/web/modules/serviceworker/web_service_worker_context_client.h" -#include "third_party/blink/public/web/modules/serviceworker/web_service_worker_context_proxy.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" #include "v8/include/v8.h" namespace base { @@ -73,38 +73,35 @@ class WebWorkerFetchContext; // called on the worker thread. class CONTENT_EXPORT ServiceWorkerContextClient : public blink::WebServiceWorkerContextClient, - public mojom::ServiceWorkerEventDispatcher { + public mojom::ServiceWorker { public: // Returns a thread-specific client instance. This does NOT create a // new instance. static ServiceWorkerContextClient* ThreadSpecificInstance(); // Called on the main thread. - // |is_script_streaming| is true if the script is already installed and will - // be streamed from the browser process. + // |is_starting_installed_worker| is true if the script is already installed + // and will be streamed from the browser process. + // + // |start_timing| should be initially populated with + // |start_worker_received_time|. This instance will fill in the rest during + // startup. ServiceWorkerContextClient( int embedded_worker_id, int64_t service_worker_version_id, const GURL& service_worker_scope, const GURL& script_url, - bool is_script_streaming, - mojom::ServiceWorkerEventDispatcherRequest dispatcher_request, + bool is_starting_installed_worker, + RendererPreferences renderer_preferences, + mojom::ServiceWorkerRequest service_worker_request, mojom::ControllerServiceWorkerRequest controller_request, mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host, mojom::ServiceWorkerProviderInfoForStartWorkerPtr provider_info, std::unique_ptr<EmbeddedWorkerInstanceClientImpl> embedded_worker_client, + mojom::EmbeddedWorkerStartTimingPtr start_timing, scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner); ~ServiceWorkerContextClient() override; - // Called on the main thread. - void set_blink_initialized_time(base::TimeTicks blink_initialized_time) { - blink_initialized_time_ = blink_initialized_time; - } - void set_start_worker_received_time( - base::TimeTicks start_worker_received_time) { - start_worker_received_time_ = start_worker_received_time; - } - // Returns the service worker object described by |info|. Creates a new object // if needed, or else returns the existing one. scoped_refptr<WebServiceWorkerImpl> GetOrCreateServiceWorkerObject( @@ -132,6 +129,7 @@ class CONTENT_EXPORT ServiceWorkerContextClient void WorkerScriptLoaded() override; void WorkerContextStarted( blink::WebServiceWorkerContextProxy* proxy) override; + void WillEvaluateClassicScript() override; void DidEvaluateClassicScript(bool success) override; void DidInitializeWorkerContext(v8::Local<v8::Context> context) override; void WillDestroyWorkerContext(v8::Local<v8::Context> context) override; @@ -225,8 +223,8 @@ class CONTENT_EXPORT ServiceWorkerContextClient double dispatch_event_time) override; std::unique_ptr<blink::WebServiceWorkerNetworkProvider> CreateServiceWorkerNetworkProvider() override; - std::unique_ptr<blink::WebWorkerFetchContext> - CreateServiceWorkerFetchContext() override; + std::unique_ptr<blink::WebWorkerFetchContext> CreateServiceWorkerFetchContext( + blink::WebServiceWorkerNetworkProvider*) override; std::unique_ptr<blink::WebServiceWorkerProvider> CreateServiceWorkerProvider() override; void PostMessageToClient(const blink::WebString& uuid, @@ -251,7 +249,7 @@ class CONTENT_EXPORT ServiceWorkerContextClient // This method needs to be used only if the event comes directly from a // client, which means it is coming through the ControllerServiceWorkerImpl. void DispatchOrQueueFetchEvent( - mojom::DispatchFetchEventParamsPtr params, + blink::mojom::DispatchFetchEventParamsPtr params, mojom::ServiceWorkerFetchResponseCallbackPtr response_callback, DispatchFetchEventCallback callback); @@ -274,9 +272,9 @@ class CONTENT_EXPORT ServiceWorkerContextClient // in the browser process. int GetRoutingID() const { return embedded_worker_id_; } - void SendWorkerStarted(); + void SendWorkerStarted(blink::mojom::ServiceWorkerStartStatus status); - // Implements mojom::ServiceWorkerEventDispatcher. + // Implements mojom::ServiceWorker. void InitializeGlobalScope( blink::mojom::ServiceWorkerHostAssociatedPtrInfo service_worker_host, blink::mojom::ServiceWorkerRegistrationObjectInfoPtr registration_info) @@ -307,7 +305,7 @@ class CONTENT_EXPORT ServiceWorkerContextClient mojom::ExtendableMessageEventPtr event, DispatchExtendableMessageEventCallback callback) override; void DispatchFetchEvent( - mojom::DispatchFetchEventParamsPtr params, + blink::mojom::DispatchFetchEventParamsPtr params, mojom::ServiceWorkerFetchResponseCallbackPtr response_callback, DispatchFetchEventCallback callback) override; void DispatchNotificationClickEvent( @@ -327,16 +325,13 @@ class CONTENT_EXPORT ServiceWorkerContextClient base::TimeDelta timeout, DispatchSyncEventCallback callback) override; void DispatchAbortPaymentEvent( - int payment_request_id, payments::mojom::PaymentHandlerResponseCallbackPtr response_callback, DispatchAbortPaymentEventCallback callback) override; void DispatchCanMakePaymentEvent( - int payment_request_id, payments::mojom::CanMakePaymentEventDataPtr event_data, payments::mojom::PaymentHandlerResponseCallbackPtr response_callback, DispatchCanMakePaymentEventCallback callback) override; void DispatchPaymentRequestEvent( - int payment_request_id, payments::mojom::PaymentRequestEventDataPtr event_data, payments::mojom::PaymentHandlerResponseCallbackPtr response_callback, DispatchPaymentRequestEventCallback callback) override; @@ -384,9 +379,10 @@ class CONTENT_EXPORT ServiceWorkerContextClient int fetch_event_id, std::unique_ptr<blink::WebServiceWorkerError> error); - void SetupNavigationPreload(int fetch_event_id, - const GURL& url, - mojom::FetchEventPreloadHandlePtr preload_handle); + void SetupNavigationPreload( + int fetch_event_id, + const GURL& url, + blink::mojom::FetchEventPreloadHandlePtr preload_handle); // Called by ServiceWorkerTimeoutTimer when a certain time has passed since // the last task finished. @@ -411,6 +407,11 @@ class CONTENT_EXPORT ServiceWorkerContextClient const int64_t service_worker_version_id_; const GURL service_worker_scope_; const GURL script_url_; + // True if this service worker was already installed at worker + // startup time. + const bool is_starting_installed_worker_; + + RendererPreferences renderer_preferences_; scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_; scoped_refptr<base::TaskRunner> worker_task_runner_; @@ -421,7 +422,7 @@ class CONTENT_EXPORT ServiceWorkerContextClient blink::WebServiceWorkerContextProxy* proxy_; // These Mojo objects are bound on the worker thread. - mojom::ServiceWorkerEventDispatcherRequest pending_dispatcher_request_; + mojom::ServiceWorkerRequest pending_service_worker_request_; mojom::ControllerServiceWorkerRequest pending_controller_request_; // This is bound on the main thread. @@ -441,8 +442,9 @@ class CONTENT_EXPORT ServiceWorkerContextClient // destructed on the worker thread in willDestroyWorkerContext. std::unique_ptr<WorkerContextData> context_; - base::TimeTicks blink_initialized_time_; - base::TimeTicks start_worker_received_time_; + // Accessed on the worker thread. Passed to the browser process after worker + // startup completes. + mojom::EmbeddedWorkerStartTimingPtr start_timing_; 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 d9fbfee4759..fbd3fceab5d 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,7 +14,6 @@ #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_utils.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/web_service_worker_impl.h" @@ -25,18 +24,19 @@ #include "services/network/public/cpp/resource_request.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/message_port/message_port_channel.h" +#include "third_party/blink/public/common/service_worker/service_worker_utils.h" #include "third_party/blink/public/mojom/service_worker/service_worker_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/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/serviceworker/web_service_worker_clients_info.h" -#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_error.h" -#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_request.h" +#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_clients_info.h" +#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_error.h" +#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_request.h" #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" #include "third_party/blink/public/platform/web_data_consumer_handle.h" #include "third_party/blink/public/platform/web_string.h" #include "third_party/blink/public/platform/web_url_response.h" -#include "third_party/blink/public/web/modules/serviceworker/web_service_worker_context_proxy.h" +#include "third_party/blink/public/web/modules/service_worker/web_service_worker_context_proxy.h" namespace content { @@ -45,7 +45,7 @@ namespace { // Pipes connected to the context client. struct ContextClientPipes { // From the browser to ServiceWorkerContextClient. - mojom::ServiceWorkerEventDispatcherPtr event_dispatcher; + mojom::ServiceWorkerPtr service_worker; mojom::ControllerServiceWorkerPtr controller; blink::mojom::ServiceWorkerRegistrationObjectAssociatedPtr registration; @@ -105,10 +105,10 @@ class MockWebServiceWorkerContextProxy override { NOTREACHED(); } - void DispatchCookieChangeEvent(int event_id, - const blink::WebString& name, - const blink::WebString& value, - bool is_deleted) override { + void DispatchCookieChangeEvent( + int event_id, + const blink::WebCanonicalCookie& cookie, + ::network::mojom::CookieChangeCause change_cause) override { NOTREACHED(); } void DispatchExtendableMessageEvent( @@ -245,11 +245,12 @@ class ServiceWorkerContextClientTest : public testing::Test { ServiceWorkerContextClient::ResetThreadSpecificInstanceForTesting(); // Unregister this thread from worker threads. WorkerThreadRegistry::Instance()->WillStopCurrentWorkerThread(); + task_runner_->RunUntilIdle(); } void EnableServicification() { feature_list_.InitWithFeatures({network::features::kNetworkService}, {}); - ASSERT_TRUE(ServiceWorkerUtils::IsServicificationEnabled()); + ASSERT_TRUE(blink::ServiceWorkerUtils::IsServicificationEnabled()); } // Creates an empty struct to initialize ServiceWorkerProviderContext. @@ -264,8 +265,7 @@ class ServiceWorkerContextClientTest : public testing::Test { std::unique_ptr<ServiceWorkerContextClient> CreateContextClient( ContextClientPipes* out_pipes, blink::WebServiceWorkerContextProxy* proxy) { - auto event_dispatcher_request = - mojo::MakeRequest(&out_pipes->event_dispatcher); + auto service_worker_request = mojo::MakeRequest(&out_pipes->service_worker); auto controller_request = mojo::MakeRequest(&out_pipes->controller); mojom::EmbeddedWorkerInstanceHostAssociatedPtr embedded_worker_host_ptr; out_pipes->embedded_worker_host_request = @@ -276,9 +276,11 @@ class ServiceWorkerContextClientTest : public testing::Test { std::make_unique<ServiceWorkerContextClient>( 1 /* embedded_worker_id */, 1 /* service_worker_version_id */, kScope, kScript, false /* is_script_streaming */, - std::move(event_dispatcher_request), std::move(controller_request), + RendererPreferences(), std::move(service_worker_request), + std::move(controller_request), embedded_worker_host_ptr.PassInterface(), CreateProviderInfo(), nullptr /* embedded_worker_client */, + mojom::EmbeddedWorkerStartTiming::New(), blink::scheduler::GetSingleThreadTaskRunnerForTesting()); context_client->WorkerContextStarted(proxy); @@ -295,7 +297,7 @@ class ServiceWorkerContextClientTest : public testing::Test { out_pipes->registration_host_request = mojo::MakeRequest(®istration_info->host_ptr_info); registration_info->request = mojo::MakeRequest(&out_pipes->registration); - out_pipes->event_dispatcher->InitializeGlobalScope( + out_pipes->service_worker->InitializeGlobalScope( std::move(service_worker_host), std::move(registration_info)); task_runner()->RunUntilIdle(); return context_client; @@ -323,7 +325,7 @@ TEST_F(ServiceWorkerContextClientTest, Ping) { CreateContextClient(&pipes, &mock_proxy); bool is_called = false; - pipes.event_dispatcher->Ping(CreateCallbackWithCalledFlag(&is_called)); + pipes.service_worker->Ping(CreateCallbackWithCalledFlag(&is_called)); task_runner()->RunUntilIdle(); EXPECT_TRUE(is_called); } @@ -343,9 +345,9 @@ TEST_F(ServiceWorkerContextClientTest, DispatchFetchEvent) { request->url = expected_url; mojom::ServiceWorkerFetchResponseCallbackPtr fetch_callback_ptr; fetch_callback_request = mojo::MakeRequest(&fetch_callback_ptr); - auto params = mojom::DispatchFetchEventParams::New(); + auto params = blink::mojom::DispatchFetchEventParams::New(); params->request = *request; - pipes.event_dispatcher->DispatchFetchEvent( + pipes.service_worker->DispatchFetchEvent( std::move(params), std::move(fetch_callback_ptr), base::BindOnce( [](blink::mojom::ServiceWorkerEventStatus, base::Time) {})); @@ -380,7 +382,7 @@ TEST_F(ServiceWorkerContextClientTest, mojo::MakeRequest(&fetch_callback_ptr); auto request = std::make_unique<network::ResourceRequest>(); request->url = expected_url; - auto params = mojom::DispatchFetchEventParams::New(); + auto params = blink::mojom::DispatchFetchEventParams::New(); params->request = *request; context_client->DispatchOrQueueFetchEvent( std::move(params), std::move(fetch_callback_ptr), @@ -428,7 +430,7 @@ TEST_F(ServiceWorkerContextClientTest, fetch_callback_request = mojo::MakeRequest(&fetch_callback_ptr); auto request = std::make_unique<network::ResourceRequest>(); request->url = expected_url; - auto params = mojom::DispatchFetchEventParams::New(); + auto params = blink::mojom::DispatchFetchEventParams::New(); params->request = *request; pipes.controller->DispatchFetchEvent( std::move(params), std::move(fetch_callback_ptr), @@ -477,7 +479,7 @@ TEST_F(ServiceWorkerContextClientTest, fetch_callback_request_1 = mojo::MakeRequest(&fetch_callback_ptr); auto request = std::make_unique<network::ResourceRequest>(); request->url = expected_url_1; - auto params = mojom::DispatchFetchEventParams::New(); + auto params = blink::mojom::DispatchFetchEventParams::New(); params->request = *request; pipes.controller->DispatchFetchEvent( std::move(params), std::move(fetch_callback_ptr), @@ -487,16 +489,16 @@ TEST_F(ServiceWorkerContextClientTest, } EXPECT_TRUE(mock_proxy.fetch_events().empty()); - // Another event dispatched to mojom::ServiceWorkerEventDispatcher wakes up + // Another event dispatched to mojom::ServiceWorker wakes up // the context client. { 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; - auto params = mojom::DispatchFetchEventParams::New(); + auto params = blink::mojom::DispatchFetchEventParams::New(); params->request = *request; - pipes.event_dispatcher->DispatchFetchEvent( + pipes.service_worker->DispatchFetchEvent( std::move(params), std::move(fetch_callback_ptr), base::BindOnce( [](blink::mojom::ServiceWorkerEventStatus, base::Time) {})); 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 f432fa6d2e4..5cdaab338f6 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 @@ -5,6 +5,7 @@ #include "content/renderer/service_worker/service_worker_fetch_context_impl.h" #include "base/feature_list.h" +#include "content/common/content_constants_internal.h" #include "content/public/common/content_features.h" #include "content/public/renderer/url_loader_throttle_provider.h" #include "content/public/renderer/websocket_handshake_throttle_provider.h" @@ -18,15 +19,20 @@ namespace content { ServiceWorkerFetchContextImpl::ServiceWorkerFetchContextImpl( + RendererPreferences renderer_preferences, const GURL& worker_script_url, std::unique_ptr<network::SharedURLLoaderFactoryInfo> url_loader_factory_info, + std::unique_ptr<network::SharedURLLoaderFactoryInfo> + script_loader_factory_info, int service_worker_provider_id, std::unique_ptr<URLLoaderThrottleProvider> throttle_provider, std::unique_ptr<WebSocketHandshakeThrottleProvider> websocket_handshake_throttle_provider) - : worker_script_url_(worker_script_url), + : renderer_preferences_(std::move(renderer_preferences)), + worker_script_url_(worker_script_url), url_loader_factory_info_(std::move(url_loader_factory_info)), + script_loader_factory_info_(std::move(script_loader_factory_info)), service_worker_provider_id_(service_worker_provider_id), throttle_provider_(std::move(throttle_provider)), websocket_handshake_throttle_provider_( @@ -47,6 +53,10 @@ void ServiceWorkerFetchContextImpl::InitializeOnWorkerThread() { url_loader_factory_ = network::SharedURLLoaderFactory::Create( std::move(url_loader_factory_info_)); + if (script_loader_factory_info_) { + script_loader_factory_ = network::SharedURLLoaderFactory::Create( + std::move(script_loader_factory_info_)); + } } std::unique_ptr<blink::WebURLLoaderFactory> @@ -67,8 +77,20 @@ ServiceWorkerFetchContextImpl::WrapURLLoaderFactory( network::mojom::URLLoaderFactory::Version_))); } +std::unique_ptr<blink::WebURLLoaderFactory> +ServiceWorkerFetchContextImpl::CreateScriptLoaderFactory() { + if (!script_loader_factory_) + return nullptr; + return std::make_unique<content::WebURLLoaderFactoryImpl>( + resource_dispatcher_->GetWeakPtr(), std::move(script_loader_factory_)); +} + void ServiceWorkerFetchContextImpl::WillSendRequest( blink::WebURLRequest& request) { + if (renderer_preferences_.enable_do_not_track) { + request.SetHTTPHeaderField(blink::WebString::FromUTF8(kDoNotTrackHeader), + "1"); + } auto extra_data = std::make_unique<RequestExtraData>(); extra_data->set_service_worker_provider_id(service_worker_provider_id_); extra_data->set_originated_from_service_worker(true); @@ -78,10 +100,16 @@ void ServiceWorkerFetchContextImpl::WillSendRequest( MSG_ROUTING_NONE, request, WebURLRequestToResourceType(request))); } request.SetExtraData(std::move(extra_data)); + + if (!renderer_preferences_.enable_referrers) { + request.SetHTTPReferrer(blink::WebString(), + blink::kWebReferrerPolicyDefault); + } } -bool ServiceWorkerFetchContextImpl::IsControlledByServiceWorker() const { - return false; +blink::mojom::ControllerServiceWorkerMode +ServiceWorkerFetchContextImpl::IsControlledByServiceWorker() const { + return blink::mojom::ControllerServiceWorkerMode::kNoController; } blink::WebURL ServiceWorkerFetchContextImpl::SiteForCookies() const { 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 8ccd9817f40..082614a85c7 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,6 +5,7 @@ #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_preferences.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" @@ -16,10 +17,20 @@ class WebSocketHandshakeThrottleProvider; class ServiceWorkerFetchContextImpl : public blink::WebWorkerFetchContext { 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 + // contain non-NetworkService factories for handling non-http(s) URLs like + // chrome-extension://. + // |script_loader_factory_info| is used for importScripts() from the service + // worker when InstalledScriptsManager doesn't have the requested script. It + // is a ServiceWorkerScriptLoaderFactory, which loads and installs the script. ServiceWorkerFetchContextImpl( + RendererPreferences renderer_preferences, const GURL& worker_script_url, std::unique_ptr<network::SharedURLLoaderFactoryInfo> url_loader_factory_info, + std::unique_ptr<network::SharedURLLoaderFactoryInfo> + script_loader_factory_info, int service_worker_provider_id, std::unique_ptr<URLLoaderThrottleProvider> throttle_provider, std::unique_ptr<WebSocketHandshakeThrottleProvider> @@ -32,22 +43,32 @@ class ServiceWorkerFetchContextImpl : public blink::WebWorkerFetchContext { std::unique_ptr<blink::WebURLLoaderFactory> CreateURLLoaderFactory() override; std::unique_ptr<blink::WebURLLoaderFactory> WrapURLLoaderFactory( mojo::ScopedMessagePipeHandle url_loader_factory_handle) override; + std::unique_ptr<blink::WebURLLoaderFactory> CreateScriptLoaderFactory() + override; void WillSendRequest(blink::WebURLRequest&) override; - bool IsControlledByServiceWorker() const override; + blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker() + const override; blink::WebURL SiteForCookies() const override; std::unique_ptr<blink::WebSocketHandshakeThrottle> CreateWebSocketHandshakeThrottle() override; private: + RendererPreferences renderer_preferences_; const GURL worker_script_url_; // Consumed on the worker thread to create |url_loader_factory_|. std::unique_ptr<network::SharedURLLoaderFactoryInfo> url_loader_factory_info_; + // Consumed on the worker thread to create |script_loader_factory_|. + std::unique_ptr<network::SharedURLLoaderFactoryInfo> + script_loader_factory_info_; const int service_worker_provider_id_; // Initialized on the worker thread when InitializeOnWorkerThread() is called. std::unique_ptr<ResourceDispatcher> resource_dispatcher_; + // Responsible for regular loads from the service worker (i.e., Fetch API). scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; + // Responsible for handling importScripts(). + scoped_refptr<network::SharedURLLoaderFactory> script_loader_factory_; std::unique_ptr<URLLoaderThrottleProvider> throttle_provider_; std::unique_ptr<WebSocketHandshakeThrottleProvider> diff --git a/chromium/content/renderer/service_worker/service_worker_message_filter.cc b/chromium/content/renderer/service_worker/service_worker_message_filter.cc deleted file mode 100644 index 1e99e493c4c..00000000000 --- a/chromium/content/renderer/service_worker/service_worker_message_filter.cc +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/service_worker/service_worker_message_filter.h" - -#include <stddef.h> - -#include "content/common/service_worker/service_worker_messages.h" -#include "ipc/ipc_message_macros.h" - -namespace content { - -ServiceWorkerMessageFilter::ServiceWorkerMessageFilter( - ThreadSafeSender* sender, - scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner) - : WorkerThreadMessageFilter(sender, std::move(main_thread_task_runner)) {} - -ServiceWorkerMessageFilter::~ServiceWorkerMessageFilter() {} - -bool ServiceWorkerMessageFilter::ShouldHandleMessage( - const IPC::Message& msg) const { - return IPC_MESSAGE_CLASS(msg) == ServiceWorkerMsgStart; -} - -void ServiceWorkerMessageFilter::OnFilteredMessageReceived( - const IPC::Message& msg) { -} - -bool ServiceWorkerMessageFilter::GetWorkerThreadIdForMessage( - const IPC::Message& msg, - int* ipc_thread_id) { - return base::PickleIterator(msg).ReadInt(ipc_thread_id); -} - -} // namespace content diff --git a/chromium/content/renderer/service_worker/service_worker_message_filter.h b/chromium/content/renderer/service_worker/service_worker_message_filter.h deleted file mode 100644 index 52cc42b69d5..00000000000 --- a/chromium/content/renderer/service_worker/service_worker_message_filter.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_MESSAGE_FILTER_H_ -#define CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_MESSAGE_FILTER_H_ - -#include "base/macros.h" -#include "base/single_thread_task_runner.h" -#include "content/common/content_export.h" -#include "content/renderer/worker_thread_message_filter.h" - -namespace content { - -// TODO(leonhsl): Eliminate this class since we're in a pure Mojo world now, no -// longer need to handle any legacy IPCs. -class CONTENT_EXPORT ServiceWorkerMessageFilter - : public WorkerThreadMessageFilter { - public: - ServiceWorkerMessageFilter( - ThreadSafeSender* thread_safe_sender, - scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner); - - protected: - ~ServiceWorkerMessageFilter() override; - - private: - // WorkerThreadMessageFilter: - bool ShouldHandleMessage(const IPC::Message& msg) const override; - void OnFilteredMessageReceived(const IPC::Message& msg) override; - bool GetWorkerThreadIdForMessage(const IPC::Message& msg, - int* ipc_thread_id) override; - - DISALLOW_COPY_AND_ASSIGN(ServiceWorkerMessageFilter); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_MESSAGE_FILTER_H_ 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 7b64c4750ff..c3cec85dfed 100644 --- a/chromium/content/renderer/service_worker/service_worker_network_provider.cc +++ b/chromium/content/renderer/service_worker/service_worker_network_provider.cc @@ -8,7 +8,7 @@ #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_host_info.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" #include "content/public/common/origin_util.h" @@ -21,8 +21,9 @@ #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" #include "services/network/public/cpp/wrapper_shared_url_loader_factory.h" #include "third_party/blink/public/common/frame/sandbox_flags.h" +#include "third_party/blink/public/common/service_worker/service_worker_utils.h" #include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h" -#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_network_provider.h" +#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h" #include "third_party/blink/public/platform/web_security_origin.h" #include "third_party/blink/public/web/web_local_frame.h" @@ -54,7 +55,7 @@ bool IsFrameSecure(blink::WebFrame* frame) { class WebServiceWorkerNetworkProviderForFrame : public blink::WebServiceWorkerNetworkProvider { public: - WebServiceWorkerNetworkProviderForFrame( + explicit WebServiceWorkerNetworkProviderForFrame( std::unique_ptr<ServiceWorkerNetworkProvider> provider) : provider_(std::move(provider)) {} @@ -74,14 +75,16 @@ class WebServiceWorkerNetworkProviderForFrame network::mojom::RequestContextFrameType::kTopLevel && request.GetFrameType() != network::mojom::RequestContextFrameType::kNested && - !provider_->IsControlledByServiceWorker()) { + provider_->IsControlledByServiceWorker() == + blink::mojom::ControllerServiceWorkerMode::kNoController) { request.SetSkipServiceWorker(true); } } int ProviderID() const override { return provider_->provider_id(); } - bool HasControllerServiceWorker() override { + blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker() + override { return provider_->IsControlledByServiceWorker(); } @@ -95,14 +98,15 @@ class WebServiceWorkerNetworkProviderForFrame std::unique_ptr<blink::WebURLLoader> CreateURLLoader( const blink::WebURLRequest& request, - scoped_refptr<base::SingleThreadTaskRunner> task_runner) override { + std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle> + task_runner_handle) override { // RenderThreadImpl is nullptr in some tests. if (!RenderThreadImpl::current()) return nullptr; // S13nServiceWorker: // We only install our own URLLoader if Servicification is enabled. - if (!ServiceWorkerUtils::IsServicificationEnabled()) + if (!blink::ServiceWorkerUtils::IsServicificationEnabled()) return nullptr; // We need SubresourceLoaderFactory populated in order to create our own @@ -131,11 +135,13 @@ class WebServiceWorkerNetworkProviderForFrame // pointer into SharedURLLoaderFactory. return std::make_unique<WebURLLoaderImpl>( RenderThreadImpl::current()->resource_dispatcher(), - std::move(task_runner), + std::move(task_runner_handle), base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( provider_->context()->GetSubresourceLoaderFactory())); } + void DispatchNetworkQuiet() override { provider_->DispatchNetworkQuiet(); } + private: std::unique_ptr<ServiceWorkerNetworkProvider> provider_; }; @@ -146,9 +152,8 @@ class WebServiceWorkerNetworkProviderForFrame std::unique_ptr<blink::WebServiceWorkerNetworkProvider> ServiceWorkerNetworkProvider::CreateForNavigation( int route_id, - const RequestNavigationParams& request_params, + const RequestNavigationParams* request_params, blink::WebLocalFrame* frame, - bool content_initiated, mojom::ControllerServiceWorkerInfoPtr controller_info, scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory) { // Determine if a ServiceWorkerNetworkProvider should be created and properly @@ -157,13 +162,13 @@ ServiceWorkerNetworkProvider::CreateForNavigation( // however it will have an invalid id. bool should_create_provider = false; int provider_id = kInvalidServiceWorkerProviderId; - if (content_initiated) { + if (request_params) { + should_create_provider = request_params->should_create_service_worker; + provider_id = request_params->service_worker_provider_id; + } else { should_create_provider = ((frame->EffectiveSandboxFlags() & blink::WebSandboxFlags::kOrigin) != blink::WebSandboxFlags::kOrigin); - } else { - should_create_provider = request_params.should_create_service_worker; - provider_id = request_params.service_worker_provider_id; } // If we shouldn't create a real ServiceWorkerNetworkProvider, return one with @@ -206,7 +211,7 @@ ServiceWorkerNetworkProvider::CreateForSharedWorker( scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory) { // S13nServiceWorker: |info| holds info about the precreated provider host. if (info) { - DCHECK(ServiceWorkerUtils::IsServicificationEnabled()); + DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled()); return base::WrapUnique(new ServiceWorkerNetworkProvider( std::move(info), std::move(script_loader_factory_info), std::move(fallback_loader_factory))); @@ -232,7 +237,7 @@ ServiceWorkerNetworkProvider* ServiceWorkerNetworkProvider::FromWebServiceWorkerNetworkProvider( blink::WebServiceWorkerNetworkProvider* provider) { if (!provider) { - DCHECK(ServiceWorkerUtils::IsServicificationEnabled()); + DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled()); return nullptr; } return static_cast<WebServiceWorkerNetworkProviderForFrame*>(provider) @@ -251,9 +256,17 @@ int ServiceWorkerNetworkProvider::provider_id() const { return context()->provider_id(); } -bool ServiceWorkerNetworkProvider::IsControlledByServiceWorker() const { - return context() && context()->GetControllerVersionId() != - blink::mojom::kInvalidServiceWorkerVersionId; +blink::mojom::ControllerServiceWorkerMode +ServiceWorkerNetworkProvider::IsControlledByServiceWorker() const { + if (!context()) + return blink::mojom::ControllerServiceWorkerMode::kNoController; + return context()->IsControlledByServiceWorker(); +} + +void ServiceWorkerNetworkProvider::DispatchNetworkQuiet() { + if (!context()) + return; + context()->DispatchNetworkQuiet(); } // Creates an invalid instance (provider_id() returns @@ -273,14 +286,15 @@ ServiceWorkerNetworkProvider::ServiceWorkerNetworkProvider( provider_type == blink::mojom::ServiceWorkerProviderType::kForSharedWorker); - ServiceWorkerProviderHostInfo host_info(provider_id, route_id, provider_type, - is_parent_frame_secure); + auto host_info = mojom::ServiceWorkerProviderHostInfo::New( + provider_id, route_id, provider_type, is_parent_frame_secure, + nullptr /* host_request */, nullptr /* client_ptr_info */); mojom::ServiceWorkerContainerAssociatedRequest client_request = - mojo::MakeRequest(&host_info.client_ptr_info); + mojo::MakeRequest(&host_info->client_ptr_info); mojom::ServiceWorkerContainerHostAssociatedPtrInfo host_ptr_info; - host_info.host_request = mojo::MakeRequest(&host_ptr_info); - DCHECK(host_info.host_request.is_pending()); - DCHECK(host_info.host_request.handle().is_valid()); + host_info->host_request = mojo::MakeRequest(&host_ptr_info); + DCHECK(host_info->host_request.is_pending()); + DCHECK(host_info->host_request.handle().is_valid()); // current() may be null in tests. if (ChildThreadImpl::current()) { 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 120b71cbdf9..ab53df97d40 100644 --- a/chromium/content/renderer/service_worker/service_worker_network_provider.h +++ b/chromium/content/renderer/service_worker/service_worker_network_provider.h @@ -16,7 +16,6 @@ #include "base/supports_user_data.h" #include "content/common/content_export.h" #include "content/common/service_worker/controller_service_worker.mojom.h" -#include "content/common/service_worker/service_worker.mojom.h" #include "content/common/service_worker/service_worker_provider.mojom.h" #include "content/renderer/service_worker/service_worker_provider_context.h" #include "third_party/blink/public/mojom/service_worker/service_worker_provider_type.mojom.h" @@ -60,6 +59,14 @@ class CONTENT_EXPORT ServiceWorkerNetworkProvider { // Creates a ServiceWorkerNetworkProvider for navigation and wraps it // with WebServiceWorkerNetworkProvider to be owned by Blink. // + // |request_params| are navigation parameters that were transmitted to the + // 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). + // TODO(ahemery): Update this comment when do not create placeholder document + // loaders for renderer-initiated navigations. In this case, this should never + // be null. + // // For S13nServiceWorker: // |controller_info| contains the endpoint and object info that is needed to // set up the controller service worker for the client. @@ -70,9 +77,8 @@ class CONTENT_EXPORT ServiceWorkerNetworkProvider { static std::unique_ptr<blink::WebServiceWorkerNetworkProvider> CreateForNavigation( int route_id, - const RequestNavigationParams& request_params, + const RequestNavigationParams* request_params, blink::WebLocalFrame* frame, - bool content_initiated, mojom::ControllerServiceWorkerInfoPtr controller_info, scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory); @@ -103,7 +109,12 @@ class CONTENT_EXPORT ServiceWorkerNetworkProvider { return script_loader_factory_.get(); } - bool IsControlledByServiceWorker() const; + // Returns whether the context this provider is for is controlled by a service + // worker. Can be called only for providers for service worker clients. + blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker() const; + + // Called when blink::IdlenessDetector emits its network idle signal. + void DispatchNetworkQuiet(); private: // Creates an invalid instance (provider_id() returns 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 e63e68b8ae2..c187d3c147e 100644 --- a/chromium/content/renderer/service_worker/service_worker_provider_context.cc +++ b/chromium/content/renderer/service_worker/service_worker_provider_context.cc @@ -11,10 +11,10 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/stl_util.h" +#include "base/task_scheduler/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" -#include "content/common/service_worker/service_worker_utils.h" #include "content/public/common/service_names.mojom.h" #include "content/renderer/service_worker/controller_service_worker_connector.h" #include "content/renderer/service_worker/service_worker_subresource_loader.h" @@ -27,11 +27,35 @@ #include "services/network/public/mojom/url_loader_factory.mojom.h" #include "services/service_manager/public/cpp/connector.h" #include "services/service_manager/public/cpp/interface_provider.h" +#include "third_party/blink/public/common/service_worker/service_worker_utils.h" #include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h" #include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h" namespace content { +namespace { + +void CreateSubresourceLoaderFactoryForProviderContext( + mojom::ServiceWorkerContainerHostPtrInfo container_host_info, + mojom::ControllerServiceWorkerPtrInfo controller_ptr_info, + const std::string& client_id, + std::unique_ptr<network::SharedURLLoaderFactoryInfo> fallback_factory_info, + mojom::ControllerServiceWorkerConnectorRequest connector_request, + network::mojom::URLLoaderFactoryRequest request, + scoped_refptr<base::SequencedTaskRunner> task_runner) { + mojom::ControllerServiceWorkerPtr controller_ptr; + controller_ptr.Bind(std::move(controller_ptr_info)); + auto connector = base::MakeRefCounted<ControllerServiceWorkerConnector>( + std::move(container_host_info), std::move(controller_ptr), client_id); + connector->AddBinding(std::move(connector_request)); + ServiceWorkerSubresourceLoaderFactory::Create( + std::move(connector), + network::SharedURLLoaderFactory::Create(std::move(fallback_factory_info)), + std::move(request), std::move(task_runner)); +} + +} // namespace + // Holds state for service worker clients. struct ServiceWorkerProviderContext::ProviderStateForClient { explicit ProviderStateForClient( @@ -57,6 +81,9 @@ struct ServiceWorkerProviderContext::ProviderStateForClient { // 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; @@ -73,13 +100,26 @@ struct ServiceWorkerProviderContext::ProviderStateForClient { // 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. Kept here in order to call - // OnContainerHostConnectionClosed when container_host_ for the - // provider is reset. - // This is (re)set to nullptr if no controller is attached to this client. - scoped_refptr<ControllerServiceWorkerConnector> controller_connector; + // 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. @@ -139,27 +179,53 @@ ServiceWorkerProviderContext::TakeController() { return std::move(state_for_client_->controller); } -int64_t ServiceWorkerProviderContext::GetControllerVersionId() { +int64_t ServiceWorkerProviderContext::GetControllerVersionId() const { DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence()); DCHECK(state_for_client_); return state_for_client_->controller_version_id; } +blink::mojom::ControllerServiceWorkerMode +ServiceWorkerProviderContext::IsControlledByServiceWorker() const { + DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence()); + DCHECK(state_for_client_); + return state_for_client_->controller_mode; +} + network::mojom::URLLoaderFactory* ServiceWorkerProviderContext::GetSubresourceLoaderFactory() { + if (!blink::ServiceWorkerUtils::IsServicificationEnabled()) + return nullptr; + DCHECK(state_for_client_); auto* state = state_for_client_.get(); - if (!state->controller_connector || - state->controller_connector->state() == - ControllerServiceWorkerConnector::State::kNoController) { + if (!state->controller_endpoint && !state->controller_connector) { // No controller is attached. return nullptr; } - DCHECK(ServiceWorkerUtils::IsServicificationEnabled()); + + if (state->controller_mode != + blink::mojom::ControllerServiceWorkerMode::kControlled) { + // The controller does not exist or has no fetch event handler. + return nullptr; + } + if (!state->subresource_loader_factory) { - ServiceWorkerSubresourceLoaderFactory::Create( - state->controller_connector, state->fallback_loader_factory, - mojo::MakeRequest(&state->subresource_loader_factory)); + DCHECK(!state->controller_connector); + DCHECK(state->controller_endpoint); + // Create a SubresourceLoaderFactory on a background thread to avoid + // extra contention on the main thread. + auto task_runner = base::CreateSequencedTaskRunnerWithTraits( + {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}); + task_runner->PostTask( + FROM_HERE, + base::BindOnce(&CreateSubresourceLoaderFactoryForProviderContext, + CloneContainerHostPtrInfo(), + std::move(state->controller_endpoint), state->client_id, + state->fallback_loader_factory->Clone(), + mojo::MakeRequest(&state->controller_connector), + mojo::MakeRequest(&state->subresource_loader_factory), + task_runner)); } return state->subresource_loader_factory.get(); } @@ -188,25 +254,31 @@ void ServiceWorkerProviderContext::SetWebServiceWorkerProvider( state_for_client_->web_service_worker_provider = provider; } -mojom::ServiceWorkerWorkerClientRequest -ServiceWorkerProviderContext::CreateWorkerClientRequest() { +void ServiceWorkerProviderContext::RegisterWorkerClient( + mojom::ServiceWorkerWorkerClientPtr client) { DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence()); DCHECK(state_for_client_); - mojom::ServiceWorkerWorkerClientPtr client; - mojom::ServiceWorkerWorkerClientRequest request = mojo::MakeRequest(&client); client.set_connection_error_handler(base::BindOnce( &ServiceWorkerProviderContext::UnregisterWorkerFetchContext, base::Unretained(this), client.get())); state_for_client_->worker_clients.push_back(std::move(client)); - return request; +} + +void ServiceWorkerProviderContext::CloneWorkerClientRegistry( + mojom::ServiceWorkerWorkerClientRegistryRequest request) { + DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence()); + DCHECK(state_for_client_); + state_for_client_->worker_client_registry_bindings.AddBinding( + this, std::move(request)); } mojom::ServiceWorkerContainerHostPtrInfo ServiceWorkerProviderContext::CloneContainerHostPtrInfo() { - DCHECK(ServiceWorkerUtils::IsServicificationEnabled()); + DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled()); DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence()); DCHECK(state_for_client_); mojom::ServiceWorkerContainerHostPtrInfo container_host_ptr_info; + // TODO(kinuko): rename this, now this can be used for non-worker clients. container_host_->CloneForWorker(mojo::MakeRequest(&container_host_ptr_info)); return container_host_ptr_info; } @@ -248,8 +320,6 @@ ServiceWorkerProviderContext::GetOrCreateServiceWorkerObject( void ServiceWorkerProviderContext::OnNetworkProviderDestroyed() { container_host_.reset(); - if (state_for_client_ && state_for_client_->controller_connector) - state_for_client_->controller_connector->OnContainerHostConnectionClosed(); } void ServiceWorkerProviderContext::PingContainerHost( @@ -258,6 +328,24 @@ void ServiceWorkerProviderContext::PingContainerHost( container_host_->Ping(std::move(callback)); } +void ServiceWorkerProviderContext::DispatchNetworkQuiet() { + DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence()); + ProviderStateForClient* state = state_for_client_.get(); + DCHECK(state); + + // In non-S13nSW, this hint isn't needed because the browser process + // sees all requests and schedules update at a convenient time. + if (!blink::ServiceWorkerUtils::IsServicificationEnabled()) + return; + + if (state->controller_mode == + blink::mojom::ControllerServiceWorkerMode::kNoController) { + return; + } + + container_host_->HintToUpdateServiceWorker(); +} + void ServiceWorkerProviderContext::UnregisterWorkerFetchContext( mojom::ServiceWorkerWorkerClient* client) { DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence()); @@ -286,6 +374,15 @@ void ServiceWorkerProviderContext::SetController( state->client_id == controller_info->client_id); state->client_id = controller_info->client_id; + DCHECK((controller_info->mode == + blink::mojom::ControllerServiceWorkerMode::kNoController && + !state->controller) || + (controller_info->mode != + blink::mojom::ControllerServiceWorkerMode::kNoController && + state->controller)); + state->controller_mode = controller_info->mode; + state->controller_endpoint = std::move(controller_info->endpoint); + // Propagate the controller to workers related to this provider. if (state->controller) { DCHECK_NE(blink::mojom::kInvalidServiceWorkerVersionId, @@ -293,16 +390,16 @@ void ServiceWorkerProviderContext::SetController( for (const auto& worker : state->worker_clients) { // This is a Mojo interface call to the (dedicated or shared) worker // thread. - worker->SetControllerServiceWorker(state->controller->version_id); + worker->OnControllerChanged(state->controller_mode); } } for (blink::mojom::WebFeature feature : used_features) state->used_features.insert(feature); // S13nServiceWorker: - // Reset subresource loader factory if necessary. + // Reset connector state for subresource loader factory if necessary. if (CanCreateSubresourceLoaderFactory()) { - DCHECK(ServiceWorkerUtils::IsServicificationEnabled()); + DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled()); // There could be four patterns: // (A) Had a controller, and got a new controller. @@ -310,26 +407,20 @@ void ServiceWorkerProviderContext::SetController( // (C) Didn't have a controller, and got a new controller. // (D) Didn't have a controller, and lost the controller (nothing to do). if (state->controller_connector) { - // Used to have a controller at least once. - // Reset the existing connector so that subsequent resource requests - // will get the new controller in case (A)/(C), or fallback to the - // network in case (B). Inflight requests that are already dispatched may - // just use the existing controller or may use the new controller - // settings depending on when the request is actually passed to the - // factory (this part is inherently racy). - state->controller_connector->ResetControllerConnection( + // Used to have a controller at least once and have created a + // subresource loader factory before (if no subresource factory was + // created before, then the right controller, if any, will be used when + // the factory is created in GetSubresourceLoaderFactory, so there's + // nothing to do here). + // Update the connector's controller so that subsequent resource requests + // will get the new controller in case (A)/(C), or fallback to the network + // in case (B). Inflight requests that are already dispatched may just use + // the existing controller or may use the new controller settings + // depending on when the request is actually passed to the factory (this + // part is inherently racy). + state->controller_connector->UpdateController( mojom::ControllerServiceWorkerPtr( - std::move(controller_info->endpoint))); - } else if (state->controller) { - // Case (C): never had a controller, but got a new one now. - // Set a new |state->controller_connector| so that subsequent resource - // requests will see it. - mojom::ControllerServiceWorkerPtr controller_ptr( - std::move(controller_info->endpoint)); - state->controller_connector = - base::MakeRefCounted<ControllerServiceWorkerConnector>( - container_host_.get(), std::move(controller_ptr), - controller_info->client_id); + std::move(state->controller_endpoint))); } } @@ -419,7 +510,7 @@ bool ServiceWorkerProviderContext::CanCreateSubresourceLoaderFactory() const { // Expected that it is called only for clients. DCHECK(state_for_client_); // |state_for_client_->fallback_loader_factory| could be null in unit tests. - return (ServiceWorkerUtils::IsServicificationEnabled() && + return (blink::ServiceWorkerUtils::IsServicificationEnabled() && state_for_client_->fallback_loader_factory); } 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 19fec07789a..405c40c960f 100644 --- a/chromium/content/renderer/service_worker/service_worker_provider_context.h +++ b/chromium/content/renderer/service_worker/service_worker_provider_context.h @@ -21,7 +21,7 @@ #include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h" #include "third_party/blink/public/mojom/service_worker/service_worker_provider_type.mojom.h" #include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h" -#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_provider_client.h" +#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_provider_client.h" namespace base { class SingleThreadTaskRunner; @@ -47,12 +47,20 @@ struct ServiceWorkerProviderContextDeleter; // the same underlying entity hold strong references to a shared instance of // this class. // +// ServiceWorkerProviderContext is also a +// mojom::ServiceWorkerWorkerClientRegistry. If it's a provider for a document, +// then it tracks all the dedicated workers created from the document (including +// nested workers), as dedicated workers don't yet have their own providers. If +// it's a provider for a shared worker, then it tracks only the shared worker +// itself. +// // Created and destructed on the main thread. Unless otherwise noted, all // methods are called on the main thread. class CONTENT_EXPORT ServiceWorkerProviderContext : public base::RefCountedThreadSafe<ServiceWorkerProviderContext, ServiceWorkerProviderContextDeleter>, - public mojom::ServiceWorkerContainer { + public mojom::ServiceWorkerContainer, + public mojom::ServiceWorkerWorkerClientRegistry { public: // Constructor for service worker clients. // @@ -108,7 +116,9 @@ class CONTENT_EXPORT ServiceWorkerProviderContext // For service worker clients. Returns version id of the controller service // worker object (ServiceWorkerContainer#controller). - int64_t GetControllerVersionId(); + int64_t GetControllerVersionId() const; + + blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker() const; // For service worker clients. Takes the controller service worker object info // set by SetController() if any, otherwise returns nullptr. @@ -135,22 +145,18 @@ class CONTENT_EXPORT ServiceWorkerProviderContext void SetWebServiceWorkerProvider( base::WeakPtr<WebServiceWorkerProviderImpl> provider); - // For service worker clients. Creates a ServiceWorkerWorkerClientRequest - // which can be used to bind with a WorkerFetchContextImpl in a (dedicated or - // shared) worker thread and receive SetControllerServiceWorker() method call - // from the main thread. - // A dedicated worker's WorkerFetchContext calls CreateWorkerClientRequest() - // on its parent Document's ServiceWorkerProviderContext. A shared worker's - // fetch context calls CreateWorkerClientRequest() on its own - // ServiceWorkerProviderContext. - mojom::ServiceWorkerWorkerClientRequest CreateWorkerClientRequest(); + // mojom::ServiceWorkerWorkerClientRegistry: + void RegisterWorkerClient( + mojom::ServiceWorkerWorkerClientPtr client) override; + void CloneWorkerClientRegistry( + mojom::ServiceWorkerWorkerClientRegistryRequest request) override; // S13nServiceWorker: // For service worker clients. Creates a ServiceWorkerContainerHostPtrInfo // which can be bound to a ServiceWorkerContainerHostPtr in a (dedicated or - // shared) worker thread. WorkerFetchContextImpl will use the host pointer to - // get the controller service worker by GetControllerServiceWorker() and send - // FetchEvents to the service worker. + // shared) worker thread. WebWorkerFetchContextImpl will use the host pointer + // to get the controller service worker by GetControllerServiceWorker() and + // send FetchEvents to the service worker. mojom::ServiceWorkerContainerHostPtrInfo CloneContainerHostPtrInfo(); // For service worker clients. Returns the registration object described by @@ -185,6 +191,11 @@ class CONTENT_EXPORT ServiceWorkerProviderContext // for waiting for all messages the host sent thus far to arrive. void PingContainerHost(base::OnceClosure callback); + // Called when blink::IdlenessDetector emits its network idle signal. Tells + // the browser process that this page is quiet soon after page load, as a + // hint to start the service worker update check. + void DispatchNetworkQuiet(); + private: friend class base::DeleteHelper<ServiceWorkerProviderContext>; friend class base::RefCountedThreadSafe<ServiceWorkerProviderContext, 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 7c73ae07a8a..d5d256d404b 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 @@ -10,6 +10,7 @@ #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/test/scoped_feature_list.h" +#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" @@ -32,7 +33,8 @@ #include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h" #include "third_party/blink/public/mojom/service_worker/service_worker_provider_type.mojom.h" #include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h" -#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_provider_client.h" +#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_provider_client.h" +#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" #include "third_party/blink/public/platform/web_feature.mojom.h" namespace content { @@ -204,9 +206,15 @@ class FakeURLLoaderFactory final : public network::mojom::URLLoaderFactory { // connection errors). last_url_ = url_request.url; clients_.push_back(std::move(client)); + if (start_loader_callback_) + std::move(start_loader_callback_).Run(); } void Clone(network::mojom::URLLoaderFactoryRequest factory) override { - NOTREACHED(); + bindings_.AddBinding(this, std::move(factory)); + } + + void set_start_loader_callback(base::OnceClosure closure) { + start_loader_callback_ = std::move(closure); } size_t clients_count() const { return clients_.size(); } @@ -215,6 +223,7 @@ class FakeURLLoaderFactory final : public network::mojom::URLLoaderFactory { private: mojo::BindingSet<network::mojom::URLLoaderFactory> bindings_; std::vector<network::mojom::URLLoaderClientPtr> clients_; + base::OnceClosure start_loader_callback_; GURL last_url_; DISALLOW_COPY_AND_ASSIGN(FakeURLLoaderFactory); @@ -229,23 +238,30 @@ class FakeControllerServiceWorker : public mojom::ControllerServiceWorker { // mojom::ControllerServiceWorker: void DispatchFetchEvent( - mojom::DispatchFetchEventParamsPtr params, + blink::mojom::DispatchFetchEventParamsPtr params, mojom::ServiceWorkerFetchResponseCallbackPtr response_callback, DispatchFetchEventCallback callback) override { fetch_event_count_++; fetch_event_request_ = params->request; std::move(callback).Run(blink::mojom::ServiceWorkerEventStatus::COMPLETED, base::Time()); + if (fetch_event_callback_) + std::move(fetch_event_callback_).Run(); } void Clone(mojom::ControllerServiceWorkerRequest request) override { bindings_.AddBinding(this, std::move(request)); } + void set_fetch_callback(base::OnceClosure closure) { + fetch_event_callback_ = std::move(closure); + } int fetch_event_count() const { return fetch_event_count_; } const network::ResourceRequest& fetch_event_request() const { return fetch_event_request_; } + void Disconnect() { bindings_.CloseAllBindings(); } + private: int fetch_event_count_ = 0; network::ResourceRequest fetch_event_request_; @@ -255,6 +271,50 @@ class FakeControllerServiceWorker : public mojom::ControllerServiceWorker { DISALLOW_COPY_AND_ASSIGN(FakeControllerServiceWorker); }; +class FakeServiceWorkerContainerHost + : public mojom::ServiceWorkerContainerHost { + public: + explicit FakeServiceWorkerContainerHost( + mojom::ServiceWorkerContainerHostAssociatedRequest request) + : associated_binding_(this, std::move(request)) {} + ~FakeServiceWorkerContainerHost() override = default; + + // Implements mojom::ServiceWorkerContainerHost. + void Register(const GURL& script_url, + blink::mojom::ServiceWorkerRegistrationOptionsPtr options, + RegisterCallback callback) override { + NOTIMPLEMENTED(); + } + void GetRegistration(const GURL& client_url, + GetRegistrationCallback callback) override { + NOTIMPLEMENTED(); + } + void GetRegistrations(GetRegistrationsCallback callback) override { + NOTIMPLEMENTED(); + } + void GetRegistrationForReady( + GetRegistrationForReadyCallback callback) override { + NOTIMPLEMENTED(); + } + void EnsureControllerServiceWorker( + mojom::ControllerServiceWorkerRequest request, + mojom::ControllerServiceWorkerPurpose purpose) override { + NOTIMPLEMENTED(); + } + void CloneForWorker( + mojom::ServiceWorkerContainerHostRequest request) override { + bindings_.AddBinding(this, std::move(request)); + } + void Ping(PingCallback callback) override { NOTIMPLEMENTED(); } + void HintToUpdateServiceWorker() override { NOTIMPLEMENTED(); } + + private: + mojo::BindingSet<mojom::ServiceWorkerContainerHost> bindings_; + mojo::AssociatedBinding<mojom::ServiceWorkerContainerHost> + associated_binding_; + DISALLOW_COPY_AND_ASSIGN(FakeServiceWorkerContainerHost); +}; + class ServiceWorkerProviderContextTest : public testing::Test { public: ServiceWorkerProviderContextTest() = default; @@ -280,8 +340,6 @@ class ServiceWorkerProviderContextTest : public testing::Test { mojo::MakeRequest(&loader), 0, 0, network::mojom::kURLLoadOptionNone, request, loader_client.CreateInterfacePtr(), net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS)); - // Need to run one more loop to make a Mojo call. - base::RunLoop().RunUntilIdle(); } bool ContainsRegistration(ServiceWorkerProviderContext* provider_context, @@ -296,7 +354,7 @@ class ServiceWorkerProviderContextTest : public testing::Test { } protected: - base::MessageLoop message_loop_; + base::test::ScopedTaskEnvironment task_environment; // S13nServiceWorker: base::test::ScopedFeatureList scoped_feature_list_; @@ -329,6 +387,7 @@ TEST_F(ServiceWorkerProviderContextTest, SetController) { nullptr /* controller_info */, nullptr /* loader_factory*/); auto info = mojom::ControllerServiceWorkerInfo::New(); + info->mode = blink::mojom::ControllerServiceWorkerMode::kControlled; info->object_info = std::move(object_info); container_ptr->SetController(std::move(info), std::vector<blink::mojom::WebFeature>(), true); @@ -373,6 +432,7 @@ TEST_F(ServiceWorkerProviderContextTest, SetController) { ASSERT_FALSE(client->was_set_controller_called()); auto info = mojom::ControllerServiceWorkerInfo::New(); + info->mode = blink::mojom::ControllerServiceWorkerMode::kControlled; info->object_info = std::move(object_info); container_ptr->SetController(std::move(info), std::vector<blink::mojom::WebFeature>(), true); @@ -430,15 +490,21 @@ TEST_F(ServiceWorkerProviderContextTest, SetControllerServiceWorker) { auto controller_info1 = mojom::ControllerServiceWorkerInfo::New(); mojom::ControllerServiceWorkerPtr controller_ptr1; fake_controller1.Clone(mojo::MakeRequest(&controller_ptr1)); + controller_info1->mode = + blink::mojom::ControllerServiceWorkerMode::kControlled; 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); auto provider_context = base::MakeRefCounted<ServiceWorkerProviderContext>( kProviderId, blink::mojom::ServiceWorkerProviderType::kForWindow, - std::move(container_request), nullptr /* host_ptr_info */, + std::move(container_request), host_ptr.PassInterface(), std::move(controller_info1), loader_factory_); base::RunLoop().RunUntilIdle(); @@ -449,7 +515,10 @@ TEST_F(ServiceWorkerProviderContextTest, SetControllerServiceWorker) { // Performing a request should reach the controller. const GURL kURL1("https://www.example.com/foo.png"); + base::RunLoop loop1; + fake_controller1.set_fetch_callback(loop1.QuitClosure()); StartRequest(subresource_loader_factory1, kURL1); + loop1.Run(); EXPECT_EQ(kURL1, fake_controller1.fetch_event_request().url); EXPECT_EQ(1, fake_controller1.fetch_event_count()); @@ -465,6 +534,8 @@ TEST_F(ServiceWorkerProviderContextTest, SetControllerServiceWorker) { auto controller_info2 = mojom::ControllerServiceWorkerInfo::New(); mojom::ControllerServiceWorkerPtr controller_ptr2; fake_controller2.Clone(mojo::MakeRequest(&controller_ptr2)); + controller_info2->mode = + blink::mojom::ControllerServiceWorkerMode::kControlled; controller_info2->object_info = std::move(object_info2); controller_info2->endpoint = controller_ptr2.PassInterface(); container_ptr->SetController(std::move(controller_info2), @@ -484,7 +555,10 @@ TEST_F(ServiceWorkerProviderContextTest, SetControllerServiceWorker) { // Performing a request should reach the new controller. const GURL kURL2("https://www.example.com/foo2.png"); + base::RunLoop loop2; + fake_controller2.set_fetch_callback(loop2.QuitClosure()); StartRequest(subresource_loader_factory2, kURL2); + loop2.Run(); EXPECT_EQ(kURL2, fake_controller2.fetch_event_request().url); EXPECT_EQ(1, fake_controller2.fetch_event_count()); // The request should not go to the previous controller. @@ -505,8 +579,11 @@ TEST_F(ServiceWorkerProviderContextTest, SetControllerServiceWorker) { // Performing a request using the subresource factory obtained before // falls back to the network. const GURL kURL3("https://www.example.com/foo3.png"); + base::RunLoop loop3; + fake_loader_factory_.set_start_loader_callback(loop3.QuitClosure()); EXPECT_EQ(0UL, fake_loader_factory_.clients_count()); StartRequest(subresource_loader_factory2, kURL3); + loop3.Run(); EXPECT_EQ(kURL3, fake_loader_factory_.last_request_url()); EXPECT_EQ(1UL, fake_loader_factory_.clients_count()); @@ -526,6 +603,8 @@ TEST_F(ServiceWorkerProviderContextTest, SetControllerServiceWorker) { auto controller_info4 = mojom::ControllerServiceWorkerInfo::New(); mojom::ControllerServiceWorkerPtr controller_ptr4; fake_controller4.Clone(mojo::MakeRequest(&controller_ptr4)); + controller_info4->mode = + blink::mojom::ControllerServiceWorkerMode::kControlled; controller_info4->object_info = std::move(object_info4); controller_info4->endpoint = controller_ptr4.PassInterface(); container_ptr->SetController(std::move(controller_info4), @@ -539,7 +618,10 @@ TEST_F(ServiceWorkerProviderContextTest, SetControllerServiceWorker) { // Performing a request should reach the new controller. const GURL kURL4("https://www.example.com/foo4.png"); + base::RunLoop loop4; + fake_controller4.set_fetch_callback(loop4.QuitClosure()); StartRequest(subresource_loader_factory4, kURL4); + loop4.Run(); EXPECT_EQ(kURL4, fake_controller4.fetch_event_request().url); EXPECT_EQ(1, fake_controller4.fetch_event_count()); @@ -548,6 +630,41 @@ TEST_F(ServiceWorkerProviderContextTest, SetControllerServiceWorker) { EXPECT_EQ(1, fake_controller2.fetch_event_count()); // The request should not go to the network. EXPECT_EQ(1UL, fake_loader_factory_.clients_count()); + + // Perform a request again, but then drop the controller connection. + // The outcome is not deterministic but should not crash. + StartRequest(subresource_loader_factory4, kURL4); + fake_controller4.Disconnect(); + base::RunLoop().RunUntilIdle(); +} + +TEST_F(ServiceWorkerProviderContextTest, ControllerWithoutFetchHandler) { + EnableS13nServiceWorker(); + const int kProviderId = 10; + auto object_host = + std::make_unique<MockServiceWorkerObjectHost>(200 /* version_id */); + + // Set a controller without ControllerServiceWorker ptr to emulate no + // fetch event handler. + blink::mojom::ServiceWorkerObjectInfoPtr object_info = + object_host->CreateObjectInfo(); + auto controller_info = mojom::ControllerServiceWorkerInfo::New(); + mojom::ControllerServiceWorkerPtr controller_ptr; + controller_info->mode = + blink::mojom::ControllerServiceWorkerMode::kNoFetchEventHandler; + controller_info->object_info = std::move(object_info); + + mojom::ServiceWorkerContainerAssociatedPtr container_ptr; + mojom::ServiceWorkerContainerAssociatedRequest container_request = + mojo::MakeRequestAssociatedWithDedicatedPipe(&container_ptr); + auto provider_context = base::MakeRefCounted<ServiceWorkerProviderContext>( + kProviderId, blink::mojom::ServiceWorkerProviderType::kForWindow, + std::move(container_request), nullptr /* host_ptr_info */, + std::move(controller_info), loader_factory_); + base::RunLoop().RunUntilIdle(); + + // Subresource loader factory must not be available. + EXPECT_EQ(nullptr, provider_context->GetSubresourceLoaderFactory()); } TEST_F(ServiceWorkerProviderContextTest, PostMessageToClient) { 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 07c74494a64..3e5b7dbfd77 100644 --- a/chromium/content/renderer/service_worker/service_worker_subresource_loader.cc +++ b/chromium/content/renderer/service_worker/service_worker_subresource_loader.cc @@ -7,7 +7,9 @@ #include "base/atomic_sequence_num.h" #include "base/callback.h" #include "base/feature_list.h" +#include "base/metrics/histogram_macros.h" #include "base/optional.h" +#include "base/trace_event/trace_event.h" #include "content/common/service_worker/service_worker_loader_helpers.h" #include "content/common/service_worker/service_worker_types.h" #include "content/common/service_worker/service_worker_utils.h" @@ -18,13 +20,16 @@ #include "content/renderer/service_worker/controller_service_worker_connector.h" #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/strong_binding.h" +#include "net/base/net_errors.h" #include "net/url_request/redirect_util.h" #include "net/url_request/url_request.h" #include "services/network/public/cpp/features.h" #include "services/network/public/cpp/shared_url_loader_factory.h" +#include "third_party/blink/public/common/service_worker/service_worker_type_converters.h" #include "third_party/blink/public/mojom/blob/blob.mojom.h" +#include "third_party/blink/public/mojom/service_worker/dispatch_fetch_event_params.mojom.h" #include "third_party/blink/public/platform/interface_provider.h" -#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_request.h" +#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_request.h" #include "third_party/blink/public/platform/web_http_body.h" #include "third_party/blink/public/platform/web_string.h" #include "ui/base/page_transition_types.h" @@ -60,12 +65,10 @@ class HeaderRewritingURLLoaderClient : public network::mojom::URLLoaderClient { private: // network::mojom::URLLoaderClient implementation: void OnReceiveResponse( - const network::ResourceResponseHead& response_head, - network::mojom::DownloadedTempFilePtr downloaded_file) override { + const network::ResourceResponseHead& response_head) override { DCHECK(url_loader_client_.is_bound()); url_loader_client_->OnReceiveResponse( - rewrite_header_callback_.Run(response_head), - std::move(downloaded_file)); + rewrite_header_callback_.Run(response_head)); } void OnReceiveRedirect( @@ -76,11 +79,6 @@ class HeaderRewritingURLLoaderClient : public network::mojom::URLLoaderClient { redirect_info, rewrite_header_callback_.Run(response_head)); } - void OnDataDownloaded(int64_t data_len, int64_t encoded_data_len) override { - DCHECK(url_loader_client_.is_bound()); - url_loader_client_->OnDataDownloaded(data_len, encoded_data_len); - } - void OnUploadProgress(int64_t current_position, int64_t total_size, OnUploadProgressCallback ack_callback) override { @@ -152,12 +150,14 @@ ServiceWorkerSubresourceLoader::ServiceWorkerSubresourceLoader( network::mojom::URLLoaderClientPtr client, const net::MutableNetworkTrafficAnnotationTag& traffic_annotation, scoped_refptr<ControllerServiceWorkerConnector> controller_connector, - scoped_refptr<network::SharedURLLoaderFactory> fallback_factory) + scoped_refptr<network::SharedURLLoaderFactory> fallback_factory, + scoped_refptr<base::SequencedTaskRunner> task_runner) : redirect_limit_(net::URLRequest::kMaxRedirects), url_loader_client_(std::move(client)), url_loader_binding_(this, std::move(request)), response_callback_binding_(this), controller_connector_(std::move(controller_connector)), + controller_connector_observer_(this), fetch_request_restarted_(false), routing_id_(routing_id), request_id_(request_id), @@ -165,6 +165,7 @@ ServiceWorkerSubresourceLoader::ServiceWorkerSubresourceLoader( traffic_annotation_(traffic_annotation), resource_request_(resource_request), fallback_factory_(std::move(fallback_factory)), + task_runner_(std::move(task_runner)), weak_factory_(this) { DCHECK(controller_connector_); response_head_.request_start = base::TimeTicks::Now(); @@ -177,9 +178,7 @@ ServiceWorkerSubresourceLoader::ServiceWorkerSubresourceLoader( StartRequest(resource_request); } -ServiceWorkerSubresourceLoader::~ServiceWorkerSubresourceLoader() { - SettleInflightFetchRequestIfNeeded(); -}; +ServiceWorkerSubresourceLoader::~ServiceWorkerSubresourceLoader() = default; void ServiceWorkerSubresourceLoader::OnConnectionError() { delete this; @@ -187,16 +186,17 @@ void ServiceWorkerSubresourceLoader::OnConnectionError() { void ServiceWorkerSubresourceLoader::StartRequest( const network::ResourceRequest& resource_request) { + TRACE_EVENT_WITH_FLOW1( + "ServiceWorker", "ServiceWorkerSubresourceLoader::StartRequest", this, + TRACE_EVENT_FLAG_FLOW_OUT, "url", resource_request.url.spec()); DCHECK_EQ(Status::kNotStarted, status_); status_ = Status::kStarted; DCHECK(!ServiceWorkerUtils::IsMainResourceType( static_cast<ResourceType>(resource_request.resource_type))); - DCHECK(!inflight_fetch_request_); - inflight_fetch_request_ = - std::make_unique<network::ResourceRequest>(resource_request); - controller_connector_->AddObserver(this); + DCHECK(!controller_connector_observer_.IsObservingSources()); + controller_connector_observer_.Add(controller_connector_.get()); fetch_request_restarted_ = false; response_head_.service_worker_start_time = base::TimeTicks::Now(); @@ -209,15 +209,14 @@ void ServiceWorkerSubresourceLoader::StartRequest( } void ServiceWorkerSubresourceLoader::DispatchFetchEvent() { - DCHECK(inflight_fetch_request_); mojom::ServiceWorkerFetchResponseCallbackPtr response_callback_ptr; response_callback_binding_.Bind(mojo::MakeRequest(&response_callback_ptr)); mojom::ControllerServiceWorker* controller = controller_connector_->GetControllerServiceWorker( mojom::ControllerServiceWorkerPurpose::FETCH_SUB_RESOURCE); - // When |controller| is null, the network request will be aborted soon since - // the network provider has already been discarded. In that case, We don't - // need to return an error as the client must be shutting down. + TRACE_EVENT1("ServiceWorker", + "ServiceWorkerSubresourceLoader::DispatchFetchEvent", + "controller", (controller ? "exists" : "does not exist")); if (!controller) { auto controller_state = controller_connector_->state(); if (controller_state == @@ -231,14 +230,18 @@ void ServiceWorkerSubresourceLoader::DispatchFetchEvent() { delete this; return; } + + // When kNoContainerHost, the network request will be aborted soon since the + // network provider has already been discarded. In that case, we don't need + // to return an error as the client must be shutting down. DCHECK_EQ(ControllerServiceWorkerConnector::State::kNoContainerHost, controller_state); - SettleInflightFetchRequestIfNeeded(); + SettleFetchEventDispatch(base::nullopt); return; } - auto params = mojom::DispatchFetchEventParams::New(); - params->request = *inflight_fetch_request_; + auto params = blink::mojom::DispatchFetchEventParams::New(); + params->request = resource_request_; params->client_id = controller_connector_->client_id(); // S13nServiceWorker without NetworkService: @@ -246,6 +249,10 @@ void ServiceWorkerSubresourceLoader::DispatchFetchEvent() { // before dispatching the fetch event for keeping the blob alive. if (resource_request_.request_body && !base::FeatureList::IsEnabled(network::features::kNetworkService)) { + // We need this as GetBlobFromUUID is a sync IPC. + // TODO(kinuko): Remove the friend for ScopedAllowBaseSyncPrimitives + // in //base as well when we remove this code. + base::ScopedAllowBaseSyncPrimitives allow_sync_primitives; params->request_body_blob_ptrs = GetBlobPtrsForRequestBody(*resource_request_.request_body); } @@ -253,15 +260,27 @@ void ServiceWorkerSubresourceLoader::DispatchFetchEvent() { controller->DispatchFetchEvent( std::move(params), std::move(response_callback_ptr), base::BindOnce(&ServiceWorkerSubresourceLoader::OnFetchEventFinished, - weak_factory_.GetWeakPtr())); + weak_factory_.GetWeakPtr(), base::Time::Now())); } void ServiceWorkerSubresourceLoader::OnFetchEventFinished( + base::Time request_dispatch_time, blink::mojom::ServiceWorkerEventStatus status, - base::Time dispatch_event_time) { + base::Time actual_dispatch_time) { + TRACE_EVENT_WITH_FLOW1("ServiceWorker", + "ServiceWorkerSubresourceLoader::OnFetchEventFinished", + this, TRACE_EVENT_FLAG_FLOW_IN, "status", + ServiceWorkerUtils::MojoEnumToString(status)); + // Stop restarting logic here since OnFetchEventFinished() indicates that the - // fetch event was successfully dispatched. - SettleInflightFetchRequestIfNeeded(); + // fetch event dispatch reached the renderer. + SettleFetchEventDispatch( + mojo::ConvertTo<blink::ServiceWorkerStatusCode>(status)); + + base::TimeDelta delay = actual_dispatch_time - request_dispatch_time; + UMA_HISTOGRAM_TIMES("ServiceWorker.EventDispatchingDelay", delay); + UMA_HISTOGRAM_TIMES("ServiceWorker.EventDispatchingDelay_FETCH_SUB_RESOURCE", + delay); switch (status) { case blink::mojom::ServiceWorkerEventStatus::COMPLETED: @@ -274,15 +293,17 @@ void ServiceWorkerSubresourceLoader::OnFetchEventFinished( // promise, and handle this request. break; case blink::mojom::ServiceWorkerEventStatus::ABORTED: - // We have an unexpected error: fetch event dispatch failed. Return - // network error. + // Fetch event dispatch did not complete, possibly due to timeout of + // respondWith() or waitUntil(). Return network error. + + // TODO(falken): This seems racy. respondWith() may have been called + // already and we could have an outstanding stream or blob in progress, + // and we might hit CommitCompleted() twice once that settles. CommitCompleted(net::ERR_FAILED); } } void ServiceWorkerSubresourceLoader::OnConnectionClosed() { - if (!inflight_fetch_request_) - return; response_callback_binding_.Close(); // If the connection to the service worker gets disconnected after dispatching @@ -290,28 +311,40 @@ void ServiceWorkerSubresourceLoader::OnConnectionClosed() { // the fetch event again. If it has already been restarted, that means // starting worker failed. In that case, abort the request. if (fetch_request_restarted_) { - SettleInflightFetchRequestIfNeeded(); + SettleFetchEventDispatch( + blink::ServiceWorkerStatusCode::kErrorStartWorkerFailed); CommitCompleted(net::ERR_FAILED); return; } fetch_request_restarted_ = true; - base::ThreadTaskRunnerHandle::Get()->PostTask( + task_runner_->PostTask( FROM_HERE, base::BindOnce(&ServiceWorkerSubresourceLoader::DispatchFetchEvent, weak_factory_.GetWeakPtr())); } -void ServiceWorkerSubresourceLoader::SettleInflightFetchRequestIfNeeded() { - if (inflight_fetch_request_) { - inflight_fetch_request_.reset(); - controller_connector_->RemoveObserver(this); +void ServiceWorkerSubresourceLoader::SettleFetchEventDispatch( + base::Optional<blink::ServiceWorkerStatusCode> status) { + if (!controller_connector_observer_.IsObservingSources()) { + // Already settled. + return; + } + controller_connector_observer_.RemoveAll(); + + if (status) { + blink::ServiceWorkerStatusCode value = status.value(); + UMA_HISTOGRAM_ENUMERATION("ServiceWorker.FetchEvent.Subresource.Status", + value); } } void ServiceWorkerSubresourceLoader::OnResponse( const ServiceWorkerResponse& response, base::Time dispatch_event_time) { - SettleInflightFetchRequestIfNeeded(); + 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 */); } @@ -320,30 +353,29 @@ void ServiceWorkerSubresourceLoader::OnResponseBlob( const ServiceWorkerResponse& response, blink::mojom::BlobPtr body_as_blob, base::Time dispatch_event_time) { - SettleInflightFetchRequestIfNeeded(); + 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 */); } -void ServiceWorkerSubresourceLoader::OnResponseLegacyBlob( - const ServiceWorkerResponse& response, - base::Time dispatch_event_time, - OnResponseLegacyBlobCallback callback) { - NOTREACHED(); -} - void ServiceWorkerSubresourceLoader::OnResponseStream( const ServiceWorkerResponse& response, blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream, base::Time dispatch_event_time) { - SettleInflightFetchRequestIfNeeded(); + 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)); } void ServiceWorkerSubresourceLoader::OnFallback( base::Time dispatch_event_time) { - SettleInflightFetchRequestIfNeeded(); + SettleFetchEventDispatch(blink::ServiceWorkerStatusCode::kOk); // When the request mode is CORS or CORS-with-forced-preflight and the origin // of the request URL is different from the security origin of the document, // we can't simply fallback to the network here. It is because the CORS @@ -356,12 +388,18 @@ void ServiceWorkerSubresourceLoader::OnFallback( (!resource_request_.request_initiator.has_value() || !resource_request_.request_initiator->IsSameOriginWith( url::Origin::Create(resource_request_.url)))) { + TRACE_EVENT_WITH_FLOW0( + "ServiceWorker", "ServiceWorkerSubresourceLoader::OnFallback", this, + TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); response_head_.was_fetched_via_service_worker = true; response_head_.was_fallback_required_by_service_worker = true; CommitResponseHeaders(); CommitCompleted(net::OK); return; } + TRACE_EVENT_WITH_FLOW0("ServiceWorker", + "ServiceWorkerSubresourceLoader::OnFallback", this, + TRACE_EVENT_FLAG_FLOW_IN); // Hand over to the network loader. network::mojom::URLLoaderClientPtr client; @@ -415,6 +453,7 @@ void ServiceWorkerSubresourceLoader::StartResponse( } response_head_.encoded_data_length = 0; url_loader_client_->OnReceiveRedirect(*redirect_info_, response_head_); + // Set status to complete, but we expect to restart in FollowRedirect. status_ = Status::kCompleted; return; } @@ -437,18 +476,9 @@ void ServiceWorkerSubresourceLoader::StartResponse( if (body_as_blob) { DCHECK(!body_as_stream); body_as_blob_ = std::move(body_as_blob); - mojo::ScopedDataPipeConsumerHandle data_pipe; - int error = ServiceWorkerLoaderHelpers::ReadBlobResponseBody( - &body_as_blob_, resource_request_.headers, - base::BindOnce(&ServiceWorkerSubresourceLoader::OnBlobReadingComplete, - weak_factory_.GetWeakPtr()), - &data_pipe); - if (error != net::OK) { - CommitCompleted(error); - return; - } - url_loader_client_->OnStartLoadingResponseBody(std::move(data_pipe)); - // We continue in OnBlobReadingComplete(). + body_as_blob_->ReadSideData(base::BindOnce( + &ServiceWorkerSubresourceLoader::OnBlobSideDataReadingComplete, + base::Unretained(this))); return; } @@ -461,11 +491,14 @@ void ServiceWorkerSubresourceLoader::CommitResponseHeaders() { DCHECK(url_loader_client_.is_bound()); status_ = Status::kSentHeader; // TODO(kinuko): Fill the ssl_info. - url_loader_client_->OnReceiveResponse(response_head_, - nullptr /* downloaded_file */); + url_loader_client_->OnReceiveResponse(response_head_); } void ServiceWorkerSubresourceLoader::CommitCompleted(int error_code) { + TRACE_EVENT_WITH_FLOW1( + "ServiceWorker", "ServiceWorkerSubresourceLoader::CommitCompleted", this, + TRACE_EVENT_FLAG_FLOW_IN, "error_code", net::ErrorToString(error_code)); + DCHECK_LT(status_, Status::kCompleted); DCHECK(url_loader_client_.is_bound()); stream_waiter_.reset(); @@ -479,7 +512,13 @@ void ServiceWorkerSubresourceLoader::CommitCompleted(int error_code) { // ServiceWorkerSubresourceLoader: URLLoader implementation ----------------- void ServiceWorkerSubresourceLoader::FollowRedirect( + const base::Optional<std::vector<std::string>>& + to_be_removed_request_headers, const base::Optional<net::HttpRequestHeaders>& modified_request_headers) { + TRACE_EVENT_WITH_FLOW1("ServiceWorker", + "ServiceWorkerSubresourceLoader::FollowRedirect", this, + TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, + "new_url", redirect_info_->new_url.spec()); DCHECK(!modified_request_headers.has_value()) << "Redirect with modified " "headers was not supported " "yet. crbug.com/845683"; @@ -488,7 +527,8 @@ void ServiceWorkerSubresourceLoader::FollowRedirect( bool should_clear_upload = false; net::RedirectUtil::UpdateHttpRequest( resource_request_.url, resource_request_.method, *redirect_info_, - &resource_request_.headers, &should_clear_upload); + modified_request_headers, &resource_request_.headers, + &should_clear_upload); if (should_clear_upload) resource_request_.request_body = nullptr; @@ -518,7 +558,34 @@ void ServiceWorkerSubresourceLoader::PauseReadingBodyFromNet() {} void ServiceWorkerSubresourceLoader::ResumeReadingBodyFromNet() {} +void ServiceWorkerSubresourceLoader::OnBlobSideDataReadingComplete( + const base::Optional<std::vector<uint8_t>>& metadata) { + TRACE_EVENT_WITH_FLOW1( + "ServiceWorker", + "ServiceWorkerSubresourceLoader::OnBlobSideDataReadingComplete", this, + TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "metadata size", + (metadata ? metadata->size() : 0)); + DCHECK(url_loader_client_); + if (metadata.has_value()) + url_loader_client_->OnReceiveCachedMetadata(metadata.value()); + mojo::ScopedDataPipeConsumerHandle data_pipe; + int error = ServiceWorkerLoaderHelpers::ReadBlobResponseBody( + &body_as_blob_, resource_request_.headers, + base::BindOnce(&ServiceWorkerSubresourceLoader::OnBlobReadingComplete, + weak_factory_.GetWeakPtr()), + &data_pipe); + if (error != net::OK) { + CommitCompleted(error); + return; + } + url_loader_client_->OnStartLoadingResponseBody(std::move(data_pipe)); + // We continue in OnBlobReadingComplete(). +} + void ServiceWorkerSubresourceLoader::OnBlobReadingComplete(int net_error) { + TRACE_EVENT_WITH_FLOW0( + "ServiceWorker", "ServiceWorkerSubresourceLoader::OnBlobReadingComplete", + this, TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); CommitCompleted(net_error); body_as_blob_.reset(); } @@ -529,18 +596,21 @@ void ServiceWorkerSubresourceLoader::OnBlobReadingComplete(int net_error) { void ServiceWorkerSubresourceLoaderFactory::Create( scoped_refptr<ControllerServiceWorkerConnector> controller_connector, scoped_refptr<network::SharedURLLoaderFactory> fallback_factory, - network::mojom::URLLoaderFactoryRequest request) { - new ServiceWorkerSubresourceLoaderFactory(std::move(controller_connector), - std::move(fallback_factory), - std::move(request)); + network::mojom::URLLoaderFactoryRequest request, + scoped_refptr<base::SequencedTaskRunner> task_runner) { + new ServiceWorkerSubresourceLoaderFactory( + std::move(controller_connector), std::move(fallback_factory), + std::move(request), std::move(task_runner)); } ServiceWorkerSubresourceLoaderFactory::ServiceWorkerSubresourceLoaderFactory( scoped_refptr<ControllerServiceWorkerConnector> controller_connector, scoped_refptr<network::SharedURLLoaderFactory> fallback_factory, - network::mojom::URLLoaderFactoryRequest request) + network::mojom::URLLoaderFactoryRequest request, + scoped_refptr<base::SequencedTaskRunner> task_runner) : controller_connector_(std::move(controller_connector)), - fallback_factory_(std::move(fallback_factory)) { + fallback_factory_(std::move(fallback_factory)), + task_runner_(std::move(task_runner)) { DCHECK(fallback_factory_); bindings_.AddBinding(this, std::move(request)); bindings_.set_connection_error_handler(base::BindRepeating( @@ -563,10 +633,10 @@ void ServiceWorkerSubresourceLoaderFactory::CreateLoaderAndStart( // network loader when fallback happens. When that happens the loader unbinds // the request, passes the request to the fallback factory, and // destructs itself (while the loader client continues to work). - new ServiceWorkerSubresourceLoader(std::move(request), routing_id, request_id, - options, resource_request, - std::move(client), traffic_annotation, - controller_connector_, fallback_factory_); + new ServiceWorkerSubresourceLoader( + std::move(request), routing_id, request_id, options, resource_request, + std::move(client), traffic_annotation, controller_connector_, + fallback_factory_, task_runner_); } void ServiceWorkerSubresourceLoaderFactory::Clone( 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 f209a0cd3b0..91b180b27af 100644 --- a/chromium/content/renderer/service_worker/service_worker_subresource_loader.h +++ b/chromium/content/renderer/service_worker/service_worker_subresource_loader.h @@ -8,16 +8,16 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/optional.h" +#include "base/scoped_observer.h" #include "base/time/time.h" #include "content/common/content_export.h" -#include "content/common/service_worker/dispatch_fetch_event_params.mojom.h" -#include "content/common/service_worker/service_worker_status_code.h" #include "content/renderer/service_worker/controller_service_worker_connector.h" #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "net/url_request/redirect_info.h" #include "services/network/public/mojom/url_loader_factory.mojom.h" +#include "third_party/blink/public/common/service_worker/service_worker_status_code.h" #include "third_party/blink/public/mojom/blob/blob.mojom.h" #include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h" #include "third_party/blink/public/mojom/service_worker/service_worker_stream_handle.mojom.h" @@ -51,11 +51,12 @@ class CONTENT_EXPORT ServiceWorkerSubresourceLoader network::mojom::URLLoaderClientPtr client, const net::MutableNetworkTrafficAnnotationTag& traffic_annotation, scoped_refptr<ControllerServiceWorkerConnector> controller_connector, - scoped_refptr<network::SharedURLLoaderFactory> fallback_factory); + scoped_refptr<network::SharedURLLoaderFactory> fallback_factory, + scoped_refptr<base::SequencedTaskRunner> task_runner); ~ServiceWorkerSubresourceLoader() override; - // ControllerServiceWorkerConnector::Observer overrdies: + // ControllerServiceWorkerConnector::Observer overrides: void OnConnectionClosed() override; private: @@ -65,9 +66,13 @@ class CONTENT_EXPORT ServiceWorkerSubresourceLoader void StartRequest(const network::ResourceRequest& resource_request); void DispatchFetchEvent(); - void OnFetchEventFinished(blink::mojom::ServiceWorkerEventStatus status, + void OnFetchEventFinished(base::Time request_dispatch_time, + blink::mojom::ServiceWorkerEventStatus status, base::Time dispatch_event_time); - void SettleInflightFetchRequestIfNeeded(); + // Called when this loader no longer needs to restart dispatching the fetch + // event on failure. Null |status| means the event dispatch was not attempted. + void SettleFetchEventDispatch( + base::Optional<blink::ServiceWorkerStatusCode> status); // mojom::ServiceWorkerFetchResponseCallback overrides: void OnResponse(const ServiceWorkerResponse& response, @@ -75,9 +80,6 @@ class CONTENT_EXPORT ServiceWorkerSubresourceLoader void OnResponseBlob(const ServiceWorkerResponse& response, blink::mojom::BlobPtr blob, base::Time dispatch_event_time) override; - void OnResponseLegacyBlob(const ServiceWorkerResponse& response, - base::Time dispatch_event_time, - OnResponseLegacyBlobCallback callback) override; void OnResponseStream( const ServiceWorkerResponse& response, blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream, @@ -89,7 +91,9 @@ class CONTENT_EXPORT ServiceWorkerSubresourceLoader blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream); // network::mojom::URLLoader overrides: - void FollowRedirect(const base::Optional<net::HttpRequestHeaders>& + void FollowRedirect(const base::Optional<std::vector<std::string>>& + to_be_removed_request_headers, + const base::Optional<net::HttpRequestHeaders>& modified_request_headers) override; void ProceedWithResponse() override; void SetPriority(net::RequestPriority priority, @@ -97,6 +101,8 @@ class CONTENT_EXPORT ServiceWorkerSubresourceLoader void PauseReadingBodyFromNet() override; void ResumeReadingBodyFromNet() override; + void OnBlobSideDataReadingComplete( + const base::Optional<std::vector<uint8_t>>& metadata); void OnBlobReadingComplete(int net_error); // Calls url_loader_client_->OnReceiveResponse() with |response_head_|. @@ -119,10 +125,12 @@ class CONTENT_EXPORT ServiceWorkerSubresourceLoader scoped_refptr<ControllerServiceWorkerConnector> controller_connector_; - // The request destined for the controller service worker. This is used - // separately from |resource_request_| for the restarting mechanism when the - // first attempt to dispatch to the controller failed. - std::unique_ptr<network::ResourceRequest> inflight_fetch_request_; + // Observes |controller_connector_| while this loader dispatches a fetch event + // to the controller. If a broken connection is observed, this loader attempts + // to restart the controller and dispatch the event again. + ScopedObserver<ControllerServiceWorkerConnector, + ServiceWorkerSubresourceLoader> + controller_connector_observer_; bool fetch_request_restarted_; // These are given by the constructor (as the params for @@ -149,6 +157,9 @@ class CONTENT_EXPORT ServiceWorkerSubresourceLoader }; Status status_ = Status::kNotStarted; + // The task runner where this loader is running. + scoped_refptr<base::SequencedTaskRunner> task_runner_; + base::WeakPtrFactory<ServiceWorkerSubresourceLoader> weak_factory_; DISALLOW_COPY_AND_ASSIGN(ServiceWorkerSubresourceLoader); @@ -167,10 +178,14 @@ class CONTENT_EXPORT ServiceWorkerSubresourceLoaderFactory // default URLLoaderFactory for network fallback. This should be the // URLLoaderFactory that directly goes to network without going through // any custom URLLoader factories. + // |task_runner| is the runner where this loader runs. (We need to pass + // this around because calling base::SequencedTaskRunnerHandle is + // prohibited in the renderer :() static void Create( scoped_refptr<ControllerServiceWorkerConnector> controller_connector, scoped_refptr<network::SharedURLLoaderFactory> fallback_factory, - network::mojom::URLLoaderFactoryRequest request); + network::mojom::URLLoaderFactoryRequest request, + scoped_refptr<base::SequencedTaskRunner> task_runner); ~ServiceWorkerSubresourceLoaderFactory() override; @@ -189,7 +204,8 @@ class CONTENT_EXPORT ServiceWorkerSubresourceLoaderFactory ServiceWorkerSubresourceLoaderFactory( scoped_refptr<ControllerServiceWorkerConnector> controller_connector, scoped_refptr<network::SharedURLLoaderFactory> fallback_factory, - network::mojom::URLLoaderFactoryRequest request); + network::mojom::URLLoaderFactoryRequest request, + scoped_refptr<base::SequencedTaskRunner> task_runner); void OnConnectionError(); @@ -200,6 +216,9 @@ class CONTENT_EXPORT ServiceWorkerSubresourceLoaderFactory mojo::BindingSet<network::mojom::URLLoaderFactory> bindings_; + // The task runner where this factory is running. + scoped_refptr<base::SequencedTaskRunner> task_runner_; + DISALLOW_COPY_AND_ASSIGN(ServiceWorkerSubresourceLoaderFactory); }; 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 1dd21ee8447..73f5661eb9a 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 @@ -6,6 +6,7 @@ #include "base/run_loop.h" #include "base/strings/string_number_conversions.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "content/common/service_worker/service_worker_container.mojom.h" #include "content/common/service_worker/service_worker_utils.h" @@ -25,11 +26,49 @@ #include "services/network/test/test_data_pipe_getter.h" #include "services/network/test/test_url_loader_client.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/mojom/blob/blob.mojom.h" +#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" #include "url/origin.h" namespace content { +namespace service_worker_subresource_loader_unittest { -namespace { +// A simple blob implementation for serving data stored in a vector. +class FakeBlob final : public blink::mojom::Blob { + public: + FakeBlob(base::Optional<std::vector<uint8_t>> side_data, std::string body) + : side_data_(std::move(side_data)), body_(std::move(body)) {} + + private: + // Implements blink::mojom::Blob. + void Clone(blink::mojom::BlobRequest) override { NOTREACHED(); } + void AsDataPipeGetter(network::mojom::DataPipeGetterRequest) override { + NOTREACHED(); + } + void ReadRange(uint64_t offset, + uint64_t length, + mojo::ScopedDataPipeProducerHandle handle, + blink::mojom::BlobReaderClientPtr client) override { + NOTREACHED(); + } + void ReadAll(mojo::ScopedDataPipeProducerHandle handle, + blink::mojom::BlobReaderClientPtr client) override { + EXPECT_TRUE(mojo::BlockingCopyFromString(body_, handle)); + if (client) { + client->OnCalculatedSize(body_.size(), body_.size()); + client->OnComplete(net::OK, body_.size()); + } + } + void ReadSideData(ReadSideDataCallback callback) override { + std::move(callback).Run(side_data_); + } + void GetInternalUUID(GetInternalUUIDCallback callback) override { + NOTREACHED(); + } + + base::Optional<std::vector<uint8_t>> side_data_; + std::string body_; +}; // A simple URLLoaderFactory that responds with status 200 to every request. // This is the default network loader factory for @@ -55,7 +94,7 @@ class FakeNetworkURLLoaderFactory final network::ResourceResponseHead response; response.headers = info.headers; response.headers->GetMimeType(&response.mime_type); - client->OnReceiveResponse(response, nullptr); + client->OnReceiveResponse(response); std::string body = "this body came from the network"; uint32_t bytes_written = body.size(); @@ -82,6 +121,48 @@ 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 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 ServiceWorkerResponse 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 */); + } + void CloseAllBindings() { bindings_.CloseAllBindings(); } // Tells this controller to abort the fetch event without a response. @@ -113,6 +194,14 @@ class FakeControllerServiceWorker : public mojom::ControllerServiceWorker { redirect_location_header_ = redirect_location_header; } + void RespondWithBlob(base::Optional<std::vector<uint8_t>> metadata, + std::string body) { + response_mode_ = ResponseMode::kBlob; + mojo::MakeStrongBinding( + std::make_unique<FakeBlob>(std::move(metadata), std::move(body)), + mojo::MakeRequest(&blob_)); + } + void ReadRequestBody(std::string* out_string) { ASSERT_TRUE(request_body_); std::vector<network::DataElement>* elements = @@ -143,7 +232,7 @@ class FakeControllerServiceWorker : public mojom::ControllerServiceWorker { // mojom::ControllerServiceWorker: void DispatchFetchEvent( - mojom::DispatchFetchEventParamsPtr params, + blink::mojom::DispatchFetchEventParamsPtr params, mojom::ServiceWorkerFetchResponseCallbackPtr response_callback, DispatchFetchEventCallback callback) override { EXPECT_FALSE(ServiceWorkerUtils::IsMainResourceType( @@ -155,6 +244,7 @@ class FakeControllerServiceWorker : public mojom::ControllerServiceWorker { switch (response_mode_) { case ResponseMode::kDefault: + response_callback->OnResponse(OkResponse(), base::Time::Now()); std::move(callback).Run( blink::mojom::ServiceWorkerEventStatus::COMPLETED, base::Time()); break; @@ -164,17 +254,13 @@ class FakeControllerServiceWorker : public mojom::ControllerServiceWorker { break; 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()); + OkResponse(), 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()); std::move(callback).Run( blink::mojom::ServiceWorkerEventStatus::COMPLETED, base::Time()); break; @@ -185,37 +271,14 @@ class FakeControllerServiceWorker : public mojom::ControllerServiceWorker { base::Time::Now()); break; 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(callback).Run( blink::mojom::ServiceWorkerEventStatus::REJECTED, base::Time::Now()); break; case ResponseMode::kRedirectResponse: { - auto headers = std::make_unique<ServiceWorkerHeaderMap>(); - (*headers)["Location"] = redirect_location_header_; response_callback->OnResponse( - 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 */), - base::Time::Now()); + RedirectResponse(redirect_location_header_), base::Time::Now()); std::move(callback).Run( blink::mojom::ServiceWorkerEventStatus::COMPLETED, base::Time()); break; @@ -245,6 +308,7 @@ class FakeControllerServiceWorker : public mojom::ControllerServiceWorker { kDefault, kAbort, kStream, + kBlob, kFallbackResponse, kErrorResponse, kRedirectResponse @@ -261,6 +325,9 @@ class FakeControllerServiceWorker : public mojom::ControllerServiceWorker { // For ResponseMode::kStream. blink::mojom::ServiceWorkerStreamHandlePtr stream_handle_; + // For ResponseMode::kBlob. + blink::mojom::BlobPtr blob_; + // For ResponseMode::kRedirectResponse std::string redirect_location_header_; @@ -284,7 +351,6 @@ class FakeServiceWorkerContainerHost return get_controller_service_worker_count_; } - private: // Implements mojom::ServiceWorkerContainerHost. void Register(const GURL& script_url, blink::mojom::ServiceWorkerRegistrationOptionsPtr options, @@ -312,12 +378,15 @@ class FakeServiceWorkerContainerHost } void CloneForWorker( mojom::ServiceWorkerContainerHostRequest request) override { - NOTIMPLEMENTED(); + bindings_.AddBinding(this, std::move(request)); } void Ping(PingCallback callback) override { NOTIMPLEMENTED(); } + void HintToUpdateServiceWorker() override { NOTIMPLEMENTED(); } + private: int get_controller_service_worker_count_ = 0; FakeControllerServiceWorker* fake_controller_; + mojo::BindingSet<mojom::ServiceWorkerContainerHost> bindings_; DISALLOW_COPY_AND_ASSIGN(FakeServiceWorkerContainerHost); }; @@ -340,7 +409,8 @@ CreateResponseInfoFromServiceWorker() { return head; } -} // namespace +const char kHistogramSubresourceFetchEvent[] = + "ServiceWorker.FetchEvent.Subresource.Status"; class ServiceWorkerSubresourceLoaderTest : public ::testing::Test { protected: @@ -361,13 +431,17 @@ class ServiceWorkerSubresourceLoaderTest : public ::testing::Test { network::mojom::URLLoaderFactoryPtr CreateSubresourceLoaderFactory() { if (!connector_) { + mojom::ServiceWorkerContainerHostPtrInfo host_ptr_info; + fake_container_host_.CloneForWorker(mojo::MakeRequest(&host_ptr_info)); connector_ = base::MakeRefCounted<ControllerServiceWorkerConnector>( - &fake_container_host_, nullptr /*controller_ptr*/, "" /*client_id*/); + std::move(host_ptr_info), nullptr /*controller_ptr*/, + "" /*client_id*/); } network::mojom::URLLoaderFactoryPtr service_worker_url_loader_factory; ServiceWorkerSubresourceLoaderFactory::Create( connector_, loader_factory_, - mojo::MakeRequest(&service_worker_url_loader_factory)); + mojo::MakeRequest(&service_worker_url_loader_factory), + blink::scheduler::GetSequencedTaskRunnerForTesting()); return service_worker_url_loader_factory; } @@ -466,6 +540,8 @@ class ServiceWorkerSubresourceLoaderTest : public ::testing::Test { }; TEST_F(ServiceWorkerSubresourceLoaderTest, Basic) { + base::HistogramTester histogram_tester; + network::mojom::URLLoaderFactoryPtr factory = CreateSubresourceLoaderFactory(); network::ResourceRequest request = @@ -479,10 +555,15 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, Basic) { EXPECT_EQ(request.method, fake_controller_.fetch_event_request().method); EXPECT_EQ(1, fake_controller_.fetch_event_count()); EXPECT_EQ(1, fake_container_host_.get_controller_service_worker_count()); + + client->RunUntilComplete(); + histogram_tester.ExpectUniqueSample(kHistogramSubresourceFetchEvent, + blink::ServiceWorkerStatusCode::kOk, 1); } TEST_F(ServiceWorkerSubresourceLoaderTest, Abort) { fake_controller_.AbortEventWithNoResponse(); + base::HistogramTester histogram_tester; network::mojom::URLLoaderFactoryPtr factory = CreateSubresourceLoaderFactory(); @@ -496,6 +577,9 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, Abort) { client->RunUntilComplete(); EXPECT_EQ(net::ERR_FAILED, client->completion_status().error_code); + histogram_tester.ExpectUniqueSample( + kHistogramSubresourceFetchEvent, + blink::ServiceWorkerStatusCode::kErrorAbort, 1); } TEST_F(ServiceWorkerSubresourceLoaderTest, DropController) { @@ -570,9 +654,10 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, NoController) { } // Make the connector have no controller. - connector_->ResetControllerConnection(nullptr); + connector_->UpdateController(nullptr); base::RunLoop().RunUntilIdle(); + base::HistogramTester histogram_tester; { // This should fallback to the network. network::ResourceRequest request = @@ -588,6 +673,9 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, NoController) { EXPECT_EQ(1, fake_controller_.fetch_event_count()); EXPECT_EQ(1, fake_container_host_.get_controller_service_worker_count()); } + + // No fetch event was dispatched, so no sample should be recorded. + histogram_tester.ExpectTotalCount(kHistogramSubresourceFetchEvent, 0); } TEST_F(ServiceWorkerSubresourceLoaderTest, DropController_RestartFetchEvent) { @@ -623,8 +711,11 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, DropController_RestartFetchEvent) { EXPECT_EQ(request.method, fake_controller_.fetch_event_request().method); EXPECT_EQ(2, fake_controller_.fetch_event_count()); EXPECT_EQ(1, fake_container_host_.get_controller_service_worker_count()); + client->RunUntilComplete(); } + base::HistogramTester histogram_tester; + network::ResourceRequest request = CreateRequest(GURL("https://www.example.com/foo3.png")); network::mojom::URLLoaderPtr loader; @@ -641,9 +732,12 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, DropController_RestartFetchEvent) { EXPECT_EQ(request.method, fake_controller_.fetch_event_request().method); EXPECT_EQ(3, fake_controller_.fetch_event_count()); EXPECT_EQ(2, fake_container_host_.get_controller_service_worker_count()); + histogram_tester.ExpectUniqueSample(kHistogramSubresourceFetchEvent, + blink::ServiceWorkerStatusCode::kOk, 1); } TEST_F(ServiceWorkerSubresourceLoaderTest, DropController_TooManyRestart) { + base::HistogramTester histogram_tester; // Simulate the container host fails to start a service worker. fake_container_host_.set_fake_controller(nullptr); @@ -663,9 +757,15 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, DropController_TooManyRestart) { EXPECT_EQ(2, fake_container_host_.get_controller_service_worker_count()); EXPECT_TRUE(client->has_received_completion()); EXPECT_EQ(net::ERR_FAILED, client->completion_status().error_code); + + histogram_tester.ExpectUniqueSample( + kHistogramSubresourceFetchEvent, + blink::ServiceWorkerStatusCode::kErrorStartWorkerFailed, 1); } TEST_F(ServiceWorkerSubresourceLoaderTest, StreamResponse) { + base::HistogramTester histogram_tester; + // Construct the Stream to respond with. const char kResponseBody[] = "Here is sample text for the Stream."; blink::mojom::ServiceWorkerStreamCallbackPtr stream_callback; @@ -705,9 +805,14 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, StreamResponse) { EXPECT_TRUE( mojo::BlockingCopyToString(client->response_body_release(), &response)); EXPECT_EQ(kResponseBody, response); + + histogram_tester.ExpectUniqueSample(kHistogramSubresourceFetchEvent, + blink::ServiceWorkerStatusCode::kOk, 1); } TEST_F(ServiceWorkerSubresourceLoaderTest, StreamResponse_Abort) { + base::HistogramTester histogram_tester; + // Construct the Stream to respond with. const char kResponseBody[] = "Here is sample text for the Stream."; blink::mojom::ServiceWorkerStreamCallbackPtr stream_callback; @@ -747,11 +852,94 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, StreamResponse_Abort) { EXPECT_TRUE( mojo::BlockingCopyToString(client->response_body_release(), &response)); EXPECT_EQ(kResponseBody, response); + + histogram_tester.ExpectUniqueSample(kHistogramSubresourceFetchEvent, + blink::ServiceWorkerStatusCode::kOk, 1); +} + +TEST_F(ServiceWorkerSubresourceLoaderTest, BlobResponse) { + base::HistogramTester histogram_tester; + + // Construct the Blob to respond with. + const std::string kResponseBody = "Here is sample text for the Blob."; + const std::vector<uint8_t> kMetadata = {0xE3, 0x81, 0x8F, 0xE3, 0x82, + 0x8D, 0xE3, 0x81, 0xBF, 0xE3, + 0x81, 0x86, 0xE3, 0x82, 0x80}; + fake_controller_.RespondWithBlob(kMetadata, kResponseBody); + + network::mojom::URLLoaderFactoryPtr factory = + CreateSubresourceLoaderFactory(); + + // Perform the request. + network::ResourceRequest request = + CreateRequest(GURL("https://www.example.com/foo.png")); + network::mojom::URLLoaderPtr loader; + std::unique_ptr<network::TestURLLoaderClient> client; + StartRequest(factory, request, &loader, &client); + client->RunUntilResponseReceived(); + + const network::ResourceResponseHead& info = client->response_head(); + ExpectResponseInfo(info, *CreateResponseInfoFromServiceWorker()); + + // Test the cached metadata. + client->RunUntilCachedMetadataReceived(); + EXPECT_EQ(client->cached_metadata(), + std::string(kMetadata.begin(), kMetadata.end())); + + client->RunUntilComplete(); + EXPECT_EQ(net::OK, client->completion_status().error_code); + + // Test the body. + std::string response; + EXPECT_TRUE(client->response_body().is_valid()); + EXPECT_TRUE( + mojo::BlockingCopyToString(client->response_body_release(), &response)); + EXPECT_EQ(kResponseBody, response); + + histogram_tester.ExpectUniqueSample(kHistogramSubresourceFetchEvent, + blink::ServiceWorkerStatusCode::kOk, 1); +} + +TEST_F(ServiceWorkerSubresourceLoaderTest, BlobResponseWithoutMetadata) { + base::HistogramTester histogram_tester; + + // Construct the Blob to respond with. + const std::string kResponseBody = "Here is sample text for the Blob."; + fake_controller_.RespondWithBlob(base::nullopt, kResponseBody); + + network::mojom::URLLoaderFactoryPtr factory = + CreateSubresourceLoaderFactory(); + + // Perform the request. + network::ResourceRequest request = + CreateRequest(GURL("https://www.example.com/foo.png")); + network::mojom::URLLoaderPtr loader; + std::unique_ptr<network::TestURLLoaderClient> client; + StartRequest(factory, request, &loader, &client); + client->RunUntilResponseReceived(); + + const network::ResourceResponseHead& info = client->response_head(); + ExpectResponseInfo(info, *CreateResponseInfoFromServiceWorker()); + + client->RunUntilComplete(); + EXPECT_EQ(net::OK, client->completion_status().error_code); + + // Test the body. + std::string response; + EXPECT_TRUE(client->response_body().is_valid()); + EXPECT_TRUE( + mojo::BlockingCopyToString(client->response_body_release(), &response)); + EXPECT_EQ(kResponseBody, response); + EXPECT_FALSE(client->has_received_cached_metadata()); + + histogram_tester.ExpectUniqueSample(kHistogramSubresourceFetchEvent, + blink::ServiceWorkerStatusCode::kOk, 1); } // Test when the service worker responds with network fallback. // i.e., does not call respondWith(). TEST_F(ServiceWorkerSubresourceLoaderTest, FallbackResponse) { + base::HistogramTester histogram_tester; fake_controller_.RespondWithFallback(); network::mojom::URLLoaderFactoryPtr factory = @@ -768,9 +956,13 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, FallbackResponse) { // OnFallback() should complete the network request using network loader. EXPECT_TRUE(client->has_received_completion()); EXPECT_FALSE(client->response_head().was_fetched_via_service_worker); + + histogram_tester.ExpectUniqueSample(kHistogramSubresourceFetchEvent, + blink::ServiceWorkerStatusCode::kOk, 1); } TEST_F(ServiceWorkerSubresourceLoaderTest, ErrorResponse) { + base::HistogramTester histogram_tester; fake_controller_.RespondWithError(); network::mojom::URLLoaderFactoryPtr factory = @@ -785,9 +977,12 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, ErrorResponse) { client->RunUntilComplete(); EXPECT_EQ(net::ERR_FAILED, client->completion_status().error_code); + histogram_tester.ExpectUniqueSample(kHistogramSubresourceFetchEvent, + blink::ServiceWorkerStatusCode::kOk, 1); } TEST_F(ServiceWorkerSubresourceLoaderTest, RedirectResponse) { + base::HistogramTester histogram_tester; fake_controller_.RespondWithRedirect("https://www.example.com/bar.png"); network::mojom::URLLoaderFactoryPtr factory = @@ -813,7 +1008,7 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, RedirectResponse) { // Redirect once more. fake_controller_.RespondWithRedirect("https://other.example.com/baz.png"); - loader->FollowRedirect(base::nullopt); + loader->FollowRedirect(base::nullopt, base::nullopt); client->RunUntilRedirectReceived(); EXPECT_EQ(net::OK, client->completion_status().error_code); @@ -832,7 +1027,7 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, RedirectResponse) { mojo::DataPipe data_pipe; fake_controller_.RespondWithStream(mojo::MakeRequest(&stream_callback), std::move(data_pipe.consumer_handle)); - loader->FollowRedirect(base::nullopt); + loader->FollowRedirect(base::nullopt, base::nullopt); client->RunUntilResponseReceived(); const network::ResourceResponseHead& info = client->response_head(); @@ -858,9 +1053,15 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, RedirectResponse) { EXPECT_TRUE( mojo::BlockingCopyToString(client->response_body_release(), &response)); EXPECT_EQ(kResponseBody, response); + + // There were 3 fetch events, so expect a count of 3. + histogram_tester.ExpectUniqueSample(kHistogramSubresourceFetchEvent, + blink::ServiceWorkerStatusCode::kOk, 3); } TEST_F(ServiceWorkerSubresourceLoaderTest, TooManyRedirects) { + base::HistogramTester histogram_tester; + int count = 1; std::string redirect_location = std::string("https://www.example.com/redirect_") + @@ -897,7 +1098,7 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, TooManyRedirects) { redirect_location = std::string("https://www.example.com/redirect_") + base::IntToString(count); fake_controller_.RespondWithRedirect(redirect_location); - loader->FollowRedirect(base::nullopt); + loader->FollowRedirect(base::nullopt, base::nullopt); } client->RunUntilComplete(); @@ -905,6 +1106,11 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, TooManyRedirects) { EXPECT_FALSE(client->has_received_redirect()); EXPECT_EQ(net::ERR_TOO_MANY_REDIRECTS, client->completion_status().error_code); + + // Expect a sample for each fetch event (kMaxRedirects + 1). + histogram_tester.ExpectUniqueSample(kHistogramSubresourceFetchEvent, + blink::ServiceWorkerStatusCode::kOk, + net::URLRequest::kMaxRedirects + 1); } // Test when the service worker responds with network fallback to CORS request. @@ -996,4 +1202,5 @@ TEST_F(ServiceWorkerSubresourceLoaderTest, FallbackWithRequestBody_DataPipe) { RunFallbackWithRequestBodyTest(std::move(request_body), kData); } +} // namespace service_worker_subresource_loader_unittest } // namespace content 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 83b78f2fb59..f61a8b98a5d 100644 --- a/chromium/content/renderer/service_worker/service_worker_timeout_timer.cc +++ b/chromium/content/renderer/service_worker/service_worker_timeout_timer.cc @@ -7,8 +7,8 @@ #include "base/stl_util.h" #include "base/time/default_tick_clock.h" #include "base/time/time.h" -#include "content/common/service_worker/service_worker_utils.h" #include "services/network/public/cpp/features.h" +#include "third_party/blink/public/common/service_worker/service_worker_utils.h" namespace content { @@ -93,20 +93,20 @@ void ServiceWorkerTimeoutTimer::EndEvent(int event_id) { void ServiceWorkerTimeoutTimer::PushPendingTask( base::OnceClosure pending_task) { - DCHECK(ServiceWorkerUtils::IsServicificationEnabled()); + DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled()); DCHECK(did_idle_timeout()); pending_tasks_.emplace(std::move(pending_task)); } void ServiceWorkerTimeoutTimer::SetIdleTimerDelayToZero() { - DCHECK(ServiceWorkerUtils::IsServicificationEnabled()); + DCHECK(blink::ServiceWorkerUtils::IsServicificationEnabled()); zero_idle_timer_delay_ = true; if (inflight_events_.empty()) MaybeTriggerIdleTimer(); } void ServiceWorkerTimeoutTimer::UpdateStatus() { - if (!ServiceWorkerUtils::IsServicificationEnabled()) + if (!blink::ServiceWorkerUtils::IsServicificationEnabled()) return; base::TimeTicks now = tick_clock_->NowTicks(); 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 540a9912af8..27396c1bea6 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 @@ -10,9 +10,9 @@ #include "base/test/scoped_feature_list.h" #include "base/test/test_mock_time_task_runner.h" #include "base/time/tick_clock.h" -#include "content/common/service_worker/service_worker_utils.h" #include "services/network/public/cpp/features.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/service_worker/service_worker_utils.h" namespace content { @@ -59,7 +59,7 @@ class ServiceWorkerTimeoutTimerTest : public testing::Test { void EnableServicification() { feature_list_.InitWithFeatures({network::features::kNetworkService}, {}); - ASSERT_TRUE(ServiceWorkerUtils::IsServicificationEnabled()); + ASSERT_TRUE(blink::ServiceWorkerUtils::IsServicificationEnabled()); } base::TestMockTimeTaskRunner* task_runner() { return task_runner_.get(); } @@ -273,7 +273,8 @@ TEST_F(ServiceWorkerTimeoutTimerTest, SetIdleTimerDelayToZero) { } TEST_F(ServiceWorkerTimeoutTimerTest, NonS13nServiceWorker) { - ASSERT_FALSE(ServiceWorkerUtils::IsServicificationEnabled()); + if (blink::ServiceWorkerUtils::IsServicificationEnabled()) + return; MockEvent event; { 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 3065d0e543e..ca15fab9670 100644 --- a/chromium/content/renderer/service_worker/service_worker_type_converters.cc +++ b/chromium/content/renderer/service_worker/service_worker_type_converters.cc @@ -72,15 +72,9 @@ blink::WebPaymentMethodData TypeConverter<blink::WebPaymentMethodData, payments::mojom::PaymentMethodDataPtr>:: Convert(const payments::mojom::PaymentMethodDataPtr& input) { + DCHECK(!input->supported_method.empty()); blink::WebPaymentMethodData output; - - output.supported_methods = - blink::WebVector<blink::WebString>(input->supported_methods.size()); - for (size_t i = 0; i < input->supported_methods.size(); i++) { - output.supported_methods[i] = - blink::WebString::FromUTF8(input->supported_methods[i]); - } - + output.supported_method = blink::WebString::FromUTF8(input->supported_method); output.stringified_data = blink::WebString::FromUTF8(input->stringified_data); return output; @@ -111,14 +105,11 @@ blink::WebPaymentDetailsModifier TypeConverter<blink::WebPaymentDetailsModifier, payments::mojom::PaymentDetailsModifierPtr>:: Convert(const payments::mojom::PaymentDetailsModifierPtr& input) { + DCHECK(!input->method_data->supported_method.empty()); blink::WebPaymentDetailsModifier output; - output.supported_methods = blink::WebVector<blink::WebString>( - input->method_data->supported_methods.size()); - for (size_t i = 0; i < input->method_data->supported_methods.size(); i++) { - output.supported_methods[i] = - blink::WebString::FromUTF8(input->method_data->supported_methods[i]); - } + output.supported_method = + blink::WebString::FromUTF8(input->method_data->supported_method); output.total = mojo::ConvertTo<blink::WebPaymentItem>(input->total); 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 b5ea9ca7bcb..796c7467632 100644 --- a/chromium/content/renderer/service_worker/service_worker_type_converters.h +++ b/chromium/content/renderer/service_worker/service_worker_type_converters.h @@ -5,13 +5,13 @@ #ifndef CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_TYPE_CONVERTERS_H_ #define CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_TYPE_CONVERTERS_H_ -#include "content/common/service_worker/service_worker_event_dispatcher.mojom.h" -#include "content/common/service_worker/service_worker_status_code.h" +#include "content/common/service_worker/service_worker.mojom.h" +#include "third_party/blink/public/common/service_worker/service_worker_status_code.h" #include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h" #include "third_party/blink/public/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/serviceworker/web_service_worker_context_proxy.h" +#include "third_party/blink/public/web/modules/service_worker/web_service_worker_context_proxy.h" namespace mojo { 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 7741366348f..020f30164d2 100644 --- a/chromium/content/renderer/service_worker/service_worker_type_util.cc +++ b/chromium/content/renderer/service_worker/service_worker_type_util.cc @@ -10,8 +10,8 @@ #include "base/strings/utf_string_conversions.h" #include "content/common/service_worker/service_worker_types.h" #include "storage/common/blob_storage/blob_handle.h" -#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_request.h" -#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_response.h" +#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_request.h" +#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_response.h" #include "third_party/blink/public/platform/web_http_header_visitor.h" #include "third_party/blink/public/platform/web_string.h" diff --git a/chromium/content/renderer/service_worker/thread_safe_script_container.h b/chromium/content/renderer/service_worker/thread_safe_script_container.h index 9e658ffe675..c0e8d6dbff2 100644 --- a/chromium/content/renderer/service_worker/thread_safe_script_container.h +++ b/chromium/content/renderer/service_worker/thread_safe_script_container.h @@ -12,7 +12,7 @@ #include "base/synchronization/condition_variable.h" #include "base/synchronization/lock.h" #include "content/common/content_export.h" -#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_installed_scripts_manager.h" +#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_installed_scripts_manager.h" 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 2d3322a6f44..dba3fc329f7 100644 --- a/chromium/content/renderer/service_worker/web_service_worker_impl.cc +++ b/chromium/content/renderer/service_worker/web_service_worker_impl.cc @@ -11,7 +11,7 @@ #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" -#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_proxy.h" +#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_proxy.h" #include "third_party/blink/public/platform/web_runtime_features.h" #include "third_party/blink/public/platform/web_string.h" diff --git a/chromium/content/renderer/service_worker/web_service_worker_impl.h b/chromium/content/renderer/service_worker/web_service_worker_impl.h index 60e7f7e8584..8e183fa77f5 100644 --- a/chromium/content/renderer/service_worker/web_service_worker_impl.h +++ b/chromium/content/renderer/service_worker/web_service_worker_impl.h @@ -15,7 +15,7 @@ #include "content/common/content_export.h" #include "mojo/public/cpp/bindings/associated_binding.h" #include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h" -#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker.h" +#include "third_party/blink/public/platform/modules/service_worker/web_service_worker.h" #include "third_party/blink/public/web/web_frame.h" namespace blink { @@ -51,8 +51,8 @@ class ServiceWorkerProviderContext; // blink::mojom::ServiceWorkerObjectInfo, otherwise reuse the existing one. // // WebServiceWorkerImpl holds a Mojo connection (|host_|). The connection keeps -// the ServiceWorkerHandle in the browser process alive, which in turn keeps the -// relevant ServiceWorkerVersion alive. +// the ServiceWorkerObjectHost in the browser process alive, which in turn keeps +// the relevant ServiceWorkerVersion alive. class CONTENT_EXPORT WebServiceWorkerImpl : public blink::mojom::ServiceWorkerObject, public blink::WebServiceWorker, @@ -93,11 +93,11 @@ class CONTENT_EXPORT WebServiceWorkerImpl // worker thread for service worker execution contexts. // // |host_| keeps the Mojo connection to the - // browser-side ServiceWorkerHandle, whose lifetime is bound + // browser-side ServiceWorkerObjectHost, whose lifetime is bound // to |host_| via the Mojo connection. blink::mojom::ServiceWorkerObjectHostAssociatedPtr host_; // |binding_| keeps the Mojo binding to serve its other Mojo endpoint (i.e. - // the caller end) held by the content::ServiceWorkerHandle in the browser + // the caller end) held by the content::ServiceWorkerObjectHost in the browser // process. mojo::AssociatedBinding<blink::mojom::ServiceWorkerObject> binding_; diff --git a/chromium/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.h b/chromium/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.h index d9e7d0abe4c..5054d4830a0 100644 --- a/chromium/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.h +++ b/chromium/content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.h @@ -11,7 +11,7 @@ #include "base/single_thread_task_runner.h" #include "content/renderer/service_worker/thread_safe_script_container.h" #include "third_party/blink/public/mojom/service_worker/service_worker_installed_scripts_manager.mojom.h" -#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_installed_scripts_manager.h" +#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_installed_scripts_manager.h" namespace content { diff --git a/chromium/content/renderer/service_worker/web_service_worker_provider_impl.cc b/chromium/content/renderer/service_worker/web_service_worker_provider_impl.cc index 2813f6b69f4..f4ddf8af5be 100644 --- a/chromium/content/renderer/service_worker/web_service_worker_provider_impl.cc +++ b/chromium/content/renderer/service_worker/web_service_worker_provider_impl.cc @@ -16,7 +16,7 @@ #include "third_party/blink/public/common/message_port/message_port_channel.h" #include "third_party/blink/public/mojom/service_worker/service_worker_provider_type.mojom.h" #include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h" -#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_provider_client.h" +#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_provider_client.h" #include "third_party/blink/public/platform/web_url.h" using blink::WebURL; @@ -230,7 +230,7 @@ void WebServiceWorkerProviderImpl::OnRegistered( blink::mojom::ServiceWorkerRegistrationObjectInfoPtr registration) { TRACE_EVENT_ASYNC_END2( "ServiceWorker", "WebServiceWorkerProviderImpl::RegisterServiceWorker", - this, "Error", ServiceWorkerUtils::ErrorTypeToString(error), "Message", + this, "Error", ServiceWorkerUtils::MojoEnumToString(error), "Message", error_msg ? *error_msg : "Success"); if (error != blink::mojom::ServiceWorkerErrorType::kNone) { DCHECK(error_msg); @@ -256,7 +256,7 @@ void WebServiceWorkerProviderImpl::OnDidGetRegistration( blink::mojom::ServiceWorkerRegistrationObjectInfoPtr registration) { TRACE_EVENT_ASYNC_END2("ServiceWorker", "WebServiceWorkerProviderImpl::GetRegistration", this, - "Error", ServiceWorkerUtils::ErrorTypeToString(error), + "Error", ServiceWorkerUtils::MojoEnumToString(error), "Message", error_msg ? *error_msg : "Success"); if (error != blink::mojom::ServiceWorkerErrorType::kNone) { DCHECK(error_msg); @@ -292,7 +292,7 @@ void WebServiceWorkerProviderImpl::OnDidGetRegistrations( infos) { TRACE_EVENT_ASYNC_END2("ServiceWorker", "WebServiceWorkerProviderImpl::GetRegistrations", this, - "Error", ServiceWorkerUtils::ErrorTypeToString(error), + "Error", ServiceWorkerUtils::MojoEnumToString(error), "Message", error_msg ? *error_msg : "Success"); if (error != blink::mojom::ServiceWorkerErrorType::kNone) { DCHECK(error_msg); diff --git a/chromium/content/renderer/service_worker/web_service_worker_provider_impl.h b/chromium/content/renderer/service_worker/web_service_worker_provider_impl.h index b496a3f2f1a..9c73253eee5 100644 --- a/chromium/content/renderer/service_worker/web_service_worker_provider_impl.h +++ b/chromium/content/renderer/service_worker/web_service_worker_provider_impl.h @@ -15,7 +15,7 @@ #include "third_party/blink/public/common/message_port/transferable_message.h" #include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom.h" #include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h" -#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_provider.h" +#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_provider.h" #include "third_party/blink/public/platform/web_feature.mojom.h" namespace blink { diff --git a/chromium/content/renderer/service_worker/web_service_worker_registration_impl.cc b/chromium/content/renderer/service_worker/web_service_worker_registration_impl.cc index 8c78ad3263a..bd98361eb53 100644 --- a/chromium/content/renderer/service_worker/web_service_worker_registration_impl.cc +++ b/chromium/content/renderer/service_worker/web_service_worker_registration_impl.cc @@ -13,9 +13,9 @@ #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_provider_impl.h" -#include "third_party/blink/public/platform/modules/serviceworker/web_navigation_preload_state.h" -#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_error.h" -#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_registration_proxy.h" +#include "third_party/blink/public/platform/modules/service_worker/web_navigation_preload_state.h" +#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_error.h" +#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_registration_proxy.h" namespace content { @@ -150,21 +150,8 @@ WebServiceWorkerRegistrationImpl::UpdateViaCache() const { void WebServiceWorkerRegistrationImpl::Update( std::unique_ptr<WebServiceWorkerUpdateCallbacks> callbacks) { - host_->Update(base::BindOnce( - [](std::unique_ptr<WebServiceWorkerUpdateCallbacks> callbacks, - blink::mojom::ServiceWorkerErrorType error, - const base::Optional<std::string>& error_msg) { - if (error != blink::mojom::ServiceWorkerErrorType::kNone) { - DCHECK(error_msg); - callbacks->OnError(blink::WebServiceWorkerError( - error, blink::WebString::FromUTF8(*error_msg))); - return; - } - - DCHECK(!error_msg); - callbacks->OnSuccess(); - }, - std::move(callbacks))); + host_->Update(base::BindOnce(&WebServiceWorkerRegistrationImpl::OnUpdated, + this, std::move(callbacks))); } void WebServiceWorkerRegistrationImpl::Unregister( @@ -321,6 +308,19 @@ WebServiceWorkerRegistrationImpl::GetOrCreateServiceWorkerObject( return service_worker; } +void WebServiceWorkerRegistrationImpl::OnUpdated( + std::unique_ptr<WebServiceWorkerUpdateCallbacks> callbacks, + blink::mojom::ServiceWorkerErrorType error, + const base::Optional<std::string>& error_msg) { + if (error != blink::mojom::ServiceWorkerErrorType::kNone) { + callbacks->OnError(blink::WebServiceWorkerError( + error, blink::WebString::FromUTF8(*error_msg))); + return; + } + callbacks->OnSuccess(WebServiceWorkerRegistrationImpl::CreateHandle( + base::WrapRefCounted(this))); +} + void WebServiceWorkerRegistrationImpl::SetVersionAttributes( int changed_mask, blink::mojom::ServiceWorkerObjectInfoPtr installing, diff --git a/chromium/content/renderer/service_worker/web_service_worker_registration_impl.h b/chromium/content/renderer/service_worker/web_service_worker_registration_impl.h index 4405d0415b7..e57e36208f4 100644 --- a/chromium/content/renderer/service_worker/web_service_worker_registration_impl.h +++ b/chromium/content/renderer/service_worker/web_service_worker_registration_impl.h @@ -19,7 +19,7 @@ #include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom.h" #include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h" #include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h" -#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_registration.h" +#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_registration.h" namespace blink { class WebServiceWorkerRegistrationProxy; @@ -123,6 +123,10 @@ class CONTENT_EXPORT WebServiceWorkerRegistrationImpl scoped_refptr<WebServiceWorkerImpl> GetOrCreateServiceWorkerObject( blink::mojom::ServiceWorkerObjectInfoPtr info); + void OnUpdated(std::unique_ptr<WebServiceWorkerUpdateCallbacks> callbacks, + blink::mojom::ServiceWorkerErrorType error, + const base::Optional<std::string>& error_msg); + // Implements blink::mojom::ServiceWorkerRegistrationObject. void SetVersionAttributes( int changed_mask, diff --git a/chromium/content/renderer/shared_worker/OWNERS b/chromium/content/renderer/shared_worker/OWNERS index 595a38572a7..6bda8b5e83f 100644 --- a/chromium/content/renderer/shared_worker/OWNERS +++ b/chromium/content/renderer/shared_worker/OWNERS @@ -1,3 +1,4 @@ +falken@chromium.org horo@chromium.org nhiroki@chromium.org 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 edf1d066262..a2be7d7cdef 100644 --- a/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.cc +++ b/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.cc @@ -12,27 +12,34 @@ #include "base/threading/thread_task_runner_handle.h" #include "content/child/scoped_child_process_reference.h" #include "content/common/possibly_associated_wrapper_shared_url_loader_factory.h" -#include "content/common/service_worker/service_worker_utils.h" +#include "content/common/url_loader_factory_bundle.h" #include "content/public/common/appcache_info.h" #include "content/public/common/content_client.h" #include "content/public/common/content_features.h" #include "content/public/common/origin_util.h" +#include "content/public/common/renderer_preferences.h" #include "content/public/renderer/content_renderer_client.h" #include "content/renderer/appcache/appcache_dispatcher.h" #include "content/renderer/appcache/web_application_cache_host_impl.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_worker_fetch_context_impl.h" #include "content/renderer/render_thread_impl.h" #include "content/renderer/renderer_blink_platform_impl.h" #include "content/renderer/service_worker/service_worker_network_provider.h" #include "content/renderer/service_worker/service_worker_provider_context.h" -#include "content/renderer/service_worker/worker_fetch_context_impl.h" #include "ipc/ipc_message_macros.h" +#include "services/network/public/cpp/features.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" #include "third_party/blink/public/common/message_port/message_port_channel.h" +#include "third_party/blink/public/common/privacy_preferences.h" +#include "third_party/blink/public/common/service_worker/service_worker_utils.h" #include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h" #include "third_party/blink/public/platform/interface_provider.h" -#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_network_provider.h" +#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h" +#include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/public/platform/url_conversion.h" #include "third_party/blink/public/platform/web_security_origin.h" #include "third_party/blink/public/web/web_shared_worker.h" @@ -98,14 +105,16 @@ class WebServiceWorkerNetworkProviderForSharedWorker // request and break the assumptions of the renderer. if (request.GetRequestContext() != blink::WebURLRequest::kRequestContextSharedWorker && - !provider_->IsControlledByServiceWorker()) { + provider_->IsControlledByServiceWorker() == + blink::mojom::ControllerServiceWorkerMode::kNoController) { request.SetSkipServiceWorker(true); } } int ProviderID() const override { return provider_->provider_id(); } - bool HasControllerServiceWorker() override { + blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker() + override { return provider_->IsControlledByServiceWorker(); } @@ -119,10 +128,11 @@ class WebServiceWorkerNetworkProviderForSharedWorker std::unique_ptr<blink::WebURLLoader> CreateURLLoader( const blink::WebURLRequest& request, - scoped_refptr<base::SingleThreadTaskRunner> task_runner) override { + std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle> + task_runner_handle) override { // S13nServiceWorker: // We only install our own URLLoader if Servicification is enabled. - if (!ServiceWorkerUtils::IsServicificationEnabled()) + if (!blink::ServiceWorkerUtils::IsServicificationEnabled()) return nullptr; RenderThreadImpl* render_thread = RenderThreadImpl::current(); @@ -137,20 +147,28 @@ class WebServiceWorkerNetworkProviderForSharedWorker // TODO(crbug.com/796425): Temporarily wrap the raw // mojom::URLLoaderFactory pointer into SharedURLLoaderFactory. return std::make_unique<WebURLLoaderImpl>( - render_thread->resource_dispatcher(), std::move(task_runner), + render_thread->resource_dispatcher(), std::move(task_runner_handle), base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( provider_->script_loader_factory())); } - // Otherwise, it's an importScript. Use the subresource loader factory. + // Otherwise, it's an importScript. Use the subresource loader factory if + // it exists (we are controlled by a service worker). if (!provider_->context() || !provider_->context()->GetSubresourceLoaderFactory()) { return nullptr; } - // If it's not for HTTP or HTTPS, no need to intercept the request. - if (!GURL(request.Url()).SchemeIsHTTPOrHTTPS()) + // If the URL is not http(s) or otherwise whitelisted, do not intercept the + // request. Schemes like 'blob' and 'file' are not eligible to be + // intercepted by service workers. + // TODO(falken): Let ServiceWorkerSubresourceLoaderFactory handle the + // request and move this check there (i.e., for such URLs, it should use + // its fallback factory). + if (!GURL(request.Url()).SchemeIsHTTPOrHTTPS() && + !OriginCanAccessServiceWorkers(request.Url())) { return nullptr; + } // If GetSkipServiceWorker() returns true, do not intercept the request. if (request.GetSkipServiceWorker()) @@ -162,7 +180,7 @@ class WebServiceWorkerNetworkProviderForSharedWorker // pointer into SharedURLLoaderFactory. return std::make_unique<WebURLLoaderImpl>( RenderThreadImpl::current()->resource_dispatcher(), - std::move(task_runner), + std::move(task_runner_handle), base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( provider_->context()->GetSubresourceLoaderFactory())); } @@ -178,18 +196,21 @@ EmbeddedSharedWorkerStub::EmbeddedSharedWorkerStub( mojom::SharedWorkerInfoPtr info, bool pause_on_start, const base::UnguessableToken& devtools_worker_token, + const RendererPreferences& renderer_preferences, blink::mojom::WorkerContentSettingsProxyPtr content_settings, mojom::ServiceWorkerProviderInfoForSharedWorkerPtr service_worker_provider_info, network::mojom::URLLoaderFactoryAssociatedPtrInfo script_loader_factory_info, + std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders, mojom::SharedWorkerHostPtr host, mojom::SharedWorkerRequest request, service_manager::mojom::InterfaceProviderPtr interface_provider) : binding_(this, std::move(request)), host_(std::move(host)), name_(info->name), - url_(info->url) { + url_(info->url), + renderer_preferences_(renderer_preferences) { impl_ = blink::WebSharedWorker::Create(this); if (pause_on_start) { // Pause worker context when it starts and wait until either DevTools client @@ -200,11 +221,40 @@ EmbeddedSharedWorkerStub::EmbeddedSharedWorkerStub( service_worker_provider_info_ = std::move(service_worker_provider_info); script_loader_factory_info_ = std::move(script_loader_factory_info); + // Make the factory bundle. + loader_factories_ = base::MakeRefCounted<HostChildURLLoaderFactoryBundle>( + impl_->GetTaskRunner(blink::TaskType::kInternalLoading)); + // In some tests |render_thread| could be null. + if (RenderThreadImpl* render_thread = RenderThreadImpl::current()) { + loader_factories_->Update(render_thread->blink_platform_impl() + ->CreateDefaultURLLoaderFactoryBundle() + ->PassInterface(), + base::nullopt /* subresource_overrides */); + } + + if (subresource_loaders) { + loader_factories_->Update(std::make_unique<ChildURLLoaderFactoryBundleInfo>( + std::move(subresource_loaders)), + base::nullopt /* subresource_overrides */); + } + + // It is important to understand the default factory of |loader_factories_|. + // |loader_factories_| was made from CreateDefaultURLLoaderFactoryBundle, + // which does not set a default factory, and |subresource_loaders|, whose + // default factory is the direct network factory (as SharedWorkerHost sets it + // that way). Therefore, the default factory either does not exist or is the + // direct network factory. So we don't need to call CloneWithoutDefault() to + // bypass features like AppCache, unlike the bundle created for a frame. + impl_->StartWorkerContext( url_, blink::WebString::FromUTF8(name_), blink::WebString::FromUTF8(info->content_security_policy), info->content_security_policy_type, info->creation_address_space, - devtools_worker_token, content_settings.PassInterface().PassHandle(), + devtools_worker_token, + blink::PrivacyPreferences(renderer_preferences_.enable_do_not_track, + renderer_preferences_.enable_referrers), + loader_factories_, + content_settings.PassInterface().PassHandle(), interface_provider.PassInterface().PassHandle()); // If the host drops its connection, then self-destruct. @@ -275,20 +325,11 @@ EmbeddedSharedWorkerStub::CreateApplicationCacheHost( std::unique_ptr<blink::WebServiceWorkerNetworkProvider> EmbeddedSharedWorkerStub::CreateServiceWorkerNetworkProvider() { - scoped_refptr<network::SharedURLLoaderFactory> fallback_factory; - // current() may be null in tests. - if (RenderThreadImpl* render_thread = RenderThreadImpl::current()) { - scoped_refptr<ChildURLLoaderFactoryBundle> bundle = - render_thread->blink_platform_impl() - ->CreateDefaultURLLoaderFactoryBundle(); - fallback_factory = network::SharedURLLoaderFactory::Create( - bundle->CloneWithoutDefaultFactory()); - } - std::unique_ptr<ServiceWorkerNetworkProvider> provider = ServiceWorkerNetworkProvider::CreateForSharedWorker( std::move(service_worker_provider_info_), - std::move(script_loader_factory_info_), std::move(fallback_factory)); + std::move(script_loader_factory_info_), loader_factories_); + return std::make_unique<WebServiceWorkerNetworkProviderForSharedWorker>( std::move(provider), IsOriginSecure(url_)); } @@ -313,33 +354,46 @@ EmbeddedSharedWorkerStub::CreateWorkerFetchContext( web_network_provider) ->provider() ->context(); - mojom::ServiceWorkerWorkerClientRequest request = - context->CreateWorkerClientRequest(); + + mojom::ServiceWorkerWorkerClientRegistryPtrInfo + worker_client_registry_ptr_info; + context->CloneWorkerClientRegistry( + mojo::MakeRequest(&worker_client_registry_ptr_info)); + + mojom::ServiceWorkerWorkerClientPtr worker_client_ptr; + mojom::ServiceWorkerWorkerClientRequest worker_client_request = + mojo::MakeRequest(&worker_client_ptr); + context->RegisterWorkerClient(std::move(worker_client_ptr)); mojom::ServiceWorkerContainerHostPtrInfo container_host_ptr_info; - // TODO(horo): Use this host pointer also when S13nServiceWorker is not - // enabled once we support navigator.serviceWorker on shared workers: - // crbug.com/371690. Currently we use this only to call - // GetControllerServiceWorker() from the worker thread if S13nServiceWorker - // is enabled. - if (ServiceWorkerUtils::IsServicificationEnabled()) + if (blink::ServiceWorkerUtils::IsServicificationEnabled()) container_host_ptr_info = context->CloneContainerHostPtrInfo(); - scoped_refptr<ChildURLLoaderFactoryBundle> url_loader_factory_bundle = - RenderThreadImpl::current() - ->blink_platform_impl() - ->CreateDefaultURLLoaderFactoryBundle(); - auto worker_fetch_context = std::make_unique<WorkerFetchContextImpl>( - std::move(request), std::move(container_host_ptr_info), - url_loader_factory_bundle->Clone(), - url_loader_factory_bundle->CloneWithoutDefaultFactory(), + // We know |loader_factories_|'s default factory is not a feature like + // AppCache, so it's OK to call Clone() and not CloneWithoutDefault() to get + // the fallback factory. We don't want to call CloneWithoutDefault() because + // the default is a NetworkService-backed factory with auto-reconnect + // when NetworkService is enabled (it will support auto-reconnect once + // https://crbug.com/848256 is addressed). See comments in the constructor. + // + // TODO(falken): We might need to set the default factory of + // |loader_factories_| to AppCache if requests from this shared worker are + // supposed to go through AppCache. + std::unique_ptr<network::SharedURLLoaderFactoryInfo> fallback_factory = + loader_factories_->Clone(); + + auto worker_fetch_context = std::make_unique<WebWorkerFetchContextImpl>( + std::move(renderer_preferences_), 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), GetContentClient()->renderer()->CreateURLLoaderThrottleProvider( URLLoaderThrottleProviderType::kWorker), GetContentClient() ->renderer() ->CreateWebSocketHandshakeThrottleProvider(), ChildThreadImpl::current()->thread_safe_sender(), - RenderThreadImpl::current()->GetIOTaskRunner()); + ChildThreadImpl::current()->GetConnector()->Clone()); // TODO(horo): To get the correct first_party_to_cookies for the shared // worker, we need to check the all documents bounded by the shared worker. @@ -353,13 +407,11 @@ EmbeddedSharedWorkerStub::CreateWorkerFetchContext( // https://w3c.github.io/webappsec-secure-contexts/#examples-shared-workers worker_fetch_context->set_is_secure_context(IsOriginSecure(url_)); worker_fetch_context->set_origin_url(url_.GetOrigin()); - if (web_network_provider) { - worker_fetch_context->set_service_worker_provider_id( - web_network_provider->ProviderID()); - worker_fetch_context->set_is_controlled_by_service_worker( - web_network_provider->HasControllerServiceWorker()); - } + worker_fetch_context->set_service_worker_provider_id(context->provider_id()); + worker_fetch_context->set_is_controlled_by_service_worker( + context->IsControlledByServiceWorker()); worker_fetch_context->set_client_id(context->client_id()); + return std::move(worker_fetch_context); } 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 25b8d13f4d8..6014d199411 100644 --- a/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.h +++ b/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.h @@ -15,7 +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/renderer/child_message_filter.h" +#include "content/public/common/renderer_preferences.h" #include "ipc/ipc_listener.h" #include "mojo/public/cpp/bindings/binding.h" #include "services/network/public/mojom/url_loader_factory.mojom.h" @@ -40,6 +40,8 @@ class MessagePortChannel; } namespace content { +class HostChildURLLoaderFactoryBundle; +class URLLoaderFactoryBundleInfo; class WebApplicationCacheHostImpl; // A stub class to receive IPC from browser process and talk to @@ -58,11 +60,13 @@ class EmbeddedSharedWorkerStub : public blink::WebSharedWorkerClient, mojom::SharedWorkerInfoPtr info, bool pause_on_start, const base::UnguessableToken& devtools_worker_token, + const RendererPreferences& renderer_preferences, blink::mojom::WorkerContentSettingsProxyPtr content_settings, mojom::ServiceWorkerProviderInfoForSharedWorkerPtr service_worker_provider_info, network::mojom::URLLoaderFactoryAssociatedPtrInfo script_loader_factory_info, + std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders, mojom::SharedWorkerHostPtr host, mojom::SharedWorkerRequest request, service_manager::mojom::InterfaceProviderPtr interface_provider); @@ -104,6 +108,7 @@ class EmbeddedSharedWorkerStub : public blink::WebSharedWorkerClient, const std::string name_; bool running_ = false; GURL url_; + RendererPreferences renderer_preferences_; std::unique_ptr<blink::WebSharedWorker> impl_; using PendingChannel = @@ -121,6 +126,10 @@ class EmbeddedSharedWorkerStub : public blink::WebSharedWorkerClient, // script. network::mojom::URLLoaderFactoryAssociatedPtrInfo script_loader_factory_info_; + // S13nServiceWorker: The factory bundle used for loads from this shared + // worker. + scoped_refptr<HostChildURLLoaderFactoryBundle> loader_factories_; + DISALLOW_COPY_AND_ASSIGN(EmbeddedSharedWorkerStub); }; 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 3fe8d6c26b6..48a5091476b 100644 --- a/chromium/content/renderer/shared_worker/shared_worker_factory_impl.cc +++ b/chromium/content/renderer/shared_worker/shared_worker_factory_impl.cc @@ -5,6 +5,7 @@ #include "content/renderer/shared_worker/shared_worker_factory_impl.h" #include "base/memory/ptr_util.h" +#include "content/common/url_loader_factory_bundle.h" #include "content/renderer/shared_worker/embedded_shared_worker_stub.h" #include "mojo/public/cpp/bindings/strong_binding.h" @@ -23,20 +24,23 @@ void SharedWorkerFactoryImpl::CreateSharedWorker( mojom::SharedWorkerInfoPtr info, bool pause_on_start, const base::UnguessableToken& devtools_worker_token, + const RendererPreferences& renderer_preferences, blink::mojom::WorkerContentSettingsProxyPtr content_settings, mojom::ServiceWorkerProviderInfoForSharedWorkerPtr service_worker_provider_info, network::mojom::URLLoaderFactoryAssociatedPtrInfo script_loader_factory_ptr_info, + std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders, mojom::SharedWorkerHostPtr host, mojom::SharedWorkerRequest request, service_manager::mojom::InterfaceProviderPtr interface_provider) { // Bound to the lifetime of the underlying blink::WebSharedWorker instance. new EmbeddedSharedWorkerStub( std::move(info), pause_on_start, devtools_worker_token, - std::move(content_settings), std::move(service_worker_provider_info), - std::move(script_loader_factory_ptr_info), std::move(host), - std::move(request), std::move(interface_provider)); + 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)); } } // 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 0fc2cfdf23c..78aef0102e6 100644 --- a/chromium/content/renderer/shared_worker/shared_worker_factory_impl.h +++ b/chromium/content/renderer/shared_worker/shared_worker_factory_impl.h @@ -11,6 +11,7 @@ #include "services/network/public/mojom/url_loader_factory.mojom.h" namespace content { +class URLLoaderFactoryBundleInfo; class SharedWorkerFactoryImpl : public mojom::SharedWorkerFactory { public: @@ -24,11 +25,13 @@ class SharedWorkerFactoryImpl : public mojom::SharedWorkerFactory { mojom::SharedWorkerInfoPtr info, bool pause_on_start, const base::UnguessableToken& devtools_worker_token, + const RendererPreferences& renderer_preferences, blink::mojom::WorkerContentSettingsProxyPtr content_settings, mojom::ServiceWorkerProviderInfoForSharedWorkerPtr service_worker_provider_info, network::mojom::URLLoaderFactoryAssociatedPtrInfo script_loader_factory_ptr_info, + std::unique_ptr<URLLoaderFactoryBundleInfo> subresource_loaders, mojom::SharedWorkerHostPtr host, mojom::SharedWorkerRequest request, service_manager::mojom::InterfaceProviderPtr interface_provider) override; diff --git a/chromium/content/renderer/shared_worker/shared_worker_repository.cc b/chromium/content/renderer/shared_worker/shared_worker_repository.cc index 562ef5b2e82..a6dbd115561 100644 --- a/chromium/content/renderer/shared_worker/shared_worker_repository.cc +++ b/chromium/content/renderer/shared_worker/shared_worker_repository.cc @@ -26,6 +26,7 @@ void SharedWorkerRepository::Connect( blink::mojom::IPAddressSpace creation_address_space, blink::mojom::SharedWorkerCreationContextType creation_context_type, blink::MessagePortChannel channel, + mojo::ScopedMessagePipeHandle blob_url_token, std::unique_ptr<blink::WebSharedWorkerConnectListener> listener) { // Lazy bind the connector. if (!connector_) @@ -40,8 +41,11 @@ void SharedWorkerRepository::Connect( std::make_unique<SharedWorkerClientImpl>(std::move(listener)), mojo::MakeRequest(&client)); - connector_->Connect(std::move(info), std::move(client), creation_context_type, - channel.ReleaseHandle()); + connector_->Connect( + std::move(info), std::move(client), creation_context_type, + channel.ReleaseHandle(), + blink::mojom::BlobURLTokenPtr(blink::mojom::BlobURLTokenPtrInfo( + std::move(blob_url_token), blink::mojom::BlobURLToken::Version_))); } void SharedWorkerRepository::DocumentDetached(DocumentID document_id) { diff --git a/chromium/content/renderer/shared_worker/shared_worker_repository.h b/chromium/content/renderer/shared_worker/shared_worker_repository.h index d0a8ce2c909..066976ba6dc 100644 --- a/chromium/content/renderer/shared_worker/shared_worker_repository.h +++ b/chromium/content/renderer/shared_worker/shared_worker_repository.h @@ -44,6 +44,7 @@ class SharedWorkerRepository final blink::mojom::IPAddressSpace, blink::mojom::SharedWorkerCreationContextType, blink::MessagePortChannel channel, + mojo::ScopedMessagePipeHandle blob_url_token, std::unique_ptr<blink::WebSharedWorkerConnectListener> listener) override; void DocumentDetached(DocumentID document_id) override; diff --git a/chromium/content/renderer/speech_recognition_dispatcher.cc b/chromium/content/renderer/speech_recognition_dispatcher.cc deleted file mode 100644 index 248a3f1d117..00000000000 --- a/chromium/content/renderer/speech_recognition_dispatcher.cc +++ /dev/null @@ -1,248 +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/speech_recognition_dispatcher.h" - -#include <stddef.h> -#include <stdint.h> - -#include <algorithm> -#include <utility> - -#include "base/strings/utf_string_conversions.h" -#include "build/build_config.h" -#include "content/public/common/service_names.mojom.h" -#include "content/public/renderer/render_thread.h" -#include "content/renderer/render_frame_impl.h" -#include "services/service_manager/public/cpp/connector.h" -#include "third_party/blink/public/platform/web_string.h" -#include "third_party/blink/public/platform/web_vector.h" -#include "third_party/blink/public/web/web_speech_grammar.h" -#include "third_party/blink/public/web/web_speech_recognition_params.h" -#include "third_party/blink/public/web/web_speech_recognition_result.h" - -using blink::WebVector; -using blink::WebString; -using blink::WebSpeechGrammar; -using blink::WebSpeechRecognitionHandle; -using blink::WebSpeechRecognitionResult; -using blink::WebSpeechRecognitionParams; -using blink::WebSpeechRecognizerClient; - -namespace content { - -SpeechRecognitionDispatcher::SpeechRecognitionDispatcher( - RenderFrame* render_frame) - : RenderFrameObserver(render_frame) {} - -SpeechRecognitionDispatcher::~SpeechRecognitionDispatcher() = default; - -void SpeechRecognitionDispatcher::OnDestruct() { - delete this; -} - -void SpeechRecognitionDispatcher::WasHidden() { -#if defined(OS_ANDROID) - for (const auto& it : session_map_) { - it.second->Abort(); - } -#endif -} - -void SpeechRecognitionDispatcher::Start( - const WebSpeechRecognitionHandle& handle, - const WebSpeechRecognitionParams& params, - const WebSpeechRecognizerClient& recognizer_client) { - DCHECK(recognizer_client_.IsNull() || - recognizer_client_ == recognizer_client); - recognizer_client_ = recognizer_client; - - mojom::StartSpeechRecognitionRequestParamsPtr msg_params = - mojom::StartSpeechRecognitionRequestParams::New(); - for (const WebSpeechGrammar& grammar : params.Grammars()) { - msg_params->grammars.push_back( - mojom::SpeechRecognitionGrammar::New(grammar.Src(), grammar.Weight())); - } - msg_params->language = params.Language().Utf8(); - msg_params->max_hypotheses = static_cast<uint32_t>(params.MaxAlternatives()); - msg_params->continuous = params.Continuous(); - msg_params->interim_results = params.InterimResults(); - msg_params->origin = params.Origin(); - - mojom::SpeechRecognitionSessionClientPtrInfo client_ptr_info; - mojom::SpeechRecognitionSessionClientRequest client_request = - mojo::MakeRequest(&client_ptr_info); - bindings_.AddBinding(std::make_unique<SpeechRecognitionSessionClientImpl>( - this, handle, recognizer_client_), - std::move(client_request)); - - mojom::SpeechRecognitionSessionPtr session_client; - mojom::SpeechRecognitionSessionRequest request = - mojo::MakeRequest(&session_client); - - AddHandle(handle, std::move(session_client)); - - msg_params->client = std::move(client_ptr_info); - msg_params->session_request = std::move(request); - - GetSpeechRecognitionHost().Start(std::move(msg_params)); -} - -void SpeechRecognitionDispatcher::Stop( - const WebSpeechRecognitionHandle& handle, - const WebSpeechRecognizerClient& recognizer_client) { - // Ignore a |stop| issued without a matching |start|. - if (recognizer_client_ != recognizer_client || !HandleExists(handle)) - return; - GetSession(handle)->StopCapture(); -} - -void SpeechRecognitionDispatcher::Abort( - const WebSpeechRecognitionHandle& handle, - const WebSpeechRecognizerClient& recognizer_client) { - // Ignore an |abort| issued without a matching |start|. - if (recognizer_client_ != recognizer_client || !HandleExists(handle)) - return; - GetSession(handle)->Abort(); -} - -static WebSpeechRecognizerClient::ErrorCode WebKitErrorCode( - SpeechRecognitionErrorCode e) { - switch (e) { - case SPEECH_RECOGNITION_ERROR_NONE: - NOTREACHED(); - return WebSpeechRecognizerClient::kOtherError; - case SPEECH_RECOGNITION_ERROR_NO_SPEECH: - return WebSpeechRecognizerClient::kNoSpeechError; - case SPEECH_RECOGNITION_ERROR_ABORTED: - return WebSpeechRecognizerClient::kAbortedError; - case SPEECH_RECOGNITION_ERROR_AUDIO_CAPTURE: - return WebSpeechRecognizerClient::kAudioCaptureError; - case SPEECH_RECOGNITION_ERROR_NETWORK: - return WebSpeechRecognizerClient::kNetworkError; - case SPEECH_RECOGNITION_ERROR_NOT_ALLOWED: - return WebSpeechRecognizerClient::kNotAllowedError; - case SPEECH_RECOGNITION_ERROR_SERVICE_NOT_ALLOWED: - return WebSpeechRecognizerClient::kServiceNotAllowedError; - case SPEECH_RECOGNITION_ERROR_BAD_GRAMMAR: - return WebSpeechRecognizerClient::kBadGrammarError; - case SPEECH_RECOGNITION_ERROR_LANGUAGE_NOT_SUPPORTED: - return WebSpeechRecognizerClient::kLanguageNotSupportedError; - case SPEECH_RECOGNITION_ERROR_NO_MATCH: - NOTREACHED(); - return WebSpeechRecognizerClient::kOtherError; - } - NOTREACHED(); - return WebSpeechRecognizerClient::kOtherError; -} - -void SpeechRecognitionDispatcher::AddHandle( - const blink::WebSpeechRecognitionHandle& handle, - mojom::SpeechRecognitionSessionPtr session) { - DCHECK(!HandleExists(handle)); - session_map_[handle] = std::move(session); -} - -bool SpeechRecognitionDispatcher::HandleExists( - const WebSpeechRecognitionHandle& handle) { - return session_map_.find(handle) != session_map_.end(); -} - -void SpeechRecognitionDispatcher::RemoveHandle( - const blink::WebSpeechRecognitionHandle& handle) { - session_map_.erase(handle); -} - -mojom::SpeechRecognitionSession* SpeechRecognitionDispatcher::GetSession( - const blink::WebSpeechRecognitionHandle& handle) { - DCHECK(HandleExists(handle)); - return session_map_[handle].get(); -} - -mojom::SpeechRecognizer& -SpeechRecognitionDispatcher::GetSpeechRecognitionHost() { - if (!speech_recognition_host_) { - render_frame()->GetRemoteInterfaces()->GetInterface( - mojo::MakeRequest(&speech_recognition_host_)); - } - return *speech_recognition_host_; -} - -// ------------ SpeechRecognitionSessionClientImpl -// ------------------------------------ - -SpeechRecognitionSessionClientImpl::SpeechRecognitionSessionClientImpl( - SpeechRecognitionDispatcher* dispatcher, - const blink::WebSpeechRecognitionHandle& handle, - const blink::WebSpeechRecognizerClient& client) - : parent_dispatcher_(dispatcher), handle_(handle), web_client_(client) {} - -void SpeechRecognitionSessionClientImpl::Started() { - web_client_.DidStart(handle_); -} - -void SpeechRecognitionSessionClientImpl::AudioStarted() { - web_client_.DidStartAudio(handle_); -} - -void SpeechRecognitionSessionClientImpl::SoundStarted() { - web_client_.DidStartSound(handle_); -} - -void SpeechRecognitionSessionClientImpl::SoundEnded() { - web_client_.DidEndSound(handle_); -} - -void SpeechRecognitionSessionClientImpl::AudioEnded() { - web_client_.DidEndAudio(handle_); -} - -void SpeechRecognitionSessionClientImpl::ErrorOccurred( - const content::SpeechRecognitionError& error) { - if (error.code == SPEECH_RECOGNITION_ERROR_NO_MATCH) { - web_client_.DidReceiveNoMatch(handle_, WebSpeechRecognitionResult()); - } else { - web_client_.DidReceiveError(handle_, - WebString(), // TODO(primiano): message? - WebKitErrorCode(error.code)); - } -} - -void SpeechRecognitionSessionClientImpl::Ended() { - parent_dispatcher_->RemoveHandle(handle_); - web_client_.DidEnd(handle_); -} - -void SpeechRecognitionSessionClientImpl::ResultRetrieved( - const std::vector<content::SpeechRecognitionResult>& results) { - size_t provisional_count = - std::count_if(results.begin(), results.end(), - [](const SpeechRecognitionResult& result) { - return result.is_provisional; - }); - - WebVector<WebSpeechRecognitionResult> provisional(provisional_count); - WebVector<WebSpeechRecognitionResult> final(results.size() - - provisional_count); - - int provisional_index = 0, final_index = 0; - for (const SpeechRecognitionResult& result : results) { - WebSpeechRecognitionResult* webkit_result = - result.is_provisional ? &provisional[provisional_index++] - : &final[final_index++]; - - const size_t num_hypotheses = result.hypotheses.size(); - WebVector<WebString> transcripts(num_hypotheses); - WebVector<float> confidences(num_hypotheses); - for (size_t i = 0; i < num_hypotheses; ++i) { - transcripts[i] = WebString::FromUTF16(result.hypotheses[i].utterance); - confidences[i] = static_cast<float>(result.hypotheses[i].confidence); - } - webkit_result->Assign(transcripts, confidences, !result.is_provisional); - } - - web_client_.DidReceiveResults(handle_, final, provisional); -} - -} // namespace content diff --git a/chromium/content/renderer/speech_recognition_dispatcher.h b/chromium/content/renderer/speech_recognition_dispatcher.h deleted file mode 100644 index eb261b705f0..00000000000 --- a/chromium/content/renderer/speech_recognition_dispatcher.h +++ /dev/null @@ -1,120 +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_SPEECH_RECOGNITION_DISPATCHER_H_ -#define CONTENT_RENDERER_SPEECH_RECOGNITION_DISPATCHER_H_ - -#include <map> -#include <memory> - -#include "base/macros.h" -#include "content/common/speech_recognizer.mojom.h" -#include "content/public/common/speech_recognition_result.h" -#include "content/public/renderer/render_frame_observer.h" -#include "mojo/public/cpp/bindings/strong_binding_set.h" -#include "third_party/blink/public/web/web_speech_recognition_handle.h" -#include "third_party/blink/public/web/web_speech_recognizer.h" -#include "third_party/blink/public/web/web_speech_recognizer_client.h" - -namespace content { -struct SpeechRecognitionError; - -// SpeechRecognitionDispatcher is a delegate for methods used by WebKit for -// scripted JS speech APIs. It's the complement of -// SpeechRecognitionDispatcherHost (owned by RenderFrameHost), and communicates -// with it using two mojo interfaces (SpeechRecognizer and -// SpeechRecognitionSession). -class SpeechRecognitionDispatcher : public RenderFrameObserver, - public blink::WebSpeechRecognizer { - public: - explicit SpeechRecognitionDispatcher(RenderFrame* render_frame); - ~SpeechRecognitionDispatcher() override; - - private: - // RenderFrameObserver implementation. - void OnDestruct() override; - void WasHidden() override; - - // blink::WebSpeechRecognizer implementation. - void Start(const blink::WebSpeechRecognitionHandle&, - const blink::WebSpeechRecognitionParams&, - const blink::WebSpeechRecognizerClient&) override; - void Stop(const blink::WebSpeechRecognitionHandle&, - const blink::WebSpeechRecognizerClient&) override; - void Abort(const blink::WebSpeechRecognitionHandle&, - const blink::WebSpeechRecognizerClient&) override; - - // Methods to interact with |session_map_| - void AddHandle(const blink::WebSpeechRecognitionHandle& handle, - mojom::SpeechRecognitionSessionPtr session); - bool HandleExists(const blink::WebSpeechRecognitionHandle& handle); - void RemoveHandle(const blink::WebSpeechRecognitionHandle& handle); - mojom::SpeechRecognitionSession* GetSession( - const blink::WebSpeechRecognitionHandle& handle); - - mojom::SpeechRecognizer& GetSpeechRecognitionHost(); - - // InterfacePtr used to communicate with SpeechRecognitionDispatcherHost to - // start a session for each WebSpeechRecognitionHandle. - mojom::SpeechRecognizerPtr speech_recognition_host_; - - // The Blink client class that we use to send events back to the JS world. - // This is passed to each SpeechRecognitionSessionClientImpl instance. - blink::WebSpeechRecognizerClient recognizer_client_; - - // Owns a SpeechRecognitionSessionClientImpl for each session created. The - // bindings are automatically cleaned up when the connection is closed by the - // browser process. We use mojo::StrongBindingSet instead of using - // mojo::MakeStrongBinding for each individual binding as - // SpeechRecognitionSessionClientImpl holds a pointer to its parent - // SpeechRecognitionDispatcher, and we need to clean up the - // SpeechRecognitionSessionClientImpl objects when |this| is deleted. - mojo::StrongBindingSet<mojom::SpeechRecognitionSessionClient> bindings_; - - // Owns a SpeechRecognitionSessionPtr per session created. Each - // WebSpeechRecognitionHandle has its own speech recognition session, and is - // used as a key for the map. - using SessionMap = std::map<blink::WebSpeechRecognitionHandle, - mojom::SpeechRecognitionSessionPtr>; - SessionMap session_map_; - - DISALLOW_COPY_AND_ASSIGN(SpeechRecognitionDispatcher); - friend class SpeechRecognitionSessionClientImpl; -}; - -// SpeechRecognitionSessionClientImpl is owned by SpeechRecognitionDispatcher -// and is cleaned up either when the end point is closed by the browser process, -// or if SpeechRecognitionDispatcher is deleted. -class SpeechRecognitionSessionClientImpl - : public mojom::SpeechRecognitionSessionClient { - public: - SpeechRecognitionSessionClientImpl( - SpeechRecognitionDispatcher* dispatcher, - const blink::WebSpeechRecognitionHandle& handle, - const blink::WebSpeechRecognizerClient& client); - ~SpeechRecognitionSessionClientImpl() override = default; - - // mojom::SpeechRecognitionSessionClient implementation - void Started() override; - void AudioStarted() override; - void SoundStarted() override; - void SoundEnded() override; - void AudioEnded() override; - void ErrorOccurred(const content::SpeechRecognitionError& error) override; - void Ended() override; - void ResultRetrieved( - const std::vector<content::SpeechRecognitionResult>& results) override; - - private: - // Not owned, |parent_dispatcher_| owns |this|. - SpeechRecognitionDispatcher* parent_dispatcher_; - // WebSpeechRecognitionHandle that this instance is associated with. - blink::WebSpeechRecognitionHandle handle_; - // The Blink client class that we use to send events back to the JS world. - blink::WebSpeechRecognizerClient web_client_; -}; - -} // namespace content - -#endif // CONTENT_RENDERER_SPEECH_RECOGNITION_DISPATCHER_H_ diff --git a/chromium/content/renderer/web_database_observer_impl.cc b/chromium/content/renderer/web_database_observer_impl.cc index 087cf47ede2..31a64d45f1b 100644 --- a/chromium/content/renderer/web_database_observer_impl.cc +++ b/chromium/content/renderer/web_database_observer_impl.cc @@ -9,8 +9,6 @@ #include "base/single_thread_task_runner.h" #include "base/strings/string16.h" #include "base/threading/thread_task_runner_handle.h" -#include "content/renderer/storage_util.h" -#include "storage/common/database/database_identifier.h" #include "third_party/blink/public/platform/web_security_origin.h" #include "third_party/blink/public/platform/web_string.h" #include "third_party/sqlite/sqlite3.h" @@ -62,7 +60,6 @@ int DetermineHistogramResult(int websql_error, int sqlite_error) { WebDatabaseObserverImpl::WebDatabaseObserverImpl( scoped_refptr<blink::mojom::ThreadSafeWebDatabaseHostPtr> web_database_host) : web_database_host_(std::move(web_database_host)), - open_connections_(new storage::DatabaseConnectionsWrapper), main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()) { DCHECK(main_thread_task_runner_); } @@ -74,8 +71,6 @@ void WebDatabaseObserverImpl::DatabaseOpened( const WebString& database_name, const WebString& database_display_name, unsigned long estimated_size) { - open_connections_->AddOpenConnection(storage::GetIdentifierFromOrigin(origin), - database_name.Utf16()); GetWebDatabaseHost().Opened(origin, database_name.Utf16(), database_display_name.Utf16(), estimated_size); } @@ -89,8 +84,6 @@ void WebDatabaseObserverImpl::DatabaseClosed(const WebSecurityOrigin& origin, const WebString& database_name) { DCHECK(!main_thread_task_runner_->RunsTasksInCurrentSequence()); GetWebDatabaseHost().Closed(origin, database_name.Utf16()); - open_connections_->RemoveOpenConnection( - storage::GetIdentifierFromOrigin(origin), database_name.Utf16()); } void WebDatabaseObserverImpl::ReportOpenDatabaseResult( @@ -99,17 +92,15 @@ void WebDatabaseObserverImpl::ReportOpenDatabaseResult( int callsite, int websql_error, int sqlite_error, - double call_time) { + base::TimeDelta call_time) { UMA_HISTOGRAM_WEBSQL_RESULT("OpenResult", callsite, websql_error, sqlite_error); HandleSqliteError(origin, database_name, sqlite_error); if (websql_error == kWebSQLSuccess && sqlite_error == SQLITE_OK) { - UMA_HISTOGRAM_TIMES("websql.Async.OpenTime.Success", - base::TimeDelta::FromSecondsD(call_time)); + UMA_HISTOGRAM_TIMES("websql.Async.OpenTime.Success", call_time); } else { - UMA_HISTOGRAM_TIMES("websql.Async.OpenTime.Error", - base::TimeDelta::FromSecondsD(call_time)); + UMA_HISTOGRAM_TIMES("websql.Async.OpenTime.Error", call_time); } } @@ -167,12 +158,6 @@ void WebDatabaseObserverImpl::ReportVacuumDatabaseResult( HandleSqliteError(origin, database_name, sqlite_error); } -bool WebDatabaseObserverImpl::WaitForAllDatabasesToClose( - base::TimeDelta timeout) { - DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence()); - return open_connections_->WaitForAllDatabasesToClose(timeout); -} - void WebDatabaseObserverImpl::HandleSqliteError(const WebSecurityOrigin& origin, const WebString& database_name, int error) { diff --git a/chromium/content/renderer/web_database_observer_impl.h b/chromium/content/renderer/web_database_observer_impl.h index df5c4c1eb2f..74544bca0f8 100644 --- a/chromium/content/renderer/web_database_observer_impl.h +++ b/chromium/content/renderer/web_database_observer_impl.h @@ -7,7 +7,6 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "storage/common/database/database_connections.h" #include "third_party/blink/public/platform/modules/webdatabase/web_database.mojom.h" #include "third_party/blink/public/platform/web_database_observer.h" @@ -37,7 +36,7 @@ class WebDatabaseObserverImpl : public blink::WebDatabaseObserver { int callsite, int websql_error, int sqlite_error, - double call_time) override; + base::TimeDelta call_time) override; void ReportChangeVersionResult(const blink::WebSecurityOrigin& origin, const blink::WebString& database_name, int callsite, @@ -62,8 +61,6 @@ class WebDatabaseObserverImpl : public blink::WebDatabaseObserver { const blink::WebString& database_name, int sqlite_error) override; - bool WaitForAllDatabasesToClose(base::TimeDelta timeout); - private: void HandleSqliteError(const blink::WebSecurityOrigin& origin, const blink::WebString& database_name, @@ -73,7 +70,6 @@ class WebDatabaseObserverImpl : public blink::WebDatabaseObserver { blink::mojom::WebDatabaseHost& GetWebDatabaseHost(); scoped_refptr<blink::mojom::ThreadSafeWebDatabaseHostPtr> web_database_host_; - scoped_refptr<storage::DatabaseConnectionsWrapper> open_connections_; scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_; DISALLOW_COPY_AND_ASSIGN(WebDatabaseObserverImpl); diff --git a/chromium/content/renderer/web_frame_utils.cc b/chromium/content/renderer/web_frame_utils.cc deleted file mode 100644 index cba1820c98f..00000000000 --- a/chromium/content/renderer/web_frame_utils.cc +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/web_frame_utils.h" - -#include "content/renderer/render_frame_impl.h" -#include "content/renderer/render_frame_proxy.h" -#include "ipc/ipc_message.h" -#include "third_party/blink/public/web/web_frame.h" -#include "third_party/blink/public/web/web_local_frame.h" -#include "third_party/blink/public/web/web_remote_frame.h" - -namespace content { - -blink::WebFrame* GetWebFrameFromRoutingIdForFrameOrProxy(int routing_id) { - auto* render_frame = RenderFrameImpl::FromRoutingID(routing_id); - if (render_frame) - return render_frame->GetWebFrame(); - - auto* render_frame_proxy = RenderFrameProxy::FromRoutingID(routing_id); - if (render_frame_proxy) - return render_frame_proxy->web_frame(); - - return nullptr; -} - -} // namespace content diff --git a/chromium/content/renderer/web_frame_utils.h b/chromium/content/renderer/web_frame_utils.h deleted file mode 100644 index 5b888d5cbb7..00000000000 --- a/chromium/content/renderer/web_frame_utils.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_WEB_FRAME_UTILS_H_ -#define CONTENT_RENDERER_WEB_FRAME_UTILS_H_ - -namespace blink { -class WebFrame; -} - -namespace content { - -// Returns either a WebLocalFrame or WebRemoteFrame based on |routing_id|. -// Returns nullptr if |routing_id| doesn't properly map to a frame. -blink::WebFrame* GetWebFrameFromRoutingIdForFrameOrProxy(int routing_id); - -} // namespace content - -#endif // CONTENT_RENDERER_WEB_FRAME_UTILS_H_ diff --git a/chromium/content/renderer/webclipboard_impl_browsertest.cc b/chromium/content/renderer/webclipboard_impl_browsertest.cc index 13b7c7560ce..181dfe0a8e1 100644 --- a/chromium/content/renderer/webclipboard_impl_browsertest.cc +++ b/chromium/content/renderer/webclipboard_impl_browsertest.cc @@ -55,10 +55,11 @@ IN_PROC_BROWSER_TEST_F(WebClipboardImplTest, ImageCopy) { NavigateIframeToURL(web_contents, "copyme", GetTestUrl(".", "media/blackwhite.png")); - // Run script to copy image contents and wait for completion. - web_contents->GetMainFrame()->ExecuteJavaScriptWithUserGestureForTests( - base::ASCIIToUTF16("frames[0].document.execCommand('copy');" - "document.title = 'copied';")); + // Run script in child frame to copy image contents and wait for completion. + RenderFrameHost* child_frame = ChildFrameAt(web_contents->GetMainFrame(), 0); + child_frame->ExecuteJavaScriptWithUserGestureForTests( + base::ASCIIToUTF16("document.execCommand('copy');" + "parent.document.title = 'copied';")); TitleWatcher watcher1(web_contents, base::ASCIIToUTF16("copied")); EXPECT_EQ(base::ASCIIToUTF16("copied"), watcher1.WaitAndGetTitle()); diff --git a/chromium/content/renderer/webgraphicscontext3d_provider_impl.cc b/chromium/content/renderer/webgraphicscontext3d_provider_impl.cc index ad82d6cfea9..f44ed327657 100644 --- a/chromium/content/renderer/webgraphicscontext3d_provider_impl.cc +++ b/chromium/content/renderer/webgraphicscontext3d_provider_impl.cc @@ -12,10 +12,8 @@ namespace content { WebGraphicsContext3DProviderImpl::WebGraphicsContext3DProviderImpl( - scoped_refptr<ui::ContextProviderCommandBuffer> provider, - bool software_rendering) - : provider_(std::move(provider)), software_rendering_(software_rendering) { -} + scoped_refptr<ui::ContextProviderCommandBuffer> provider) + : provider_(std::move(provider)) {} WebGraphicsContext3DProviderImpl::~WebGraphicsContext3DProviderImpl() { provider_->RemoveObserver(this); @@ -56,10 +54,6 @@ viz::GLHelper* WebGraphicsContext3DProviderImpl::GetGLHelper() { return gl_helper_.get(); } -bool WebGraphicsContext3DProviderImpl::IsSoftwareRendering() const { - return software_rendering_; -} - void WebGraphicsContext3DProviderImpl::SetLostContextCallback( base::RepeatingClosure c) { context_lost_callback_ = std::move(c); diff --git a/chromium/content/renderer/webgraphicscontext3d_provider_impl.h b/chromium/content/renderer/webgraphicscontext3d_provider_impl.h index 97d65fcdcf0..28947063460 100644 --- a/chromium/content/renderer/webgraphicscontext3d_provider_impl.h +++ b/chromium/content/renderer/webgraphicscontext3d_provider_impl.h @@ -36,8 +36,7 @@ class CONTENT_EXPORT WebGraphicsContext3DProviderImpl public viz::ContextLostObserver { public: WebGraphicsContext3DProviderImpl( - scoped_refptr<ui::ContextProviderCommandBuffer> provider, - bool software_rendering); + scoped_refptr<ui::ContextProviderCommandBuffer> provider); ~WebGraphicsContext3DProviderImpl() override; // WebGraphicsContext3DProvider implementation. @@ -47,7 +46,6 @@ class CONTENT_EXPORT WebGraphicsContext3DProviderImpl const gpu::Capabilities& GetCapabilities() const override; const gpu::GpuFeatureInfo& GetGpuFeatureInfo() const override; viz::GLHelper* GetGLHelper() override; - bool IsSoftwareRendering() const override; void SetLostContextCallback(base::RepeatingClosure) override; void SetErrorMessageCallback( base::RepeatingCallback<void(const char*, int32_t)>) override; @@ -63,7 +61,6 @@ class CONTENT_EXPORT WebGraphicsContext3DProviderImpl scoped_refptr<ui::ContextProviderCommandBuffer> provider_; std::unique_ptr<viz::GLHelper> gl_helper_; - const bool software_rendering_; base::RepeatingClosure context_lost_callback_; std::unique_ptr<cc::ImageDecodeCache> image_decode_cache_; diff --git a/chromium/content/renderer/webpublicsuffixlist_impl.cc b/chromium/content/renderer/webpublicsuffixlist_impl.cc deleted file mode 100644 index 03ba14cbca3..00000000000 --- a/chromium/content/renderer/webpublicsuffixlist_impl.cc +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/webpublicsuffixlist_impl.h" - -#include "net/base/registry_controlled_domains/registry_controlled_domain.h" - -namespace content { - -WebPublicSuffixListImpl::~WebPublicSuffixListImpl() { -} - -size_t WebPublicSuffixListImpl::GetPublicSuffixLength( - const blink::WebString& host) { - // Blink passes some things that aren't technically hosts like "*.foo", so - // use the permissive variant. - size_t result = - net::registry_controlled_domains::PermissiveGetHostRegistryLength( - host.Utf8(), - net::registry_controlled_domains::INCLUDE_UNKNOWN_REGISTRIES, - net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); - return result ? result : host.length(); -} - -} // namespace content diff --git a/chromium/content/renderer/webpublicsuffixlist_impl.h b/chromium/content/renderer/webpublicsuffixlist_impl.h deleted file mode 100644 index a38010e0de3..00000000000 --- a/chromium/content/renderer/webpublicsuffixlist_impl.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_RENDERER_WEBPUBLICSUFFIXLIST_IMPL_H_ -#define CONTENT_RENDERER_WEBPUBLICSUFFIXLIST_IMPL_H_ - -#include <stddef.h> - -#include "base/compiler_specific.h" -#include "third_party/blink/public/platform/web_public_suffix_list.h" - -namespace content { - -class WebPublicSuffixListImpl : public blink::WebPublicSuffixList { - public: - // WebPublicSuffixList methods: - size_t GetPublicSuffixLength(const blink::WebString&) override; - ~WebPublicSuffixListImpl() override; -}; - -} // namespace content - -#endif // CONTENT_RENDERER_WEBPUBLICSUFFIXLIST_IMPL_H_ diff --git a/chromium/content/renderer/webscrollbarbehavior_impl_aura.cc b/chromium/content/renderer/webscrollbarbehavior_impl_aura.cc deleted file mode 100644 index c6c15715a90..00000000000 --- a/chromium/content/renderer/webscrollbarbehavior_impl_aura.cc +++ /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. - -#include "content/renderer/webscrollbarbehavior_impl_aura.h" - -#include "build/build_config.h" -#include "third_party/blink/public/platform/web_point.h" -#include "third_party/blink/public/platform/web_rect.h" - -namespace content { - -bool WebScrollbarBehaviorImpl::ShouldCenterOnThumb( - blink::WebPointerProperties::Button mouseButton, - bool shiftKeyPressed, - bool altKeyPressed) { -#if (defined(OS_LINUX) && !defined(OS_CHROMEOS)) - if (mouseButton == blink::WebPointerProperties::Button::kMiddle) - return true; -#endif - return (mouseButton == blink::WebPointerProperties::Button::kLeft) && - shiftKeyPressed; -} - -bool WebScrollbarBehaviorImpl::ShouldSnapBackToDragOrigin( - const blink::WebPoint& eventPoint, - const blink::WebRect& scrollbarRect, - bool isHorizontal) { -// Disable snapback on desktop Linux to better integrate with the desktop -// behavior. Typically, Linux apps do not implement scrollbar snapback (this is -// true for at least GTK and QT apps). -#if (defined(OS_LINUX) && !defined(OS_CHROMEOS)) - return false; -#endif - - // Constants used to figure the drag rect outside which we should snap the - // scrollbar thumb back to its origin. These calculations are based on - // observing the behavior of the MSVC8 main window scrollbar + some - // guessing/extrapolation. - static const int kOffEndMultiplier = 3; - static const int kOffSideMultiplier = 8; - static const int kDefaultWinScrollbarThickness = 17; - - // Find the rect within which we shouldn't snap, by expanding the track rect - // in both dimensions. - gfx::Rect noSnapRect(scrollbarRect); - int thickness = isHorizontal ? noSnapRect.height() : noSnapRect.width(); - // Even if the platform's scrollbar is narrower than the default Windows one, - // we still want to provide at least as much slop area, since a slightly - // narrower scrollbar doesn't necessarily imply that users will drag - // straighter. - thickness = std::max(thickness, kDefaultWinScrollbarThickness); - noSnapRect.Inset( - (isHorizontal ? kOffEndMultiplier : kOffSideMultiplier) * -thickness, - (isHorizontal ? kOffSideMultiplier : kOffEndMultiplier) * -thickness); - - return !noSnapRect.Contains(eventPoint); -} - -} // namespace content diff --git a/chromium/content/renderer/webscrollbarbehavior_impl_aura.h b/chromium/content/renderer/webscrollbarbehavior_impl_aura.h deleted file mode 100644 index f06717ddc56..00000000000 --- a/chromium/content/renderer/webscrollbarbehavior_impl_aura.h +++ /dev/null @@ -1,24 +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_WEBSCROLLBARBEHAVIOR_IMPL_AURA_H_ -#define CONTENT_RENDERER_WEBSCROLLBARBEHAVIOR_IMPL_AURA_H_ - -#include "third_party/blink/public/platform/web_scrollbar_behavior.h" - -namespace content { - -class WebScrollbarBehaviorImpl : public blink::WebScrollbarBehavior { - public: - bool ShouldCenterOnThumb(blink::WebPointerProperties::Button mouseButton, - bool shiftKeyPressed, - bool altKeyPressed) override; - bool ShouldSnapBackToDragOrigin(const blink::WebPoint& eventPoint, - const blink::WebRect& scrollbarRect, - bool isHorizontal) override; -}; - -} // namespace content - -#endif // CONTENT_RENDERER_WEBSCROLLBARBEHAVIOR_IMPL_AURA_H_ diff --git a/chromium/content/renderer/webscrollbarbehavior_impl_mac.h b/chromium/content/renderer/webscrollbarbehavior_impl_mac.h deleted file mode 100644 index c6303816875..00000000000 --- a/chromium/content/renderer/webscrollbarbehavior_impl_mac.h +++ /dev/null @@ -1,31 +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_WEBSCROLLBARBEHAVIOR_IMPL_MAC_H_ -#define CONTENT_RENDERER_WEBSCROLLBARBEHAVIOR_IMPL_MAC_H_ - -#include "third_party/blink/public/platform/web_scrollbar_behavior.h" - -namespace content { - -class WebScrollbarBehaviorImpl : public blink::WebScrollbarBehavior { - public: - WebScrollbarBehaviorImpl(); - - bool ShouldCenterOnThumb(blink::WebPointerProperties::Button mouseButton, - bool shiftKeyPressed, - bool altKeyPressed) override; - - void set_jump_on_track_click(bool jump_on_track_click) { - jump_on_track_click_ = jump_on_track_click; - } - - private: - // The current value of AppleScrollerPagingBehavior from NSUserDefaults. - bool jump_on_track_click_; -}; - -} // namespace content - -#endif // CONTENT_RENDERER_WEBSCROLLBARBEHAVIOR_IMPL_MAC_H_ diff --git a/chromium/content/renderer/webscrollbarbehavior_impl_mac.mm b/chromium/content/renderer/webscrollbarbehavior_impl_mac.mm deleted file mode 100644 index b2f3fbdff6f..00000000000 --- a/chromium/content/renderer/webscrollbarbehavior_impl_mac.mm +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/webscrollbarbehavior_impl_mac.h" - -namespace content { - -WebScrollbarBehaviorImpl::WebScrollbarBehaviorImpl() - : jump_on_track_click_(false) { -} - -bool WebScrollbarBehaviorImpl::ShouldCenterOnThumb( - blink::WebPointerProperties::Button mouseButton, - bool shiftKeyPressed, - bool altKeyPressed) { - return (mouseButton == blink::WebPointerProperties::Button::kLeft) && - (jump_on_track_click_ != altKeyPressed); -} - -} // namespace content diff --git a/chromium/content/renderer/worker_thread_message_filter.cc b/chromium/content/renderer/worker_thread_message_filter.cc deleted file mode 100644 index f1f259f7c15..00000000000 --- a/chromium/content/renderer/worker_thread_message_filter.cc +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/renderer/worker_thread_message_filter.h" - -#include "base/single_thread_task_runner.h" -#include "base/threading/thread_task_runner_handle.h" -#include "content/child/thread_safe_sender.h" -#include "content/renderer/worker_thread_registry.h" -#include "ipc/ipc_message_macros.h" - -namespace content { - -WorkerThreadMessageFilter::WorkerThreadMessageFilter( - ThreadSafeSender* thread_safe_sender, - scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner) - : main_thread_task_runner_(std::move(main_thread_task_runner)), - thread_safe_sender_(thread_safe_sender) {} - -WorkerThreadMessageFilter::~WorkerThreadMessageFilter() { -} - -base::TaskRunner* WorkerThreadMessageFilter::OverrideTaskRunnerForMessage( - const IPC::Message& msg) { - if (!ShouldHandleMessage(msg)) - return nullptr; - int ipc_thread_id = 0; - const bool success = GetWorkerThreadIdForMessage(msg, &ipc_thread_id); - DCHECK(success); - if (!ipc_thread_id) - return main_thread_task_runner_.get(); - return WorkerThreadRegistry::Instance()->GetTaskRunnerFor(ipc_thread_id); -} - -bool WorkerThreadMessageFilter::OnMessageReceived(const IPC::Message& msg) { - if (!ShouldHandleMessage(msg)) - return false; - // If the IPC message is received in a worker thread, but it has already been - // stopped, then drop the message. - if (!main_thread_task_runner_->BelongsToCurrentThread() && - !WorkerThread::GetCurrentId()) { - return false; - } - OnFilteredMessageReceived(msg); - return true; -} - -} // namespace content diff --git a/chromium/content/renderer/worker_thread_message_filter.h b/chromium/content/renderer/worker_thread_message_filter.h deleted file mode 100644 index 64c0d47b896..00000000000 --- a/chromium/content/renderer/worker_thread_message_filter.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_RENDERER_WORKER_THREAD_MESSAGE_FILTER_H_ -#define CONTENT_RENDERER_WORKER_THREAD_MESSAGE_FILTER_H_ - -#include "base/macros.h" -#include "content/renderer/child_message_filter.h" - -namespace base { -class SingleThreadTaskRunner; -} - -namespace content { - -class ThreadSafeSender; - -// A base class for filtering IPC messages targeted for worker threads. -class WorkerThreadMessageFilter : public ChildMessageFilter { - public: - WorkerThreadMessageFilter( - ThreadSafeSender* thread_safe_sender, - scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner); - - protected: - ~WorkerThreadMessageFilter() override; - - base::SingleThreadTaskRunner* main_thread_task_runner() { - return main_thread_task_runner_.get(); - } - ThreadSafeSender* thread_safe_sender() { return thread_safe_sender_.get(); } - - private: - // Returns whether this filter should process |msg|. - virtual bool ShouldHandleMessage(const IPC::Message& msg) const = 0; - - // Processes the IPC message in the worker thread, if the filter could extract - // its thread id. Otherwise, runs in the main thread. It only receives a - // message if ShouldHandleMessage() returns true for it. - virtual void OnFilteredMessageReceived(const IPC::Message& msg) = 0; - - // Attempts to extract the thread-id of the worker-thread that should process - // the IPC message. Returns whether the thread-id could be determined and set - // in |ipc_thread_id|. - virtual bool GetWorkerThreadIdForMessage(const IPC::Message& msg, - int* ipc_thread_id) = 0; - - // ChildMessageFilter implementation: - base::TaskRunner* OverrideTaskRunnerForMessage(const IPC::Message& msg) final; - bool OnMessageReceived(const IPC::Message& msg) final; - - scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_; - scoped_refptr<ThreadSafeSender> thread_safe_sender_; - - DISALLOW_COPY_AND_ASSIGN(WorkerThreadMessageFilter); -}; - -} // namespace content - -#endif // CONTENT_RENDERER_WORKER_THREAD_MESSAGE_FILTER_H_ |