From 447ade61ad7b3a6ad0a2953a166aca5aab076940 Mon Sep 17 00:00:00 2001 From: Lei Gao Date: Fri, 11 Dec 2020 06:33:12 +0000 Subject: [PATCH] Ensure cookies retrieved before setDataSource. When invoking MediaPlayer's setDataSource() API, cookies may not retrieved. In some case the media will playback failed if the required cookies absent. This CL will check whether the cookies are retrieved before call this API. API call will be pending until cookies retrieved. Bug: 1157376 Change-Id: I43f04461af86c83e53a169bb4df35cbe20419b6d Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2584203 Commit-Queue: Thomas Guilbert Reviewed-by: Thomas Guilbert Cr-Commit-Position: refs/heads/master@{#836018} --- AUTHORS | 1 + media/base/android/media_player_bridge.cc | 72 ++++++++++++++++------- media/base/android/media_player_bridge.h | 7 +++ 3 files changed, 59 insertions(+), 21 deletions(-) diff --git a/AUTHORS b/AUTHORS index a6199904cd1434..ba96c989b73948 100644 --- a/AUTHORS +++ b/AUTHORS @@ -611,6 +611,7 @@ Lavar Askew Le Hoang Quyen Legend Lee Leith Bade +Lei Gao Lei Li Lenny Khazan Leo Wolf diff --git a/media/base/android/media_player_bridge.cc b/media/base/android/media_player_bridge.cc index eeab111c2747fd..ab2029dc1e183c 100644 --- a/media/base/android/media_player_bridge.cc +++ b/media/base/android/media_player_bridge.cc @@ -80,6 +80,8 @@ MediaPlayerBridge::MediaPlayerBridge(const GURL& url, url_(url), site_for_cookies_(site_for_cookies), top_frame_origin_(top_frame_origin), + pending_retrieve_cookies_(false), + should_prepare_on_retrieved_cookies_(false), user_agent_(user_agent), hide_url_log_(hide_url_log), width_(0), @@ -127,6 +129,7 @@ void MediaPlayerBridge::Initialize() { media::MediaResourceGetter* resource_getter = client_->GetMediaResourceGetter(); + pending_retrieve_cookies_ = true; resource_getter->GetCookies( url_, site_for_cookies_, top_frame_origin_, base::BindOnce(&MediaPlayerBridge::OnCookiesRetrieved, @@ -200,31 +203,52 @@ void MediaPlayerBridge::SetDataSource(const std::string& url) { OnMediaError(MEDIA_ERROR_FORMAT); return; } - } else { - // Create a Java String for the URL. - ScopedJavaLocalRef j_url_string = - ConvertUTF8ToJavaString(env, url); - - const std::string data_uri_prefix("data:"); - if (base::StartsWith(url, data_uri_prefix, base::CompareCase::SENSITIVE)) { - if (!Java_MediaPlayerBridge_setDataUriDataSource( - env, j_media_player_bridge_, j_url_string)) { - OnMediaError(MEDIA_ERROR_FORMAT); - } - return; - } - ScopedJavaLocalRef j_cookies = ConvertUTF8ToJavaString( - env, cookies_); - ScopedJavaLocalRef j_user_agent = ConvertUTF8ToJavaString( - env, user_agent_); + if (!Java_MediaPlayerBridge_prepareAsync(env, j_media_player_bridge_)) + OnMediaError(MEDIA_ERROR_FORMAT); + + return; + } - if (!Java_MediaPlayerBridge_setDataSource(env, j_media_player_bridge_, - j_url_string, j_cookies, - j_user_agent, hide_url_log_)) { + // Create a Java String for the URL. + ScopedJavaLocalRef j_url_string = ConvertUTF8ToJavaString(env, url); + + const std::string data_uri_prefix("data:"); + if (base::StartsWith(url, data_uri_prefix, base::CompareCase::SENSITIVE)) { + if (!Java_MediaPlayerBridge_setDataUriDataSource( + env, j_media_player_bridge_, j_url_string)) { OnMediaError(MEDIA_ERROR_FORMAT); - return; } + return; + } + + // Cookies may not have been retrieved yet, delay prepare until they are + // retrieved. + if (pending_retrieve_cookies_) { + should_prepare_on_retrieved_cookies_ = true; + return; + } + SetDataSourceInternal(); +} + +void MediaPlayerBridge::SetDataSourceInternal() { + DCHECK(!pending_retrieve_cookies_); + + JNIEnv* env = base::android::AttachCurrentThread(); + CHECK(env); + + ScopedJavaLocalRef j_cookies = + ConvertUTF8ToJavaString(env, cookies_); + ScopedJavaLocalRef j_user_agent = + ConvertUTF8ToJavaString(env, user_agent_); + ScopedJavaLocalRef j_url_string = + ConvertUTF8ToJavaString(env, url_.spec()); + + if (!Java_MediaPlayerBridge_setDataSource(env, j_media_player_bridge_, + j_url_string, j_cookies, + j_user_agent, hide_url_log_)) { + OnMediaError(MEDIA_ERROR_FORMAT); + return; } if (!Java_MediaPlayerBridge_prepareAsync(env, j_media_player_bridge_)) @@ -267,9 +291,15 @@ void MediaPlayerBridge::OnDidSetDataUriDataSource( void MediaPlayerBridge::OnCookiesRetrieved(const std::string& cookies) { cookies_ = cookies; + pending_retrieve_cookies_ = false; client_->GetMediaResourceGetter()->GetAuthCredentials( url_, base::BindOnce(&MediaPlayerBridge::OnAuthCredentialsRetrieved, weak_factory_.GetWeakPtr())); + + if (should_prepare_on_retrieved_cookies_) { + SetDataSourceInternal(); + should_prepare_on_retrieved_cookies_ = false; + } } void MediaPlayerBridge::OnAuthCredentialsRetrieved( diff --git a/media/base/android/media_player_bridge.h b/media/base/android/media_player_bridge.h index 8757e09b24a3f8..5fe28991b69257 100644 --- a/media/base/android/media_player_bridge.h +++ b/media/base/android/media_player_bridge.h @@ -153,6 +153,7 @@ class MEDIA_EXPORT MediaPlayerBridge { // Set the data source for the media player. void SetDataSource(const std::string& url); + void SetDataSourceInternal(); // Functions that implements media player control. void StartInternal(); @@ -220,6 +221,12 @@ class MEDIA_EXPORT MediaPlayerBridge { // Used to check for cookie content settings. url::Origin top_frame_origin_; + // Waiting to retrieve cookies for |url_|. + bool pending_retrieve_cookies_; + + // Whether to prepare after cookies retrieved. + bool should_prepare_on_retrieved_cookies_; + // User agent string to be used for media player. const std::string user_agent_;