From c63c162a9d58622afccc8d530e43cbf0705fdfa0 Mon Sep 17 00:00:00 2001 From: tapanmodh Date: Sat, 9 Mar 2024 01:53:07 +0530 Subject: [PATCH 1/5] youtube fullscreen in landscape --- android/brave_java_sources.gni | 1 + .../BackgroundVideoPlaybackTabHelper.java | 31 +++++++ .../chrome/browser/app/BraveActivity.java | 71 +++++++++++++--- .../toolbar/top/BraveToolbarLayoutImpl.java | 10 ++- .../background_video_playback_tab_helper.cc | 80 ++++++++++++++++++- build/android/BUILD.gn | 1 + build/android/config.gni | 1 + 7 files changed, 179 insertions(+), 16 deletions(-) create mode 100644 android/java/org/chromium/chrome/browser/BackgroundVideoPlaybackTabHelper.java diff --git a/android/brave_java_sources.gni b/android/brave_java_sources.gni index 670fd69672e0..20c3eb4732d0 100644 --- a/android/brave_java_sources.gni +++ b/android/brave_java_sources.gni @@ -20,6 +20,7 @@ import("//brave/components/signin/public/android/java_sources.gni") import("//components/feed/features.gni") brave_java_sources = [ + "../../brave/android/java/org/chromium/chrome/browser/BackgroundVideoPlaybackTabHelper.java", "../../brave/android/java/org/chromium/chrome/browser/BraveAdFreeCalloutDialogFragment.java", "../../brave/android/java/org/chromium/chrome/browser/BraveAppHooks.java", "../../brave/android/java/org/chromium/chrome/browser/BraveApplicationImplBase.java", diff --git a/android/java/org/chromium/chrome/browser/BackgroundVideoPlaybackTabHelper.java b/android/java/org/chromium/chrome/browser/BackgroundVideoPlaybackTabHelper.java new file mode 100644 index 000000000000..5ff0d9a89139 --- /dev/null +++ b/android/java/org/chromium/chrome/browser/BackgroundVideoPlaybackTabHelper.java @@ -0,0 +1,31 @@ +/* Copyright (c) 2024 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +package org.chromium.chrome.browser; + +import org.jni_zero.JNINamespace; +import org.jni_zero.NativeMethods; + +import org.chromium.content_public.browser.WebContents; + +@JNINamespace("chrome::android") +public class BackgroundVideoPlaybackTabHelper { + + public static void sendOrientationChangeEvent(WebContents webContents, boolean isFullScreen) { + BackgroundVideoPlaybackTabHelperJni.get() + .sendOrientationChangeEvent(webContents, isFullScreen); + } + + public static boolean isPlayingMedia(WebContents webContents) { + return BackgroundVideoPlaybackTabHelperJni.get().isPlayingMedia(webContents); + } + + @NativeMethods + interface Natives { + void sendOrientationChangeEvent(WebContents webContents, boolean isFullScreen); + + boolean isPlayingMedia(WebContents webContents); + } +} diff --git a/android/java/org/chromium/chrome/browser/app/BraveActivity.java b/android/java/org/chromium/chrome/browser/app/BraveActivity.java index fbbf5d520776..d4ff3e5e7855 100644 --- a/android/java/org/chromium/chrome/browser/app/BraveActivity.java +++ b/android/java/org/chromium/chrome/browser/app/BraveActivity.java @@ -10,6 +10,7 @@ import android.app.Activity; import android.app.NotificationChannel; import android.app.NotificationManager; +import android.app.PictureInPictureParams; import android.content.Context; import android.content.Intent; import android.content.IntentSender; @@ -83,6 +84,7 @@ import org.chromium.brave_wallet.mojom.TxService; import org.chromium.chrome.R; import org.chromium.chrome.browser.ApplicationLifetime; +import org.chromium.chrome.browser.BackgroundVideoPlaybackTabHelper; import org.chromium.chrome.browser.BraveAdFreeCalloutDialogFragment; import org.chromium.chrome.browser.BraveFeatureUtil; import org.chromium.chrome.browser.BraveHelper; @@ -217,18 +219,21 @@ import java.util.List; import java.util.Locale; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; -/** - * Brave's extension for ChromeActivity - */ +/** Brave's extension for ChromeActivity */ @JNINamespace("chrome::android") public abstract class BraveActivity extends ChromeActivity - implements BrowsingDataBridge.OnClearBrowsingDataListener, BraveVpnObserver, - OnBraveSetDefaultBrowserListener, ConnectionErrorHandler, PrefObserver, - BraveSafeBrowsingApiHandler.BraveSafeBrowsingApiHandlerDelegate, - BraveNewsConnectionErrorHandler.BraveNewsConnectionErrorHandlerDelegate, - MiscAndroidMetricsConnectionErrorHandler - .MiscAndroidMetricsConnectionErrorHandlerDelegate { + implements BrowsingDataBridge.OnClearBrowsingDataListener, + BraveVpnObserver, + OnBraveSetDefaultBrowserListener, + ConnectionErrorHandler, + PrefObserver, + BraveSafeBrowsingApiHandler.BraveSafeBrowsingApiHandlerDelegate, + BraveNewsConnectionErrorHandler.BraveNewsConnectionErrorHandlerDelegate, + MiscAndroidMetricsConnectionErrorHandler + .MiscAndroidMetricsConnectionErrorHandlerDelegate { public static final String BRAVE_WALLET_HOST = "wallet"; public static final String BRAVE_WALLET_URL = "brave://wallet/crypto/portfolio/assets"; public static final String BRAVE_BUY_URL = "brave://wallet/crypto/fund-wallet"; @@ -261,6 +266,8 @@ public abstract class BraveActivity extends ChromeActivity public static final int APP_OPEN_COUNT_FOR_WIDGET_PROMO = 25; + private static final String TAG = "BraveActivity"; + private static final boolean ENABLE_IN_APP_UPDATE = Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE; @@ -366,9 +373,31 @@ public void onPauseWithNative() { if (BraveVpnUtils.isVpnFeatureSupported(BraveActivity.this)) { BraveVpnNativeWorker.getInstance().removeObserver(this); } + super.onPauseWithNative(); } + @Override + public void onUserLeaveHint() { + super.onUserLeaveHint(); + if (isActivityFinishingOrDestroyed()) return; + Tab currentTab = getActivityTab(); + if (currentTab != null + && currentTab.getUrl().getSpec() != null + && isYTVideoUrl(currentTab.getUrl().getSpec()) + && !isInPictureInPictureMode() + && BackgroundVideoPlaybackTabHelper.isPlayingMedia(currentTab.getWebContents())) { + BackgroundVideoPlaybackTabHelper.sendOrientationChangeEvent( + currentTab.getWebContents(), true); + try { + enterPictureInPictureMode(new PictureInPictureParams.Builder().build()); + } catch (IllegalStateException | IllegalArgumentException e) { + Log.e(TAG, "Error entering PiP: " + e); + return; + } + } + } + @Override public boolean onMenuOrKeyboardAction(int id, boolean fromMenu) { final Tab currentTab = getActivityTab(); @@ -1378,6 +1407,30 @@ public void initBraveNewsController() { } } + @Override + public void performOnConfigurationChanged(Configuration newConfig) { + super.performOnConfigurationChanged(newConfig); + + Tab currentTab = getActivityTab(); + if (currentTab != null + && currentTab.getUrl().getSpec() != null + && isYTVideoUrl(currentTab.getUrl().getSpec()) + && !isInPictureInPictureMode()) { + BackgroundVideoPlaybackTabHelper.sendOrientationChangeEvent( + currentTab.getWebContents(), + newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE); + } + } + + private boolean isYTVideoUrl(String url) { + + String pattern = + "^(?:https?:)?(?:\\/\\/)?(?:youtu\\.be\\/|(?:www\\.|m\\.)?youtube\\.com\\/(?:watch|v|embed)(?:\\.php)?(?:\\?.*v=|\\/))([a-zA-Z0-9\\_-]{7,15})(?:[\\?&][a-zA-Z0-9\\_-]+=[a-zA-Z0-9\\_-]+)*(?:[&\\/\\#].*)?$"; + Pattern compiledPattern = Pattern.compile(pattern); + Matcher matcher = compiledPattern.matcher(url); + return matcher.find(); + } + private void migrateBgPlaybackToFeature() { if (ChromeSharedPreferences.getInstance() .readBoolean( diff --git a/android/java/org/chromium/chrome/browser/toolbar/top/BraveToolbarLayoutImpl.java b/android/java/org/chromium/chrome/browser/toolbar/top/BraveToolbarLayoutImpl.java index 537611809498..35c42250b408 100644 --- a/android/java/org/chromium/chrome/browser/toolbar/top/BraveToolbarLayoutImpl.java +++ b/android/java/org/chromium/chrome/browser/toolbar/top/BraveToolbarLayoutImpl.java @@ -144,9 +144,13 @@ import java.util.function.BooleanSupplier; public abstract class BraveToolbarLayoutImpl extends ToolbarLayout - implements BraveToolbarLayout, OnClickListener, View.OnLongClickListener, - BraveRewardsObserver, BraveRewardsNativeWorker.PublisherObserver, - ConnectionErrorHandler, PlaylistServiceObserverImplDelegate { + implements BraveToolbarLayout, + OnClickListener, + View.OnLongClickListener, + BraveRewardsObserver, + BraveRewardsNativeWorker.PublisherObserver, + ConnectionErrorHandler, + PlaylistServiceObserverImplDelegate { private static final String TAG = "BraveToolbar"; private static final List BRAVE_SEARCH_ENGINE_DEFAULT_REGIONS = diff --git a/browser/android/preferences/background_video_playback_tab_helper.cc b/browser/android/preferences/background_video_playback_tab_helper.cc index fdbdcd95c114..57e07baf82ff 100644 --- a/browser/android/preferences/background_video_playback_tab_helper.cc +++ b/browser/android/preferences/background_video_playback_tab_helper.cc @@ -9,11 +9,15 @@ #include "base/strings/utf_string_conversions.h" #include "brave/browser/android/preferences/features.h" +#include "brave/build/android/jni_headers/BackgroundVideoPlaybackTabHelper_jni.h" #include "brave/components/brave_shields/content/browser/brave_shields_util.h" #include "brave/components/constants/pref_names.h" +#include "brave/components/script_injector/common/mojom/script_injector.mojom.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/common/chrome_isolated_world_ids.h" #include "components/prefs/pref_service.h" +#include "content/browser/media/session/media_session_impl.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/navigation_entry.h" @@ -28,10 +32,10 @@ const char16_t k_youtube_background_playback_script[] = " if (document._addEventListener === undefined) {" " document._addEventListener = document.addEventListener;" " document.addEventListener = function(a,b,c) {" - " if(a != 'visibilitychange') {" - " document._addEventListener(a,b,c);" - " }" - " };" + " if(a != 'visibilitychange') {" + " document._addEventListener(a,b,c);" + " }" + " };" " }" "}());"; @@ -80,4 +84,72 @@ void BackgroundVideoPlaybackTabHelper::DidFinishNavigation( } } +namespace chrome { +namespace android { + +mojo::AssociatedRemote GetRemote( + content::RenderFrameHost* rfh) { + mojo::AssociatedRemote + script_injector_remote; + rfh->GetRemoteAssociatedInterfaces()->GetInterface(&script_injector_remote); + return script_injector_remote; +} +void JNI_BackgroundVideoPlaybackTabHelper_SendOrientationChangeEvent( + JNIEnv* env, + const base::android::JavaParamRef& jweb_contents, + jboolean is_full_screen) { + content::WebContents* web_contents = + content::WebContents::FromJavaWebContents(jweb_contents); + std::string script; + if (is_full_screen) { + script = + "if(!document.fullscreenElement) {" + " var fullscreenBtn = " + " document.getElementsByClassName('fullscreen-icon');" + " if(fullscreenBtn && fullscreenBtn.length > 0) {" + " fullscreenBtn[0].click();" + " } else {" + " var moviePlayer = document.getElementById('movie_player');" + " if (moviePlayer) {" + " moviePlayer.click();" + " }" + " setTimeout(() => {" + " var fullscreenBtn = " + " document.getElementsByClassName('fullscreen-icon');" + " if(fullscreenBtn && fullscreenBtn.length > 0) {" + " fullscreenBtn[0].click();" + " }" + " }, 50);" + " }" + "}"; + } else { + script = + "if(document.fullscreenElement) {" + " document.exitFullscreen();" + "}"; + } + GetRemote(web_contents->GetPrimaryMainFrame()) + ->RequestAsyncExecuteScript( + ISOLATED_WORLD_ID_BRAVE_INTERNAL, base::UTF8ToUTF16(script), + blink::mojom::UserActivationOption::kActivate, + blink::mojom::PromiseResultOption::kAwait, base::NullCallback()); +} + +jboolean JNI_BackgroundVideoPlaybackTabHelper_IsPlayingMedia( + JNIEnv* env, + const base::android::JavaParamRef& jweb_contents) { + content::WebContents* web_contents = + content::WebContents::FromJavaWebContents(jweb_contents); + content::MediaSessionImpl* media_session_impl = + content::MediaSessionImpl::Get(web_contents); + if (!media_session_impl) { + return false; + } + media_session::mojom::MediaSessionInfoPtr current_info = + media_session_impl->GetMediaSessionInfoSync(); + return current_info->playback_state == + media_session::mojom::MediaPlaybackState::kPlaying; +} +} // namespace android +} // namespace chrome WEB_CONTENTS_USER_DATA_KEY_IMPL(BackgroundVideoPlaybackTabHelper); diff --git a/build/android/BUILD.gn b/build/android/BUILD.gn index 178c1c12df9e..bf5ac2e619dd 100644 --- a/build/android/BUILD.gn +++ b/build/android/BUILD.gn @@ -205,6 +205,7 @@ brave_xml_preprocessor("brave_java_xml_preprocess_resources") { generate_jni("jni_headers") { sources = [ + "//brave/android/java/org/chromium/chrome/browser/BackgroundVideoPlaybackTabHelper.java", "//brave/android/java/org/chromium/chrome/browser/BraveFeatureUtil.java", "//brave/android/java/org/chromium/chrome/browser/BraveLocalState.java", "//brave/android/java/org/chromium/chrome/browser/BraveRelaunchUtils.java", diff --git a/build/android/config.gni b/build/android/config.gni index 4c1de2d025d9..07cc6edf6733 100644 --- a/build/android/config.gni +++ b/build/android/config.gni @@ -93,6 +93,7 @@ playcore_target = "//brave/third_party/android_deps:com_google_android_play_core_java" brave_jni_headers_sources = [ + "//brave/android/java/org/chromium/chrome/browser/BackgroundVideoPlaybackTabHelper.java", "//brave/android/java/org/chromium/chrome/browser/BraveFeatureUtil.java", "//brave/android/java/org/chromium/chrome/browser/BraveLocalState.java", "//brave/android/java/org/chromium/chrome/browser/BraveRelaunchUtils.java", From 2dcfeff832c9d68461d196933546208f17750184 Mon Sep 17 00:00:00 2001 From: tapanmodh Date: Fri, 31 May 2024 18:25:16 +0530 Subject: [PATCH 2/5] update deps file --- browser/android/preferences/DEPS | 1 + 1 file changed, 1 insertion(+) diff --git a/browser/android/preferences/DEPS b/browser/android/preferences/DEPS index 5eef23681832..402829bf144b 100644 --- a/browser/android/preferences/DEPS +++ b/browser/android/preferences/DEPS @@ -1,5 +1,6 @@ specific_include_rules = { "background_video_playback_tab_helper.cc": [ + "+content/browser/media/session/media_session_impl.h", "+content/browser/web_contents/web_contents_impl.h", ], } From 7b7a1bd0b420d718da677206dde9c21782c6fbe1 Mon Sep 17 00:00:00 2001 From: tapanmodh Date: Mon, 3 Jun 2024 16:47:59 +0530 Subject: [PATCH 3/5] update youtube video url check --- .../chrome/browser/app/BraveActivity.java | 27 ++++++++++--------- .../background_video_playback_tab_helper.cc | 2 ++ 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/android/java/org/chromium/chrome/browser/app/BraveActivity.java b/android/java/org/chromium/chrome/browser/app/BraveActivity.java index d4ff3e5e7855..84aca83f7579 100644 --- a/android/java/org/chromium/chrome/browser/app/BraveActivity.java +++ b/android/java/org/chromium/chrome/browser/app/BraveActivity.java @@ -212,6 +212,7 @@ import org.chromium.mojo.bindings.ConnectionErrorHandler; import org.chromium.mojo.system.MojoException; import org.chromium.ui.widget.Toast; +import org.chromium.url.GURL; import java.util.Arrays; import java.util.Calendar; @@ -219,8 +220,6 @@ import java.util.List; import java.util.Locale; import java.util.concurrent.CopyOnWriteArrayList; -import java.util.regex.Matcher; -import java.util.regex.Pattern; /** Brave's extension for ChromeActivity */ @JNINamespace("chrome::android") @@ -383,8 +382,8 @@ public void onUserLeaveHint() { if (isActivityFinishingOrDestroyed()) return; Tab currentTab = getActivityTab(); if (currentTab != null - && currentTab.getUrl().getSpec() != null - && isYTVideoUrl(currentTab.getUrl().getSpec()) + && currentTab.getUrl() != null + && isYTVideoUrl(currentTab.getUrl()) && !isInPictureInPictureMode() && BackgroundVideoPlaybackTabHelper.isPlayingMedia(currentTab.getWebContents())) { BackgroundVideoPlaybackTabHelper.sendOrientationChangeEvent( @@ -1413,8 +1412,8 @@ public void performOnConfigurationChanged(Configuration newConfig) { Tab currentTab = getActivityTab(); if (currentTab != null - && currentTab.getUrl().getSpec() != null - && isYTVideoUrl(currentTab.getUrl().getSpec()) + && currentTab.getUrl() != null + && isYTVideoUrl(currentTab.getUrl()) && !isInPictureInPictureMode()) { BackgroundVideoPlaybackTabHelper.sendOrientationChangeEvent( currentTab.getWebContents(), @@ -1422,13 +1421,17 @@ && isYTVideoUrl(currentTab.getUrl().getSpec()) } } - private boolean isYTVideoUrl(String url) { + private boolean isYTVideoUrl(GURL url) { - String pattern = - "^(?:https?:)?(?:\\/\\/)?(?:youtu\\.be\\/|(?:www\\.|m\\.)?youtube\\.com\\/(?:watch|v|embed)(?:\\.php)?(?:\\?.*v=|\\/))([a-zA-Z0-9\\_-]{7,15})(?:[\\?&][a-zA-Z0-9\\_-]+=[a-zA-Z0-9\\_-]+)*(?:[&\\/\\#].*)?$"; - Pattern compiledPattern = Pattern.compile(pattern); - Matcher matcher = compiledPattern.matcher(url); - return matcher.find(); + if (!GURL.isEmptyOrInvalid(url) + && url.domainIs(BraveConstants.YOUTUBE_DOMAIN) + && url.getPath() != null + && url.getPath().equalsIgnoreCase("/watch") + && url.getQuery() != null) { + String videoId = UrlUtilities.getValueForKeyInQuery(url, "v"); + return videoId != null && videoId.trim().length() > 0; + } + return false; } private void migrateBgPlaybackToFeature() { diff --git a/browser/android/preferences/background_video_playback_tab_helper.cc b/browser/android/preferences/background_video_playback_tab_helper.cc index 57e07baf82ff..7b4dfe39c7de 100644 --- a/browser/android/preferences/background_video_playback_tab_helper.cc +++ b/browser/android/preferences/background_video_playback_tab_helper.cc @@ -100,6 +100,8 @@ void JNI_BackgroundVideoPlaybackTabHelper_SendOrientationChangeEvent( jboolean is_full_screen) { content::WebContents* web_contents = content::WebContents::FromJavaWebContents(jweb_contents); + // Injecting this script to make youtube video fullscreen on landscape mode + // and exit fullscreen on portrait mode. std::string script; if (is_full_screen) { script = From e6613e4e5747d42790d15217577c9540694b5885 Mon Sep 17 00:00:00 2001 From: tapanmodh Date: Tue, 4 Jun 2024 00:51:30 +0530 Subject: [PATCH 4/5] fix component build error --- browser/android/preferences/BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/browser/android/preferences/BUILD.gn b/browser/android/preferences/BUILD.gn index 17a3651be378..dc88ae543481 100644 --- a/browser/android/preferences/BUILD.gn +++ b/browser/android/preferences/BUILD.gn @@ -26,6 +26,7 @@ source_set("preferences") { "//brave/components/brave_shields/core/common", "//brave/components/brave_sync", "//brave/components/p3a", + "//brave/components/script_injector/common/mojom", "//components/content_settings/core/browser", "//components/prefs", "//content/public/browser", From 14a4d00dcb61b511cd8b6ee1c6d31464233a63bd Mon Sep 17 00:00:00 2001 From: tapanmodh Date: Mon, 24 Jun 2024 10:11:07 +0530 Subject: [PATCH 5/5] address PR comments --- .../BackgroundVideoPlaybackTabHelper.java | 7 +- .../chrome/browser/app/BraveActivity.java | 5 +- browser/android/preferences/BUILD.gn | 2 - .../background_video_playback_tab_helper.cc | 108 +++++++++--------- .../background_video_playback_tab_helper.h | 7 ++ 5 files changed, 67 insertions(+), 62 deletions(-) diff --git a/android/java/org/chromium/chrome/browser/BackgroundVideoPlaybackTabHelper.java b/android/java/org/chromium/chrome/browser/BackgroundVideoPlaybackTabHelper.java index 5ff0d9a89139..181ae866316e 100644 --- a/android/java/org/chromium/chrome/browser/BackgroundVideoPlaybackTabHelper.java +++ b/android/java/org/chromium/chrome/browser/BackgroundVideoPlaybackTabHelper.java @@ -13,9 +13,8 @@ @JNINamespace("chrome::android") public class BackgroundVideoPlaybackTabHelper { - public static void sendOrientationChangeEvent(WebContents webContents, boolean isFullScreen) { - BackgroundVideoPlaybackTabHelperJni.get() - .sendOrientationChangeEvent(webContents, isFullScreen); + public static void toggleFullscreen(WebContents webContents, boolean isFullScreen) { + BackgroundVideoPlaybackTabHelperJni.get().toggleFullscreen(webContents, isFullScreen); } public static boolean isPlayingMedia(WebContents webContents) { @@ -24,7 +23,7 @@ public static boolean isPlayingMedia(WebContents webContents) { @NativeMethods interface Natives { - void sendOrientationChangeEvent(WebContents webContents, boolean isFullScreen); + void toggleFullscreen(WebContents webContents, boolean isFullScreen); boolean isPlayingMedia(WebContents webContents); } diff --git a/android/java/org/chromium/chrome/browser/app/BraveActivity.java b/android/java/org/chromium/chrome/browser/app/BraveActivity.java index 84aca83f7579..541d83a1b5f5 100644 --- a/android/java/org/chromium/chrome/browser/app/BraveActivity.java +++ b/android/java/org/chromium/chrome/browser/app/BraveActivity.java @@ -386,8 +386,7 @@ public void onUserLeaveHint() { && isYTVideoUrl(currentTab.getUrl()) && !isInPictureInPictureMode() && BackgroundVideoPlaybackTabHelper.isPlayingMedia(currentTab.getWebContents())) { - BackgroundVideoPlaybackTabHelper.sendOrientationChangeEvent( - currentTab.getWebContents(), true); + BackgroundVideoPlaybackTabHelper.toggleFullscreen(currentTab.getWebContents(), true); try { enterPictureInPictureMode(new PictureInPictureParams.Builder().build()); } catch (IllegalStateException | IllegalArgumentException e) { @@ -1415,7 +1414,7 @@ public void performOnConfigurationChanged(Configuration newConfig) { && currentTab.getUrl() != null && isYTVideoUrl(currentTab.getUrl()) && !isInPictureInPictureMode()) { - BackgroundVideoPlaybackTabHelper.sendOrientationChangeEvent( + BackgroundVideoPlaybackTabHelper.toggleFullscreen( currentTab.getWebContents(), newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE); } diff --git a/browser/android/preferences/BUILD.gn b/browser/android/preferences/BUILD.gn index dc88ae543481..25cb0d16e123 100644 --- a/browser/android/preferences/BUILD.gn +++ b/browser/android/preferences/BUILD.gn @@ -7,8 +7,6 @@ import("//brave/components/ai_chat/core/common/buildflags/buildflags.gni") import("//build/config/android/rules.gni") source_set("preferences") { - # Remove when https://github.com/brave/brave-browser/issues/10657 is resolved - check_includes = false sources = [ "background_video_playback_tab_helper.cc", "background_video_playback_tab_helper.h", diff --git a/browser/android/preferences/background_video_playback_tab_helper.cc b/browser/android/preferences/background_video_playback_tab_helper.cc index 7b4dfe39c7de..874ec1b9cf52 100644 --- a/browser/android/preferences/background_video_playback_tab_helper.cc +++ b/browser/android/preferences/background_video_playback_tab_helper.cc @@ -7,26 +7,26 @@ #include -#include "base/strings/utf_string_conversions.h" #include "brave/browser/android/preferences/features.h" #include "brave/build/android/jni_headers/BackgroundVideoPlaybackTabHelper_jni.h" #include "brave/components/brave_shields/content/browser/brave_shields_util.h" #include "brave/components/constants/pref_names.h" #include "brave/components/script_injector/common/mojom/script_injector.mojom.h" -#include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/chrome_isolated_world_ids.h" #include "components/prefs/pref_service.h" -#include "content/browser/media/session/media_session_impl.h" -#include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/web_contents.h" +#include "mojo/public/cpp/bindings/associated_remote.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" +#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" #include "url/gurl.h" namespace { +bool is_media_playing_ = false; + const char16_t k_youtube_background_playback_script[] = u"(function() {" " if (document._addEventListener === undefined) {" @@ -62,6 +62,14 @@ bool IsBackgroundVideoPlaybackEnabled(content::WebContents* contents) { return true; } + +mojo::AssociatedRemote GetRemote( + content::RenderFrameHost* rfh) { + mojo::AssociatedRemote + script_injector_remote; + rfh->GetRemoteAssociatedInterfaces()->GetInterface(&script_injector_remote); + return script_injector_remote; +} } // namespace BackgroundVideoPlaybackTabHelper::BackgroundVideoPlaybackTabHelper( @@ -84,17 +92,23 @@ void BackgroundVideoPlaybackTabHelper::DidFinishNavigation( } } +void BackgroundVideoPlaybackTabHelper::MediaStartedPlaying( + const MediaPlayerInfo& /*video_type*/, + const content::MediaPlayerId& id) { + is_media_playing_ = true; +} + +void BackgroundVideoPlaybackTabHelper::MediaStoppedPlaying( + const MediaPlayerInfo& /*video_type*/, + const content::MediaPlayerId& id, + WebContentsObserver::MediaStoppedReason /*reason*/) { + is_media_playing_ = false; +} + namespace chrome { namespace android { -mojo::AssociatedRemote GetRemote( - content::RenderFrameHost* rfh) { - mojo::AssociatedRemote - script_injector_remote; - rfh->GetRemoteAssociatedInterfaces()->GetInterface(&script_injector_remote); - return script_injector_remote; -} -void JNI_BackgroundVideoPlaybackTabHelper_SendOrientationChangeEvent( +void JNI_BackgroundVideoPlaybackTabHelper_ToggleFullscreen( JNIEnv* env, const base::android::JavaParamRef& jweb_contents, jboolean is_full_screen) { @@ -102,55 +116,43 @@ void JNI_BackgroundVideoPlaybackTabHelper_SendOrientationChangeEvent( content::WebContents::FromJavaWebContents(jweb_contents); // Injecting this script to make youtube video fullscreen on landscape mode // and exit fullscreen on portrait mode. - std::string script; if (is_full_screen) { - script = - "if(!document.fullscreenElement) {" - " var fullscreenBtn = " - " document.getElementsByClassName('fullscreen-icon');" - " if(fullscreenBtn && fullscreenBtn.length > 0) {" - " fullscreenBtn[0].click();" - " } else {" - " var moviePlayer = document.getElementById('movie_player');" - " if (moviePlayer) {" - " moviePlayer.click();" - " }" - " setTimeout(() => {" - " var fullscreenBtn = " - " document.getElementsByClassName('fullscreen-icon');" - " if(fullscreenBtn && fullscreenBtn.length > 0) {" - " fullscreenBtn[0].click();" - " }" - " }, 50);" - " }" - "}"; + constexpr const char16_t script[] = + uR"js(if(!document.fullscreenElement) { + var fullscreenBtn = + document.getElementsByClassName('fullscreen-icon'); + if(fullscreenBtn && fullscreenBtn.length > 0) { + fullscreenBtn[0].click(); + } else { + var moviePlayer = document.getElementById('movie_player'); + if (moviePlayer) { + moviePlayer.click(); + } + setTimeout(() => { + var fullscreenBtn = + document.getElementsByClassName('fullscreen-icon'); + if(fullscreenBtn && fullscreenBtn.length > 0) { + fullscreenBtn[0].click(); + } + }, 50); + } + } )js"; + GetRemote(web_contents->GetPrimaryMainFrame()) + ->RequestAsyncExecuteScript( + ISOLATED_WORLD_ID_BRAVE_INTERNAL, script, + blink::mojom::UserActivationOption::kActivate, + blink::mojom::PromiseResultOption::kAwait, base::NullCallback()); } else { - script = - "if(document.fullscreenElement) {" - " document.exitFullscreen();" - "}"; + if (web_contents->HasActiveEffectivelyFullscreenVideo()) { + web_contents->ExitFullscreen(true); + } } - GetRemote(web_contents->GetPrimaryMainFrame()) - ->RequestAsyncExecuteScript( - ISOLATED_WORLD_ID_BRAVE_INTERNAL, base::UTF8ToUTF16(script), - blink::mojom::UserActivationOption::kActivate, - blink::mojom::PromiseResultOption::kAwait, base::NullCallback()); } jboolean JNI_BackgroundVideoPlaybackTabHelper_IsPlayingMedia( JNIEnv* env, const base::android::JavaParamRef& jweb_contents) { - content::WebContents* web_contents = - content::WebContents::FromJavaWebContents(jweb_contents); - content::MediaSessionImpl* media_session_impl = - content::MediaSessionImpl::Get(web_contents); - if (!media_session_impl) { - return false; - } - media_session::mojom::MediaSessionInfoPtr current_info = - media_session_impl->GetMediaSessionInfoSync(); - return current_info->playback_state == - media_session::mojom::MediaPlaybackState::kPlaying; + return is_media_playing_; } } // namespace android } // namespace chrome diff --git a/browser/android/preferences/background_video_playback_tab_helper.h b/browser/android/preferences/background_video_playback_tab_helper.h index 7ef245e0b562..2852da85105c 100644 --- a/browser/android/preferences/background_video_playback_tab_helper.h +++ b/browser/android/preferences/background_video_playback_tab_helper.h @@ -24,6 +24,13 @@ class BackgroundVideoPlaybackTabHelper void DidFinishNavigation( content::NavigationHandle* navigation_handle) override; + void MediaStartedPlaying(const MediaPlayerInfo& video_type, + const content::MediaPlayerId& id) override; + void MediaStoppedPlaying( + const MediaPlayerInfo& video_type, + const content::MediaPlayerId& id, + WebContentsObserver::MediaStoppedReason reason) override; + WEB_CONTENTS_USER_DATA_KEY_DECL(); };