diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index b26c54a3c43e1123f8cd84b8f1ea71a48615a143..2d702f35bb6e6ee2b2f0ee3954a5d9fa2d899bd5 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn @@ -3272,6 +3272,8 @@ source_set("browser") { "accessibility/browser_accessibility_ohos.h", "media/ohos/ohos_media_player_renderer.cc", "media/ohos/ohos_media_player_renderer.h", + "media/ohos/ohos_media_resource_getter_impl.cc", + "media/ohos/ohos_media_resource_getter_impl.h", "media/session/audio_focus_delegate_ohos.cc", "media/session/audio_focus_delegate_ohos.h", "media/session/audio_interrupt_adapter_impl.cc", diff --git a/content/browser/media/ohos/ohos_custom_media_player_renderer.cc b/content/browser/media/ohos/ohos_custom_media_player_renderer.cc index 4081281c21b4b1ccd4a0e01e880d026b9fd33227..36051e023b1ebaef9389a298dc255e8ff062ed0a 100644 --- a/content/browser/media/ohos/ohos_custom_media_player_renderer.cc +++ b/content/browser/media/ohos/ohos_custom_media_player_renderer.cc @@ -476,6 +476,10 @@ media::RendererType OHOSCustomMediaPlayerRenderer::GetRendererType() { return media::RendererType::kOHOSCustomMediaPlayer; } +media::OHOSMediaResourceGetter* OHOSCustomMediaPlayerRenderer::GetMediaResourceGetter() { + return nullptr; +} + void OHOSCustomMediaPlayerRenderer::OnMediaDurationChanged(base::TimeDelta duration) { // For HLS streams, the reported duration may be zero for infinite streams. // See http://crbug.com/501213. diff --git a/content/browser/media/ohos/ohos_custom_media_player_renderer.h b/content/browser/media/ohos/ohos_custom_media_player_renderer.h index 3e912419b19550a868feef14db7498e810f4248d..aea26dc8ca4ec344b4d29cc9f88b983020a7afde 100644 --- a/content/browser/media/ohos/ohos_custom_media_player_renderer.h +++ b/content/browser/media/ohos/ohos_custom_media_player_renderer.h @@ -91,6 +91,7 @@ class CONTENT_EXPORT OHOSCustomMediaPlayerRenderer void InitiateScopedSurfaceRequest( InitiateScopedSurfaceRequestCallback callback) override {} void FinishPaint(int32_t fd) override {} + media::OHOSMediaResourceGetter* GetMediaResourceGetter() override; void OnTimeUpdate(base::TimeDelta media_time); void OnBufferingStateChange(media::BufferingState state); diff --git a/content/browser/media/ohos/ohos_media_player_renderer.cc b/content/browser/media/ohos/ohos_media_player_renderer.cc index 02dcdb63fa1537dd90116ab784a3805875078fd8..70792eefa2d7e107cd681a770d7bb8a8b2c5226a 100644 --- a/content/browser/media/ohos/ohos_media_player_renderer.cc +++ b/content/browser/media/ohos/ohos_media_player_renderer.cc @@ -10,6 +10,7 @@ #include "base/functional/callback_helpers.h" #include "content/browser/media/ohos/ohos_media_player_renderer_web_contents_observer.h" #include "content/browser/media/session/media_session_impl.h" +#include "content/browser/media/ohos/ohos_media_resource_getter_impl.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_task_traits.h" @@ -48,6 +49,8 @@ OHOSMediaPlayerRenderer::OHOSMediaPlayerRenderer( mojo::PendingRemote client_extension_remote) : client_extension_(std::move(client_extension_remote)), has_error_(false), + render_process_id_(process_id), + routing_id_(routing_id), volume_(kDefaultVolume), web_contents_(web_contents->GetWeakPtr()), renderer_extension_receiver_(this, @@ -93,8 +96,9 @@ void OHOSMediaPlayerRenderer::CreateMediaPlayer( media_player_.reset(new media::OHOSMediaPlayerBridge( url_params.media_url, url_params.site_for_cookies, url_params.top_frame_origin, user_agent, + url_params.has_storage_access, false, // hide_url_log - this, url_params.allow_credentials, url_params.is_hls)); + this, url_params.allow_credentials, url_params.is_hls, url_params.headers)); init_cb_ = std::move(init_cb); int32_t ret = media_player_->Initialize(); if (ret != 0) { @@ -177,6 +181,24 @@ void OHOSMediaPlayerRenderer::OnFrameAvailable(int fd, } } +media::OHOSMediaResourceGetter* OHOSMediaPlayerRenderer::GetMediaResourceGetter() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + if (!media_resource_getter_.get()) { + RenderProcessHost* host = RenderProcessHost::FromID(render_process_id_); + + // The RenderFrameHost/RenderProcessHost may have been destroyed already, + // as there might be a delay between the frame closing and + // MojoRendererService receiving a connection closing error. + if (!host) + return nullptr; + + BrowserContext* context = host->GetBrowserContext(); + media_resource_getter_ = std::make_unique( + context, render_process_id_, routing_id_); + } + return media_resource_getter_.get(); +} + void OHOSMediaPlayerRenderer::OnMediaDurationChanged(base::TimeDelta duration) { if (duration.is_zero()) duration = media::kInfiniteDuration; diff --git a/content/browser/media/ohos/ohos_media_player_renderer.h b/content/browser/media/ohos/ohos_media_player_renderer.h index 45f801a84f3206f163a5e4137cf466fc60437de8..751c272a1a5d7ad5c9391b9f1b0531df5f1e39bf 100644 --- a/content/browser/media/ohos/ohos_media_player_renderer.h +++ b/content/browser/media/ohos/ohos_media_player_renderer.h @@ -67,6 +67,7 @@ class CONTENT_EXPORT OHOSMediaPlayerRenderer int32_t visible_width, int32_t visible_height, int32_t format) override; + media::OHOSMediaResourceGetter* GetMediaResourceGetter() override; void OnMediaDurationChanged(base::TimeDelta duration) override; void OnPlaybackComplete() override; void OnError(int error) override; @@ -112,6 +113,14 @@ class CONTENT_EXPORT OHOSMediaPlayerRenderer gfx::Size video_size_; + // Identifiers to find the RenderFrameHost that created |this|. + // NOTE: We store these IDs rather than a RenderFrameHost* because we do not + // know when the RenderFrameHost is destroyed. + int render_process_id_; + int routing_id_; + + std::unique_ptr media_resource_getter_; + bool web_contents_muted_; raw_ptr web_contents_observer_; float volume_; diff --git a/content/browser/media/ohos/ohos_media_resource_getter_impl.cc b/content/browser/media/ohos/ohos_media_resource_getter_impl.cc new file mode 100644 index 0000000000000000000000000000000000000000..72605571682d61ead4b12b9e01f28b4bbc60152b --- /dev/null +++ b/content/browser/media/ohos/ohos_media_resource_getter_impl.cc @@ -0,0 +1,178 @@ +// Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +#include "content/browser/media/ohos/ohos_media_resource_getter_impl.h" + +#include "base/functional/bind.h" +#include "base/path_service.h" +#include "base/task/single_thread_task_runner.h" +#include "content/browser/child_process_security_policy_impl.h" +#include "content/browser/file_system/browser_file_system_helper.h" +#include "content/browser/renderer_host/render_frame_host_impl.h" +#include "content/browser/storage_partition_impl.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/content_browser_client.h" +#include "content/public/browser/storage_partition.h" +#include "content/public/common/content_client.h" +#include "content/public/common/url_constants.h" +#include "ipc/ipc_message.h" +#include "mojo/public/cpp/bindings/remote.h" +#include "net/base/auth.h" +#include "net/base/isolation_info.h" +#include "net/base/network_anonymization_key.h" +#include "net/cookies/cookie_setting_override.h" +#include "net/http/http_auth.h" +#include "services/network/public/mojom/network_context.mojom.h" +#include "services/network/public/mojom/restricted_cookie_manager.mojom.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" +#include "url/gurl.h" +#include "url/origin.h" + +namespace content { + +namespace { + +// Returns the cookie manager for the `browser_context` at the client end of the +// mojo pipe. This will be restricted to the origin of `url`, and will apply +// policies from user and ContentBrowserClient to cookie operations. +mojo::PendingRemote +GetRestrictedCookieManagerForContext( + BrowserContext* browser_context, + const GURL& url, + const net::SiteForCookies& site_for_cookies, + const url::Origin& top_frame_origin, + RenderFrameHostImpl* render_frame_host) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + url::Origin request_origin = url::Origin::Create(url); + StoragePartition* storage_partition = + browser_context->GetDefaultStoragePartition(); + + // `request_origin` cannot be used to create `isolation_info` since it + // represents the media resource, not the frame origin. Here we use the + // `top_frame_origin` as the frame origin to ensure the consistency check + // passes when creating `isolation_info`. This is ok because + // `isolation_info.frame_origin` is unused in RestrictedCookieManager. + DCHECK(site_for_cookies.IsNull() || + site_for_cookies.IsFirstParty(top_frame_origin.GetURL())); + net::IsolationInfo isolation_info = net::IsolationInfo::Create( + net::IsolationInfo::RequestType::kOther, top_frame_origin, + top_frame_origin, site_for_cookies); + + mojo::PendingRemote pipe; + static_cast(storage_partition) + ->CreateRestrictedCookieManager( + network::mojom::RestrictedCookieManagerRole::NETWORK, request_origin, + std::move(isolation_info), + /* is_service_worker = */ false, + render_frame_host ? render_frame_host->GetProcess()->GetID() : -1, + render_frame_host ? render_frame_host->GetRoutingID() + : MSG_ROUTING_NONE, + render_frame_host ? render_frame_host->GetCookieSettingOverrides() + : net::CookieSettingOverrides(), + pipe.InitWithNewPipeAndPassReceiver(), + render_frame_host ? render_frame_host->CreateCookieAccessObserver() + : mojo::NullRemote()); + return pipe; +} + +void ReturnResultOnUIThread( + base::OnceCallback callback, + const std::string& result) { + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), result)); +} + +void ReturnResultOnUIThreadAndClosePipe( + mojo::Remote pipe, + base::OnceCallback callback, + const std::string& result) { + GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), result)); +} + +} // namespace + +OHOSMediaResourceGetterImpl::OHOSMediaResourceGetterImpl( + BrowserContext* browser_context, + int render_process_id, + int render_frame_id) + : browser_context_(browser_context), + render_process_id_(render_process_id), + render_frame_id_(render_frame_id) {} + +OHOSMediaResourceGetterImpl::~OHOSMediaResourceGetterImpl() {} + +void OHOSMediaResourceGetterImpl::GetAuthCredentials( + const GURL& url, + GetAuthCredentialsCB callback) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + // Non-standard URLs, such as data, will not be found in HTTP auth cache + // anyway, because they have no valid origin, so don't waste the time. + if (!url.IsStandard()) { + GetAuthCredentialsCallback(std::move(callback), absl::nullopt); + return; + } + + RenderFrameHostImpl* render_frame_host = + RenderFrameHostImpl::FromID(render_process_id_, render_frame_id_); + // Can't get a NetworkAnonymizationKey to get credentials if the + // RenderFrameHost has already been destroyed. + if (!render_frame_host) { + GetAuthCredentialsCallback(std::move(callback), absl::nullopt); + return; + } + + browser_context_->GetDefaultStoragePartition() + ->GetNetworkContext() + ->LookupServerBasicAuthCredentials( + url, render_frame_host->GetIsolationInfoForSubresources().network_anonymization_key(), + base::BindOnce(&OHOSMediaResourceGetterImpl::GetAuthCredentialsCallback, + weak_factory_.GetWeakPtr(), std::move(callback))); +} + +void OHOSMediaResourceGetterImpl::GetCookies( + const GURL& url, + const net::SiteForCookies& site_for_cookies, + const url::Origin& top_frame_origin, + bool has_storage_access, + GetCookieCB callback) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + ChildProcessSecurityPolicyImpl* policy = + ChildProcessSecurityPolicyImpl::GetInstance(); + if (!policy->CanAccessDataForOrigin(render_process_id_, + url::Origin::Create(url))) { + // Running the callback asynchronously on the caller thread to avoid + // reentrancy issues. + ReturnResultOnUIThread(std::move(callback), std::string()); + return; + } + + mojo::Remote cookie_manager( + GetRestrictedCookieManagerForContext( + browser_context_, url, site_for_cookies, top_frame_origin, + RenderFrameHostImpl::FromID(render_process_id_, render_frame_id_))); + network::mojom::RestrictedCookieManager* cookie_manager_ptr = + cookie_manager.get(); + cookie_manager_ptr->GetCookiesString( + url, site_for_cookies, top_frame_origin, has_storage_access, + base::BindOnce(&ReturnResultOnUIThreadAndClosePipe, + std::move(cookie_manager), std::move(callback))); +} + +void OHOSMediaResourceGetterImpl::GetAuthCredentialsCallback( + GetAuthCredentialsCB callback, + const absl::optional& credentials) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + if (credentials) + std::move(callback).Run(credentials->username(), credentials->password()); + else + std::move(callback).Run(std::u16string(), std::u16string()); +} + +} // namespace content \ No newline at end of file diff --git a/content/browser/media/ohos/ohos_media_resource_getter_impl.h b/content/browser/media/ohos/ohos_media_resource_getter_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..efafa9c8a94ad2222a85747ecbe6a3583b4f4ea4 --- /dev/null +++ b/content/browser/media/ohos/ohos_media_resource_getter_impl.h @@ -0,0 +1,67 @@ +// Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_MEDIA_OHOS_MEDIA_RESOURCE_GETTER_IMPL_H_ +#define CONTENT_BROWSER_MEDIA_OHOS_MEDIA_RESOURCE_GETTER_IMPL_H_ + +#include "base/memory/raw_ptr.h" +#include "base/memory/weak_ptr.h" +#include "base/synchronization/waitable_event.h" +#include "media/base/ohos/ohos_media_resource_getter.h" +#include "net/base/auth.h" +#include "net/cookies/canonical_cookie.h" +#include "net/cookies/site_for_cookies.h" + +namespace content { + +class BrowserContext; +class ResourceContext; + +// This class implements media::MediaResourceGetter to retrieve resources +// asynchronously on the UI thread. +class OHOSMediaResourceGetterImpl : public media::OHOSMediaResourceGetter { + public: + // Construct a MediaResourceGetterImpl object. `browser_context` and + // `render_process_id` are passed to retrieve the CookieStore. + OHOSMediaResourceGetterImpl(BrowserContext* browser_context, + int render_process_id, + int render_frame_id); + + OHOSMediaResourceGetterImpl(const OHOSMediaResourceGetterImpl&) = delete; + OHOSMediaResourceGetterImpl& operator=(const OHOSMediaResourceGetterImpl&) = delete; + + ~OHOSMediaResourceGetterImpl() override; + + // media::MediaResourceGetter implementation. + // Must be called on the UI thread. + void GetAuthCredentials(const GURL& url, + GetAuthCredentialsCB callback) override; + void GetCookies(const GURL& url, + const net::SiteForCookies& site_for_cookies, + const url::Origin& top_frame_origin, + bool has_storage_access, + GetCookieCB callback) override; + + private: + // Called when GetAuthCredentials() finishes. + void GetAuthCredentialsCallback( + GetAuthCredentialsCB callback, + const absl::optional& credentials); + + // BrowserContext to retrieve URLRequestContext and ResourceContext. + raw_ptr browser_context_; + + // Render process id, used to check whether the process can access cookies. + int render_process_id_; + + // Render frame id, used to check tab specific cookie policy. + int render_frame_id_; + + // NOTE: Weak pointers must be invalidated before all other member variables. + base::WeakPtrFactory weak_factory_{this}; +}; + +} // namespace content + +#endif // CONTENT_BROWSER_MEDIA_OHOS_MEDIA_RESOURCE_GETTER_IMPL_H_ \ No newline at end of file diff --git a/media/base/media_resource.cc b/media/base/media_resource.cc index 438520fce4f0a43f5561326043d95a0839b27bc6..3e25cae86bca29893b238909ba91881a689e78e8 100644 --- a/media/base/media_resource.cc +++ b/media/base/media_resource.cc @@ -41,4 +41,10 @@ void MediaResource::ForwardDurationChangeToDemuxerHost( NOTREACHED(); } +void MediaResource::SetHeaders( + const base::flat_map& headers) { + // Only implemented by MediaUrlDemuxer, for the MojoRendererService. + NOTREACHED(); +} + } // namespace media diff --git a/media/base/media_resource.h b/media/base/media_resource.h index fe855ef1d8b1307642cbf0a77fa0d1637c0766c6..8ccff6879816b1700956d306e432d0fc229156e1 100644 --- a/media/base/media_resource.h +++ b/media/base/media_resource.h @@ -65,6 +65,11 @@ class MEDIA_EXPORT MediaResource { // Demuxer* it is dealing with. virtual void ForwardDurationChangeToDemuxerHost(base::TimeDelta duration); + // This method is only used with the MediaUrlDemuxer, to set headers coming + // from media url params. + virtual void SetHeaders( + const base::flat_map& headers); + #if defined(OHOS_CUSTOM_VIDEO_PLAYER) virtual void ForwardBufferedEndTimeChangeToDemuxerHost( base::TimeDelta buffered_time) {} diff --git a/media/base/media_url_demuxer.cc b/media/base/media_url_demuxer.cc index c836d6086545532d9a979f7cb4c8c1d47b5492a7..cabe22b5bf95bd6e3cf9903c95b8b4beb111135c 100644 --- a/media/base/media_url_demuxer.cc +++ b/media/base/media_url_demuxer.cc @@ -59,6 +59,11 @@ void MediaUrlDemuxer::ForwardDurationChangeToDemuxerHost( host_->SetDuration(duration); } +void MediaUrlDemuxer::SetHeaders( + const base::flat_map& headers) { + params_.headers = std::move(headers); +} + #if defined(OHOS_CUSTOM_VIDEO_PLAYER) void MediaUrlDemuxer::ForwardBufferedEndTimeChangeToDemuxerHost( base::TimeDelta buffered_time) { diff --git a/media/base/media_url_demuxer.h b/media/base/media_url_demuxer.h index 63607dad2e164508bbe6fc06158a8007f7f989d3..6ad2c0a29125dc3a7cf8756f24aa5002ea415f77 100644 --- a/media/base/media_url_demuxer.h +++ b/media/base/media_url_demuxer.h @@ -51,6 +51,8 @@ class MEDIA_EXPORT MediaUrlDemuxer : public Demuxer { const MediaUrlParams& GetMediaUrlParams() const override; MediaResource::Type GetType() const override; void ForwardDurationChangeToDemuxerHost(base::TimeDelta duration) override; + void SetHeaders( + const base::flat_map& headers) override; #if defined(OHOS_CUSTOM_VIDEO_PLAYER) void ForwardBufferedEndTimeChangeToDemuxerHost( diff --git a/media/base/media_url_params.h b/media/base/media_url_params.h index 3d5a0db6b86ddae69ff571e279a5979d655daf4a..1a0af9c618e6a66e10306d28cf65103319d4d0cb 100644 --- a/media/base/media_url_params.h +++ b/media/base/media_url_params.h @@ -5,6 +5,7 @@ #ifndef MEDIA_BASE_MEDIA_URL_PARAMS_H_ #define MEDIA_BASE_MEDIA_URL_PARAMS_H_ +#include "base/containers/flat_map.h" #include "media/base/media_export.h" #include "net/cookies/site_for_cookies.h" #include "url/gurl.h" @@ -58,6 +59,9 @@ struct MEDIA_EXPORT MediaUrlParams { // detected to be HLS. Used only for metrics. bool is_hls; + // HTTP Request Headers + base::flat_map headers; + #if defined(OHOS_CUSTOM_VIDEO_PLAYER) CustomMediaUrlParams custom_media_url_params; #endif // OHOS_CUSTOM_VIDEO_PLAYER diff --git a/media/base/ohos/BUILD.gn b/media/base/ohos/BUILD.gn index 72f6ec86b7844f34536eac7097bb8ceebd544443..f2a4695b4014256e323275e5487ceebca06b3ad1 100644 --- a/media/base/ohos/BUILD.gn +++ b/media/base/ohos/BUILD.gn @@ -22,6 +22,8 @@ if (is_ohos) { "ohos_media_codec_bridge_impl.cc", "ohos_media_codec_bridge_impl.h", "ohos_media_codec_bridge.h", + "ohos_media_resource_getter.cc", + "ohos_media_resource_getter.h", "ohos_media_codec_util.cc", "ohos_media_codec_util.h", "buffer_flush_config_adapter_impl.cc", diff --git a/media/base/ohos/ohos_media_player_bridge.cc b/media/base/ohos/ohos_media_player_bridge.cc index 89629351655f0a136559beae2014446867900e22..00627d817660929871559afebbd111bc421aee7f 100644 --- a/media/base/ohos/ohos_media_player_bridge.cc +++ b/media/base/ohos/ohos_media_player_bridge.cc @@ -24,10 +24,12 @@ OHOSMediaPlayerBridge::OHOSMediaPlayerBridge( const net::SiteForCookies& site_for_cookies, const url::Origin& top_frame_origin, const std::string& user_agent, + bool has_storage_access, bool hide_url_log, Client* client, bool allow_credentials, - bool is_hls) + bool is_hls, + const base::flat_map headers) : client_(client), url_(url), prepared_(false), @@ -36,7 +38,15 @@ OHOSMediaPlayerBridge::OHOSMediaPlayerBridge( should_seek_on_prepare_(false), should_set_volume_on_prepare_(false), seeking_on_playback_complete_(false), - seeking_back_complete_(false) { + seeking_back_complete_(false), + headers_(std::move(headers)), + user_agent_(user_agent), + site_for_cookies_(site_for_cookies), + pending_retrieve_cookies_(false), + should_prepare_on_retrieved_cookies_(false), + has_storage_access_(has_storage_access), + top_frame_origin_(top_frame_origin), + allow_credentials_(allow_credentials) { #if defined(RK3568) is_hls_ = is_hls; #endif @@ -51,9 +61,71 @@ int32_t OHOSMediaPlayerBridge::Initialize() { NOTREACHED(); return PLAYER_INIT_ERROR; } + if (allow_credentials_ && client_ != nullptr) { + media::OHOSMediaResourceGetter* resource_getter_ = client_->GetMediaResourceGetter(); + pending_retrieve_cookies_ = true; + if (resource_getter_) { + resource_getter_->GetCookies( + url_, site_for_cookies_, top_frame_origin_, has_storage_access_, + base::BindOnce(&OHOSMediaPlayerBridge::OnCookiesRetrieved, + weak_factory_.GetWeakPtr())); + } + } return PLAYER_INIT_OK; } +void OHOSMediaPlayerBridge::OnCookiesRetrieved(const std::string& cookies) { + cookies_ = cookies; + pending_retrieve_cookies_ = false; + if (client_ == nullptr || client_->GetMediaResourceGetter() == nullptr) { + return; + } + client_->GetMediaResourceGetter()->GetAuthCredentials( + url_, base::BindOnce(&OHOSMediaPlayerBridge::OnAuthCredentialsRetrieved, + weak_factory_.GetWeakPtr())); + + if (should_prepare_on_retrieved_cookies_) { + should_prepare_on_retrieved_cookies_ = false; + if (!player_) { + LOG(ERROR) << "player_ is null"; + return; + } + auto player_headers = GetPlayerHeadersInternal(); + int32_t ret = player_->SetMediaSourceHeader(url_.spec(), player_headers); + if (ret != 0) { + LOG(ERROR) << "SetPlayerSourceHeader error:ret= " << ret; + return; + } + SetPlayerSurface(); + } +} + +void OHOSMediaPlayerBridge::OnAuthCredentialsRetrieved(const std::u16string& username, + const std::u16string& password) { + GURL::ReplacementsW replacements; + if (!username.empty()) { + replacements.SetUsernameStr(username); + if (!password.empty()) { + replacements.SetPasswordStr(password); + } + url_ = url_.ReplaceComponents(replacements); + } +} + +std::map OHOSMediaPlayerBridge::GetPlayerHeadersInternal() { + std::map player_headers; + if (!cookies_.empty()) { + player_headers.insert(std::pair("Cookie", cookies_)); + } + if (!user_agent_.empty()) { + player_headers.insert(std::pair("User-Agent", user_agent_)); + } + for (const auto& entry : headers_) { + player_headers[entry.first] = entry.second; + } + return player_headers; +} + void OHOSMediaPlayerBridge::Start() { if (!player_) { pending_play_ = true; @@ -99,13 +171,26 @@ void OHOSMediaPlayerBridge::Prepare() { if (url_.SchemeIsFile()) { ret = SetFdSource(url_.GetContent()); } else { - ret = player_->SetSource(url_.spec()); + if (pending_retrieve_cookies_) { + should_prepare_on_retrieved_cookies_ = true; + return; + } + auto player_headers = GetPlayerHeadersInternal(); + ret = player_->SetMediaSourceHeader(url_.spec(), player_headers); } if (ret != 0) { LOG(ERROR) << "SetSource error::ret=" << ret; return; } + SetPlayerSurface(); + +} +void OHOSMediaPlayerBridge::SetPlayerSurface() { + if (!player_) { + LOG(ERROR) << "OHOSMediaPlayerBridge SetPlayerSurface player is null"; + return; + } consumer_surface_ = OHOS::NWeb::OhosAdapterHelper::GetInstance() .CreateConsumerSurfaceAdapter(); if (consumer_surface_ == nullptr) { @@ -119,7 +204,7 @@ void OHOSMediaPlayerBridge::Prepare() { surfaceFormat, std::to_string(OHOS::NWeb::PixelFormatAdapter::PIXEL_FMT_RGBA_8888)); consumer_surface_->SetQueueSize(QUEUE_SIZE); - ret = player_->SetVideoSurface(consumer_surface_); + int32_t ret = player_->SetVideoSurface(consumer_surface_); if (ret != 0) { LOG(ERROR) << "SetVideoSurface error::ret=" << ret; consumer_surface_ = nullptr; diff --git a/media/base/ohos/ohos_media_player_bridge.h b/media/base/ohos/ohos_media_player_bridge.h index a984ebd9560831ad9838bd0b81dc00fb7f2dfa00..ab58955a402ffccc281c600f845bde3108e92f09 100644 --- a/media/base/ohos/ohos_media_player_bridge.h +++ b/media/base/ohos/ohos_media_player_bridge.h @@ -8,6 +8,7 @@ #include #include "base/memory/weak_ptr.h" +#include "base/containers/flat_map.h" #include "base/task/single_thread_task_runner.h" #include "base/timer/timer.h" #include "graphic_adapter.h" @@ -16,6 +17,7 @@ #include "net/cookies/site_for_cookies.h" #include "url/gurl.h" #include "url/origin.h" +#include "media/base/ohos/ohos_media_resource_getter.h" namespace media { class MEDIA_EXPORT OHOSMediaPlayerBridge { @@ -48,6 +50,8 @@ class MEDIA_EXPORT OHOSMediaPlayerBridge { virtual void OnAudioStateChanged(bool isAudible) = 0; virtual void OnPlayerSeekBack(base::TimeDelta back_time) = 0; + + virtual OHOSMediaResourceGetter* GetMediaResourceGetter() = 0; }; enum MediaErrorType { @@ -62,10 +66,12 @@ class MEDIA_EXPORT OHOSMediaPlayerBridge { const net::SiteForCookies& site_for_cookies, const url::Origin& top_frame_origin, const std::string& user_agent, + bool has_storage_access, bool hide_url_log, Client* client, bool allow_credentials, - bool is_hls); + bool is_hls, + const base::flat_map headers); virtual ~OHOSMediaPlayerBridge(); OHOSMediaPlayerBridge(const OHOSMediaPlayerBridge&) = delete; @@ -100,6 +106,21 @@ class MEDIA_EXPORT OHOSMediaPlayerBridge { void PropagateDuration(base::TimeDelta duration); bool IsAudible(float volume); + // Callback function passed to `resource_getter_`. Called when the cookies + // are retrieved. + void OnCookiesRetrieved(const std::string& cookies); + + // Callback function passed to `resource_getter_`. Called when the auth + // credentials are retrieved. + void OnAuthCredentialsRetrieved(const std::u16string& username, + const std::u16string& password); + + // Get media player header + std::map GetPlayerHeadersInternal(); + + // Set media player surface and register listener + void SetPlayerSurface(); + const std::string surfaceFormat = "SURFACE_FORMAT"; std::unique_ptr player_ = nullptr; std::deque> cached_buffers_; @@ -132,6 +153,33 @@ class MEDIA_EXPORT OHOSMediaPlayerBridge { bool is_hls_; #endif + // HTTP Request Headers + base::flat_map headers_; + + // User agent string to be used for media player. + const std::string user_agent_; + + // Used to determine if cookies are accessed in a third-party context. + net::SiteForCookies site_for_cookies_; + + // Waiting to retrieve cookies for `url_`. + bool pending_retrieve_cookies_; + + // Whether to prepare after cookies retrieved. + bool should_prepare_on_retrieved_cookies_; + + // Used when determining if first-party cookies may be accessible in a third-party context. + bool has_storage_access_; + + // Cookies for `url_`. + std::string cookies_; + + // Used to check for cookie content settings. + url::Origin top_frame_origin_; + + // Whether user credentials are allowed to be passed. + bool allow_credentials_; + base::WeakPtrFactory weak_factory_{this}; }; } // namespace media diff --git a/media/base/ohos/ohos_media_resource_getter.cc b/media/base/ohos/ohos_media_resource_getter.cc new file mode 100644 index 0000000000000000000000000000000000000000..41a7b87ed45eb5b55a11b0f7f74cd3b29fd8bf6a --- /dev/null +++ b/media/base/ohos/ohos_media_resource_getter.cc @@ -0,0 +1,11 @@ +// Copyright 2024 The Huawei Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/base/ohos/ohos_media_resource_getter.h" + +namespace media { + +OHOSMediaResourceGetter::~OHOSMediaResourceGetter() {} + +} // namespace media \ No newline at end of file diff --git a/media/base/ohos/ohos_media_resource_getter.h b/media/base/ohos/ohos_media_resource_getter.h new file mode 100644 index 0000000000000000000000000000000000000000..40f28e5bc493f11f329de2213bc4630aa59273df --- /dev/null +++ b/media/base/ohos/ohos_media_resource_getter.h @@ -0,0 +1,58 @@ +// Copyright 2024 The Huawei Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_BASE_OHOS_MEDIA_RESOURCE_GETTER_H_ +#define MEDIA_BASE_OHOS_MEDIA_RESOURCE_GETTER_H_ + +#include + +#include + +#include "base/functional/callback.h" +#include "base/time/time.h" +#include "media/base/media_export.h" +#include "url/gurl.h" + +namespace net { +class SiteForCookies; +} // namespace net + +namespace url { +class Origin; +} // namespace url + +namespace media { + +// Class for asynchronously retrieving resources for a media URL. All callbacks +// are executed on the caller's thread. +class MEDIA_EXPORT OHOSMediaResourceGetter { + public: + // Callback to get the cookies. Args: cookies string. + typedef base::OnceCallback GetCookieCB; + + // Callback to get the auth credentials. Args: username and password. + typedef base::OnceCallback + GetAuthCredentialsCB; + + // Callback to get the media metadata. Args: duration, width, height, and + // whether the information is retrieved successfully. + typedef base::OnceCallback + ExtractMediaMetadataCB; + virtual ~OHOSMediaResourceGetter(); + + // Method for getting the auth credentials for a URL. + virtual void GetAuthCredentials(const GURL& url, + GetAuthCredentialsCB callback) = 0; + + // Method for getting the cookies for a given URL. + virtual void GetCookies(const GURL& url, + const net::SiteForCookies& site_for_cookies, + const url::Origin& top_frame_origin, + bool has_storage_access, + GetCookieCB callback) = 0; +}; + +} // namespace media + +#endif // MEDIA_BASE_OHOS_MEDIA_RESOURCE_GETTER_H_ \ No newline at end of file diff --git a/media/filters/demuxer_manager.cc b/media/filters/demuxer_manager.cc index 852c18a54c48aca300bd58e0f7fcc63dd64e4fbf..f2345bc8b09f33166e7ceab2f1f26f14a3b34563 100644 --- a/media/filters/demuxer_manager.cc +++ b/media/filters/demuxer_manager.cc @@ -264,6 +264,10 @@ void DemuxerManager::SetLoadedUrl(GURL url) { loaded_url_ = std::move(url); } +const GURL& DemuxerManager::LoadedUrl() const { + return loaded_url_; +} + #if BUILDFLAG(ENABLE_HLS_DEMUXER) || BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_OHOS) void DemuxerManager::PopulateHlsHistograms(bool cryptographic_url) { @@ -409,7 +413,8 @@ PipelineStatus DemuxerManager::CreateDemuxer( uint32_t initial_preload, uint32_t media_source_type, #endif // OHOS_CUSTOM_VIDEO_PLAYER - DemuxerManager::DemuxerCreatedCB on_demuxer_created) { + DemuxerManager::DemuxerCreatedCB on_demuxer_created, + base::flat_map headers) { // TODO(crbug/1377053) return a better error if (!client_) { return DEMUXER_ERROR_COULD_NOT_OPEN; @@ -417,7 +422,7 @@ PipelineStatus DemuxerManager::CreateDemuxer( #if defined(OHOS_CUSTOM_VIDEO_PLAYER) if (should_create_custom_renderer) { - SetDemuxer(CreateMediaUrlDemuxer(false)); + SetDemuxer(CreateMediaUrlDemuxer(false, headers)); demuxer_->SetPreloadType(initial_preload); demuxer_->SetMediaSourceType(media_source_type); return std::move(on_demuxer_created) @@ -431,7 +436,7 @@ PipelineStatus DemuxerManager::CreateDemuxer( const bool media_player_hls = hls_fallback_ == HlsFallbackImplementation::kMediaPlayer; if (media_player_hls || client_->IsMediaPlayerRendererClient()) { - SetDemuxer(CreateMediaUrlDemuxer(media_player_hls)); + SetDemuxer(CreateMediaUrlDemuxer(media_player_hls, headers)); return std::move(on_demuxer_created) .Run(demuxer_.get(), Pipeline::StartType::kNormal, /*is_streaming = */ false, @@ -638,11 +643,15 @@ std::unique_ptr DemuxerManager::CreateHlsDemuxer() { #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_OHOS) std::unique_ptr DemuxerManager::CreateMediaUrlDemuxer( - bool expect_hls_content) { - return std::make_unique( - media_task_runner_, loaded_url_, site_for_cookies_, top_frame_origin_, - has_storage_access_, allow_media_player_renderer_credentials_, - expect_hls_content); + bool expect_hls_content, + base::flat_map headers) { + std::unique_ptr media_url_demuxer = + std::make_unique( + media_task_runner_, loaded_url_, site_for_cookies_, top_frame_origin_, + has_storage_access_, allow_media_player_renderer_credentials_, + expect_hls_content); + media_url_demuxer->SetHeaders(headers); + return media_url_demuxer; } #endif // BUILDFLAG(IS_ANDROID) diff --git a/media/filters/demuxer_manager.h b/media/filters/demuxer_manager.h index 6386834e286db7929514adf6d7ead7daf5780ff9..4fc385133b92227a7c4b677b31329e45a0beb0b8 100644 --- a/media/filters/demuxer_manager.h +++ b/media/filters/demuxer_manager.h @@ -128,6 +128,7 @@ class MEDIA_EXPORT DemuxerManager { void OnPipelineError(PipelineStatus error); void SetLoadedUrl(GURL url); + const GURL& LoadedUrl() const; #if BUILDFLAG(ENABLE_HLS_DEMUXER) || BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_OHOS) void PopulateHlsHistograms(bool cryptographic_url); PipelineStatus SelectHlsFallbackMechanism(bool cryptographic_url); @@ -150,7 +151,8 @@ class MEDIA_EXPORT DemuxerManager { uint32_t initial_preload, uint32_t media_source_type, #endif // OHOS_CUSTOM_VIDEO_PLAYER - DemuxerCreatedCB on_demuxer_created); + DemuxerCreatedCB on_demuxer_created, + base::flat_map headers); #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_OHOS) void SetAllowMediaPlayerRendererCredentials(bool allow); @@ -188,7 +190,9 @@ class MEDIA_EXPORT DemuxerManager { #endif #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_OHOS) - std::unique_ptr CreateMediaUrlDemuxer(bool hls_content); + std::unique_ptr CreateMediaUrlDemuxer( + bool hls_content, + base::flat_map headers); #endif // BUILDFLAG(IS_ANDROID) void SetDemuxer(std::unique_ptr demuxer); diff --git a/media/mojo/clients/mojo_renderer.cc b/media/mojo/clients/mojo_renderer.cc index 150fbf0c98707337339753ea82856d5fbde972a5..5f19907f915ee70d87c471a27fce9866fee4b7c4 100644 --- a/media/mojo/clients/mojo_renderer.cc +++ b/media/mojo/clients/mojo_renderer.cc @@ -136,7 +136,7 @@ void MojoRenderer::InitializeRendererFromUrl(media::RendererClient* client) { mojom::MediaUrlParamsPtr media_url_params = mojom::MediaUrlParams::New( url_params.media_url, url_params.site_for_cookies, url_params.top_frame_origin, url_params.has_storage_access, - url_params.allow_credentials, url_params.is_hls + url_params.allow_credentials, url_params.is_hls, url_params.headers #if defined(OHOS_CUSTOM_VIDEO_PLAYER) , std::move(custom_media_url_params) #endif // OHOS_CUSTOM_VIDEO_PLAYER diff --git a/media/mojo/mojom/renderer.mojom b/media/mojo/mojom/renderer.mojom index 899c2eda67e1d8d0a1b939713852c9f51c9b0ea2..470103243afd8e98e17d6171c71b571fde2df001 100644 --- a/media/mojo/mojom/renderer.mojom +++ b/media/mojo/mojom/renderer.mojom @@ -27,6 +27,7 @@ struct MediaUrlParams { bool has_storage_access; bool allow_credentials; bool is_hls; + map headers; [EnableIf=ohos_custom_video_player] CustomMediaUrlParams custom_media_url_params; diff --git a/media/mojo/services/mojo_renderer_service.cc b/media/mojo/services/mojo_renderer_service.cc index 3b041541f07fd06c4c83328638673cb7c7b5817b..9005f2e577e644d9f07e869717967d4b1e31c3db 100644 --- a/media/mojo/services/mojo_renderer_service.cc +++ b/media/mojo/services/mojo_renderer_service.cc @@ -85,6 +85,7 @@ void MojoRendererService::Initialize( media_resource_->SetMediaSourceType( media_url_params->custom_media_url_params->media_source_type); #endif // OHOS_CUSTOM_VIDEO_PLAYER + media_resource_->SetHeaders(media_url_params->headers); renderer_->Initialize( media_resource_.get(), this, base::BindOnce(&MojoRendererService::OnRendererInitializeDone, weak_this_,