Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: enable picture-in-picture mode for video tags #17686

Merged
merged 6 commits into from Aug 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions buildflags/BUILD.gn
Expand Up @@ -18,6 +18,7 @@ buildflag_header("buildflags") {
"ENABLE_TTS=$enable_tts",
"ENABLE_COLOR_CHOOSER=$enable_color_chooser",
"ENABLE_ELECTRON_EXTENSIONS=$enable_electron_extensions",
"ENABLE_PICTURE_IN_PICTURE=$enable_picture_in_picture",
"OVERRIDE_LOCATION_PROVIDER=$enable_fake_location_provider",
]
}
2 changes: 2 additions & 0 deletions buildflags/buildflags.gni
Expand Up @@ -18,6 +18,8 @@ declare_args() {

enable_color_chooser = true

enable_picture_in_picture = true

# Provide a fake location provider for mocking
# the geolocation responses. Disable it if you
# need to test with chromium's location provider.
Expand Down
28 changes: 28 additions & 0 deletions chromium_src/BUILD.gn
Expand Up @@ -184,4 +184,32 @@ static_library("chrome") {
]
}
}

if (enable_picture_in_picture) {
sources += [
"//chrome/browser/picture_in_picture/picture_in_picture_window_manager.cc",
"//chrome/browser/picture_in_picture/picture_in_picture_window_manager.h",
"//chrome/browser/ui/views/overlay/back_to_tab_image_button.cc",
"//chrome/browser/ui/views/overlay/back_to_tab_image_button.h",
"//chrome/browser/ui/views/overlay/close_image_button.cc",
"//chrome/browser/ui/views/overlay/close_image_button.h",
"//chrome/browser/ui/views/overlay/mute_image_button.cc",
"//chrome/browser/ui/views/overlay/mute_image_button.h",
"//chrome/browser/ui/views/overlay/overlay_window_views.cc",
"//chrome/browser/ui/views/overlay/overlay_window_views.h",
"//chrome/browser/ui/views/overlay/playback_image_button.cc",
"//chrome/browser/ui/views/overlay/playback_image_button.h",
"//chrome/browser/ui/views/overlay/resize_handle_button.cc",
"//chrome/browser/ui/views/overlay/resize_handle_button.h",
"//chrome/browser/ui/views/overlay/skip_ad_label_button.cc",
"//chrome/browser/ui/views/overlay/skip_ad_label_button.h",
"//chrome/browser/ui/views/overlay/track_image_button.cc",
"//chrome/browser/ui/views/overlay/track_image_button.h",
]

deps += [
"//chrome/app/vector_icons",
"//components/vector_icons:vector_icons",
]
}
}
51 changes: 51 additions & 0 deletions electron_strings.grdp
Expand Up @@ -18,4 +18,55 @@
<message name="IDS_DESKTOP_MEDIA_PICKER_MULTIPLE_SCREEN_NAME" desc="Name for screens in the desktop media picker UI when there are multiple monitors.">
{SCREEN_INDEX, plural, =1{Screen #} other{Screen #}}
</message>

<!-- Picture-in-Picture -->
<if expr="is_macosx">
<message name="IDS_PICTURE_IN_PICTURE_TITLE_TEXT" desc="Title of the Picture-in-Picture window. This appears in the system tray and window header.">
Picture in Picture
</message>
</if>
<if expr="not is_macosx">
<message name="IDS_PICTURE_IN_PICTURE_TITLE_TEXT" desc="Title of the Picture-in-Picture window. This appears in the system tray and window header.">
Picture in picture
</message>
</if>
<message name="IDS_PICTURE_IN_PICTURE_PAUSE_CONTROL_TEXT" desc="Text label of the pause control button. The button appears when the user hovers over the Picture-in-Picture window and the video is currently playing.">
Pause
</message>
<message name="IDS_PICTURE_IN_PICTURE_PLAY_CONTROL_TEXT" desc="Text label of the play control button. The button appears when the user hovers over the Picture-in-Picture window and the video is currently paused.">
Play
</message>
<message name="IDS_PICTURE_IN_PICTURE_REPLAY_CONTROL_TEXT" desc="Text label of the replay control button. The button appears when the user hovers over the Picture-in-Picture window and the video is ended.">
Play from the beginning
</message>
<message name="IDS_PICTURE_IN_PICTURE_BACK_TO_TAB_CONTROL_TEXT" desc="Text label of the back to tab control button. The button appears when the user hovers over the Picture-in-Picture window.">
Back to video player
</message>
<message name="IDS_PICTURE_IN_PICTURE_MUTE_CONTROL_TEXT" desc="Text label of the mute control button. The button appears when the user hovers over the Picture-in-Picture window and the video is currently unmuted.">
Mute
</message>
<message name="IDS_PICTURE_IN_PICTURE_UNMUTE_CONTROL_TEXT" desc="Text label of the mute control button. The button appears when the user hovers over the Picture-in-Picture window and the video is currently muted.">
Unmute
</message>
<message name="IDS_PICTURE_IN_PICTURE_SKIP_AD_CONTROL_TEXT" desc="Text label of the skip ad control button. The button appears when the user hovers over the Picture-in-Picture window.">
Skip Ad
</message>
<message name="IDS_PICTURE_IN_PICTURE_CLOSE_CONTROL_TEXT" desc="Text label of the close control button. The button appears when the user hovers over the Picture-in-Picture window.">
Close
</message>
<message name="IDS_PICTURE_IN_PICTURE_RESIZE_HANDLE_TEXT" desc="Text label of the resize handle. The button appears when the user hovers over the Picture-in-Picture window.">
Resize
</message>
<message name="IDS_PICTURE_IN_PICTURE_PLAY_PAUSE_CONTROL_ACCESSIBLE_TEXT" desc="Accessible text label used for the controls button in the Picture-in-Picture window. The button toggles between play and pause controls.">
Toggle video to play or pause
</message>
<message name="IDS_PICTURE_IN_PICTURE_MUTE_CONTROL_ACCESSIBLE_TEXT" desc="Accessible text label used for the controls button in the Picture-in-Picture window. The button toggles mute state.">
Toggle mute
</message>
<message name="IDS_PICTURE_IN_PICTURE_NEXT_TRACK_CONTROL_ACCESSIBLE_TEXT" desc="Accessible text label used for the controls button in the Picture-in-Picture window. The button invokes next track action.">
Next track
</message>
<message name="IDS_PICTURE_IN_PICTURE_PREVIOUS_TRACK_CONTROL_ACCESSIBLE_TEXT" desc="Accessible text label used for the controls button in the Picture-in-Picture window. The button invokes previous track action.">
Previous track
</message>
</grit-part>
1 change: 1 addition & 0 deletions patches/chromium/.patches
Expand Up @@ -74,3 +74,4 @@ build_win_disable_zc_twophase.patch
disable_color_correct_rendering.patch
add_contentgpuclient_precreatemessageloop_callback.patch
fix_vc_incompatible_inline_calls.patch
picture-in-picture.patch
110 changes: 110 additions & 0 deletions patches/chromium/picture-in-picture.patch
@@ -0,0 +1,110 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Heilig Benedek <benecene@gmail.com>
Date: Sat, 10 Aug 2019 00:41:50 +0200
Subject: feat: enable picture in picture mode for video players


diff --git a/chrome/browser/ui/views/overlay/back_to_tab_image_button.cc b/chrome/browser/ui/views/overlay/back_to_tab_image_button.cc
index 8e4deafa1746eeb48802a0503fefb37bedb33d04..127c62efd2327e1f3f09e9b93a0b8344e2714f80 100644
--- a/chrome/browser/ui/views/overlay/back_to_tab_image_button.cc
+++ b/chrome/browser/ui/views/overlay/back_to_tab_image_button.cc
@@ -4,7 +4,7 @@

#include "chrome/browser/ui/views/overlay/back_to_tab_image_button.h"

-#include "chrome/grit/generated_resources.h"
+#include "electron/grit/electron_resources.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/color_palette.h"
diff --git a/chrome/browser/ui/views/overlay/close_image_button.cc b/chrome/browser/ui/views/overlay/close_image_button.cc
index 0aca25164dcad26cc000e289d6eb9010e336e6fc..70114b5aa865b96d3ace898d1faf515b9098abd9 100644
--- a/chrome/browser/ui/views/overlay/close_image_button.cc
+++ b/chrome/browser/ui/views/overlay/close_image_button.cc
@@ -4,7 +4,7 @@

#include "chrome/browser/ui/views/overlay/close_image_button.h"

-#include "chrome/grit/generated_resources.h"
+#include "electron/grit/electron_resources.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/color_palette.h"
diff --git a/chrome/browser/ui/views/overlay/mute_image_button.cc b/chrome/browser/ui/views/overlay/mute_image_button.cc
index 8c88ef08dd5165c0429dd90e8a76b711ac15a4df..ebdb06a6391b8108fa51796a4ad5f3a8ca489b60 100644
--- a/chrome/browser/ui/views/overlay/mute_image_button.cc
+++ b/chrome/browser/ui/views/overlay/mute_image_button.cc
@@ -5,7 +5,7 @@
#include "chrome/browser/ui/views/overlay/mute_image_button.h"

#include "chrome/app/vector_icons/vector_icons.h"
-#include "chrome/grit/generated_resources.h"
+#include "electron/grit/electron_resources.h"
#include "components/vector_icons/vector_icons.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/ui/views/overlay/overlay_window_views.cc b/chrome/browser/ui/views/overlay/overlay_window_views.cc
index 780863193ca12ec1295752969dfc47ac06a9ae64..e2947b893cfcdb1beaa27beac80a1885ed011ce4 100644
--- a/chrome/browser/ui/views/overlay/overlay_window_views.cc
+++ b/chrome/browser/ui/views/overlay/overlay_window_views.cc
@@ -20,7 +20,7 @@
#include "chrome/browser/ui/views/overlay/resize_handle_button.h"
#include "chrome/browser/ui/views/overlay/skip_ad_label_button.h"
#include "chrome/browser/ui/views/overlay/track_image_button.h"
-#include "chrome/grit/generated_resources.h"
+#include "electron/grit/electron_resources.h"
#include "components/vector_icons/vector_icons.h"
#include "content/public/browser/picture_in_picture_window_controller.h"
#include "content/public/browser/web_contents.h"
diff --git a/chrome/browser/ui/views/overlay/playback_image_button.cc b/chrome/browser/ui/views/overlay/playback_image_button.cc
index d9e5174ed622fb030bc37d32fbb40b132d7c4c23..1bf19c344721e74bb29c11a4c5c762a75e5cd821 100644
--- a/chrome/browser/ui/views/overlay/playback_image_button.cc
+++ b/chrome/browser/ui/views/overlay/playback_image_button.cc
@@ -5,7 +5,7 @@
#include "chrome/browser/ui/views/overlay/playback_image_button.h"

#include "chrome/app/vector_icons/vector_icons.h"
-#include "chrome/grit/generated_resources.h"
+#include "electron/grit/electron_resources.h"
#include "components/vector_icons/vector_icons.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/ui/views/overlay/resize_handle_button.cc b/chrome/browser/ui/views/overlay/resize_handle_button.cc
index ee6b3612d7bdda591e05e5af338a80167ce6cd53..af093f14f1ef49c6de7228b296c32532203ca568 100644
--- a/chrome/browser/ui/views/overlay/resize_handle_button.cc
+++ b/chrome/browser/ui/views/overlay/resize_handle_button.cc
@@ -5,7 +5,7 @@
#include "chrome/browser/ui/views/overlay/resize_handle_button.h"

#include "chrome/app/vector_icons/vector_icons.h"
-#include "chrome/grit/generated_resources.h"
+#include "electron/grit/electron_resources.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/hit_test.h"
#include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/ui/views/overlay/skip_ad_label_button.cc b/chrome/browser/ui/views/overlay/skip_ad_label_button.cc
index da780c96bb757d7382df5f419e2c0fd644ac72b0..ae520bcf73cf6c39ca428c03975746e20b23c3ee 100644
--- a/chrome/browser/ui/views/overlay/skip_ad_label_button.cc
+++ b/chrome/browser/ui/views/overlay/skip_ad_label_button.cc
@@ -4,7 +4,7 @@

#include "chrome/browser/ui/views/overlay/skip_ad_label_button.h"

-#include "chrome/grit/generated_resources.h"
+#include "electron/grit/electron_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/color_palette.h"
#include "ui/views/background.h"
diff --git a/chrome/browser/ui/views/overlay/track_image_button.cc b/chrome/browser/ui/views/overlay/track_image_button.cc
index 8f42277409a216f81d21723eb03045ac54525b0e..f7a15bfde9a43c15b18e8afbd60a0b19960f2c93 100644
--- a/chrome/browser/ui/views/overlay/track_image_button.cc
+++ b/chrome/browser/ui/views/overlay/track_image_button.cc
@@ -5,7 +5,7 @@
#include "chrome/browser/ui/views/overlay/track_image_button.h"

#include "chrome/app/vector_icons/vector_icons.h"
-#include "chrome/grit/generated_resources.h"
+#include "electron/grit/electron_resources.h"
#include "components/vector_icons/vector_icons.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/l10n/l10n_util.h"
11 changes: 11 additions & 0 deletions shell/browser/atom_browser_client.cc
Expand Up @@ -402,6 +402,9 @@ void AtomBrowserClient::OverrideWebkitPrefs(content::RenderViewHost* host,
prefs->default_minimum_page_scale_factor = 1.f;
prefs->default_maximum_page_scale_factor = 1.f;
prefs->navigate_on_drag_drop = false;
#if !BUILDFLAG(ENABLE_PICTURE_IN_PICTURE)
prefs->picture_in_picture_enabled = false;
#endif

ui::NativeTheme* native_theme = ui::NativeTheme::GetInstanceForNativeUi();
prefs->preferred_color_scheme = native_theme->ShouldUseDarkColors()
Expand Down Expand Up @@ -684,6 +687,14 @@ bool AtomBrowserClient::CanCreateWindow(
return false;
}

#if BUILDFLAG(ENABLE_PICTURE_IN_PICTURE)
std::unique_ptr<content::OverlayWindow>
AtomBrowserClient::CreateWindowForPictureInPicture(
content::PictureInPictureWindowController* controller) {
return content::OverlayWindow::Create(controller);
}
#endif

void AtomBrowserClient::GetAdditionalAllowedSchemesForFileSystem(
std::vector<std::string>* additional_schemes) {
auto schemes_list = api::GetStandardSchemes();
Expand Down
5 changes: 5 additions & 0 deletions shell/browser/atom_browser_client.h
Expand Up @@ -14,6 +14,7 @@
#include "base/synchronization/lock.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_process_host_observer.h"
#include "electron/buildflags/buildflags.h"
#include "net/ssl/client_cert_identity.h"

namespace content {
Expand Down Expand Up @@ -127,6 +128,10 @@ class AtomBrowserClient : public content::ContentBrowserClient,
bool user_gesture,
bool opener_suppressed,
bool* no_javascript_access) override;
#if BUILDFLAG(ENABLE_PICTURE_IN_PICTURE)
std::unique_ptr<content::OverlayWindow> CreateWindowForPictureInPicture(
content::PictureInPictureWindowController* controller) override;
#endif
void GetAdditionalAllowedSchemesForFileSystem(
std::vector<std::string>* additional_schemes) override;
void GetAdditionalWebUISchemes(
Expand Down
23 changes: 23 additions & 0 deletions shell/browser/common_web_contents_delegate.cc
Expand Up @@ -55,6 +55,10 @@
#include "shell/browser/printing/print_preview_message_handler.h"
#endif

#if BUILDFLAG(ENABLE_PICTURE_IN_PICTURE)
#include "chrome/browser/picture_in_picture/picture_in_picture_window_manager.h"
#endif

using content::BrowserThread;

namespace electron {
Expand Down Expand Up @@ -636,4 +640,23 @@ void CommonWebContentsDelegate::SetHtmlApiFullscreen(bool enter_fullscreen) {
native_fullscreen_ = false;
}

content::PictureInPictureResult
CommonWebContentsDelegate::EnterPictureInPicture(
content::WebContents* web_contents,
const viz::SurfaceId& surface_id,
const gfx::Size& natural_size) {
#if BUILDFLAG(ENABLE_PICTURE_IN_PICTURE)
return PictureInPictureWindowManager::GetInstance()->EnterPictureInPicture(
web_contents, surface_id, natural_size);
#else
return content::PictureInPictureResult::kNotSupported;
#endif
}

void CommonWebContentsDelegate::ExitPictureInPicture() {
#if BUILDFLAG(ENABLE_PICTURE_IN_PICTURE)
PictureInPictureWindowManager::GetInstance()->ExitPictureInPicture();
#endif
}

} // namespace electron
5 changes: 5 additions & 0 deletions shell/browser/common_web_contents_delegate.h
Expand Up @@ -102,6 +102,11 @@ class CommonWebContentsDelegate : public content::WebContentsDelegate,
bool HandleKeyboardEvent(
content::WebContents* source,
const content::NativeWebKeyboardEvent& event) override;
content::PictureInPictureResult EnterPictureInPicture(
content::WebContents* web_contents,
const viz::SurfaceId&,
const gfx::Size& natural_size) override;
void ExitPictureInPicture() override;

// InspectableWebContentsDelegate:
void DevToolsSaveToFile(const std::string& url,
Expand Down
5 changes: 5 additions & 0 deletions shell/browser/feature_list.cc
Expand Up @@ -10,6 +10,8 @@
#include "base/command_line.h"
#include "base/feature_list.h"
#include "content/public/common/content_features.h"
#include "electron/buildflags/buildflags.h"
#include "media/base/media_switches.h"

namespace electron {

Expand All @@ -25,6 +27,9 @@ void InitializeFeatureList() {
// when node integration is enabled.
disable_features +=
std::string(",") + features::kSpareRendererForSitePerProcess.name;
#if !BUILDFLAG(ENABLE_PICTURE_IN_PICTURE)
disable_features += std::string(",") + media::kPictureInPicture.name;
#endif
base::FeatureList::InitializeInstance(enable_features, disable_features);
}

Expand Down
5 changes: 5 additions & 0 deletions shell/common/api/features.cc
Expand Up @@ -45,6 +45,10 @@ bool IsExtensionsEnabled() {
return BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS);
}

bool IsPictureInPictureEnabled() {
return BUILDFLAG(ENABLE_PICTURE_IN_PICTURE);
}

bool IsComponentBuild() {
#if defined(COMPONENT_BUILD)
return true;
Expand All @@ -67,6 +71,7 @@ void Initialize(v8::Local<v8::Object> exports,
dict.SetMethod("isViewApiEnabled", &IsViewApiEnabled);
dict.SetMethod("isTtsEnabled", &IsTtsEnabled);
dict.SetMethod("isPrintingEnabled", &IsPrintingEnabled);
dict.SetMethod("isPictureInPictureEnabled", &IsPictureInPictureEnabled);
dict.SetMethod("isComponentBuild", &IsComponentBuild);
dict.SetMethod("isExtensionsEnabled", &IsExtensionsEnabled);
}
Expand Down
19 changes: 19 additions & 0 deletions spec/api-web-contents-spec.js
Expand Up @@ -1273,4 +1273,23 @@ describe('webContents module', () => {
expect(data).to.be.an.instanceof(Buffer).that.is.not.empty()
})
})

describe('PictureInPicture video', () => {
it('works as expected', (done) => {
w.destroy()
w = new BrowserWindow({
show: false,
webPreferences: {
sandbox: true
}
})
w.webContents.once('did-finish-load', async () => {
const result = await w.webContents.executeJavaScript(
`runTest(${features.isPictureInPictureEnabled()})`, true)
expect(result).to.be.true()
done()
})
w.loadFile(path.join(fixtures, 'api', 'picture-in-picture.html'))
})
})
})