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

Youtube fullscreen and picture in picture feature #26355

Draft
wants to merge 49 commits into
base: master
Choose a base branch
from

Conversation

simoarpe
Copy link
Collaborator

@simoarpe simoarpe commented Nov 4, 2024

❌ DRAFT PR NOT READY TO REVIEW

Resolves brave/brave-browser#37267

⚠️ Note: this pull request supersedes #23933
🎨 [Under discussion] Figma design (option 4): https://www.figma.com/design/eQclVYFfDpTgztKDCq9ROk/Youtube-Improvements?node-id=541-3325&node-type=section&m=dev

This Android component is solely and fully focused on pages containing YouTube videos and provide some enhancements by injecting two scripts:

  • keep-playing-audio.js this script is something we are already injecting in our stable Brave for Android (check here). It seems to work good, and its only goal is to keep playing the audio when the app goes in background. Because it's battle tested I refrained from touching except for a few comments.

  • fullscreen.js This script instead takes care of triggering the fullscreen mode. It's injected only when one of these two events happen: 1.device rotation in landscape, 2. entering PIP mode. When the script is injected it plays the video if paused, and switch into fullscreen mode.

👇 keep-playing-audio.js

(function() {
    const script = document.createElement('script');
    // Modify the listener by ignoring visibilitychange
    // so when the app goes in background the video
    // is not paused.
    script.textContent = `
        if (document._addEventListener === undefined) {
            document._addEventListener = document.addEventListener;
            document.addEventListener = function(a,b,c) {
                if(a != 'visibilitychange') {
                    document._addEventListener(a,b,c);
                }
            };
        }
    `;
    (document.head || document.documentElement).appendChild(script);
    script.remove();
}());

👇 fullscreen.js

// Always play video before entering fullscreen mode.
document.querySelectorAll(".html5-main-video").forEach((vid) => vid.play());
// Check if the video is not in fullscreen mode already.
if (!document.fullscreenElement) {
  var fullscreenBtn = document.getElementsByClassName("fullscreen-icon");
  // Check if fullscreen button is available.
  if (fullscreenBtn && fullscreenBtn.length > 0) {
    fullscreenBtn[0].click();
  } else {
    // When fullscreen button is not available
    // clicking the movie player resume the UI.
    var moviePlayer = document.getElementById("movie_player");
    if (moviePlayer) {
      // Make sure the player is in focus or responsive.
      moviePlayer.click();
    }
    setTimeout(() => {
      // Wait 100ms to make sure the fullscreen button
      // in the movie player is available.
      var fullscreenBtn = document.getElementsByClassName("fullscreen-icon");
      if (fullscreenBtn && fullscreenBtn.length > 0) {
        fullscreenBtn[0].click();
      }
    }, 100);
  }
} 

New Component Info

Component name: YouTube Script Injector
ID: ninjlighifanhiflenpeafpnanjemako
Public Key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnwhDV1BTzTeDNsi+DxnyxrKqugj/a/8dKQE8usNweMkpORdxFxflbJkA5IErDyW3xca63pdMYhArPjHr0OUBACYKBfzEYF/Yo0kNxxJLWylr7FKwZxOKosmlZXUW8J2wtFu8ua6oQB2lEOk7y2jxwUAka/a0JPxeDsU9ByadmAdVZ7aaiCEGsJgEtHrpPha/2AJi8xerYLeB4bFfFc2bdXKEsN4UzjVLYpCfsKAuxEtO2QC2+Rylz60Vq3ANjjnlXINDJrl3jsSwF6GXHEE4Qzl7Qvu142N9G2rsSxMyPlunD8EGrEjK9fGRc6RPGQy1LbyY3imXpiDp0vXicCaYuwIDAQAB
Key.pem available in 1Password vault. Search for YouTube Script Injector Component.

Example of manifest.json

{
   "description": "Brave YouTube Injector Component",
   "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnwhDV1BTzTeDNsi+DxnyxrKqugj/a/8dKQE8usNweMkpORdxFxflbJkA5IErDyW3xca63pdMYhArPjHr0OUBACYKBfzEYF/Yo0kNxxJLWylr7FKwZxOKosmlZXUW8J2wtFu8ua6oQB2lEOk7y2jxwUAka/a0JPxeDsU9ByadmAdVZ7aaiCEGsJgEtHrpPha/2AJi8xerYLeB4bFfFc2bdXKEsN4UzjVLYpCfsKAuxEtO2QC2+Rylz60Vq3ANjjnlXINDJrl3jsSwF6GXHEE4Qzl7Qvu142N9G2rsSxMyPlunD8EGrEjK9fGRc6RPGQy1LbyY3imXpiDp0vXicCaYuwIDAQAB",
   "manifest_version": 2,
   "name": "Brave YouTube Injector",
   "version": "1"
}

Example of youtube.json

{
  "version": 1,
  "feature_script": "keep-playing-audio.js",
  "fullscreen_script": "fullscreen.js"
}

Submitter Checklist:

  • I confirm that no security/privacy review is needed and no other type of reviews are needed, or that I have requested them
  • There is a ticket for my issue
  • Used Github auto-closing keywords in the PR description above
  • Wrote a good PR/commit description
  • Squashed any review feedback or "fixup" commits before merge, so that history is a record of what happened in the repo, not your PR
  • Added appropriate labels (QA/Yes or QA/No; release-notes/include or release-notes/exclude; OS/...) to the associated issue
  • Checked the PR locally:
    • npm run test -- brave_browser_tests, npm run test -- brave_unit_tests wiki
    • npm run presubmit wiki, npm run gn_check, npm run tslint
  • Ran git rebase master (if needed)

Reviewer Checklist:

  • A security review is not needed, or a link to one is included in the PR description
  • New files have MPL-2.0 license header
  • Adequate test coverage exists to prevent regressions
  • Major classes, functions and non-trivial code blocks are well-commented
  • Changes in component dependencies are properly reflected in gn
  • Code follows the style guide
  • Test plan is specified in PR before merging

After-merge Checklist:

Test Plan:

@simoarpe simoarpe added CI/skip-macos-x64 Do not run CI builds for macOS x64 CI/skip-ios Do not run CI builds for iOS CI/skip-windows-x64 Do not run CI builds for Windows x64 CI/skip-macos-arm64 Do not run CI builds for macOS arm64 labels Nov 4, 2024
@simoarpe simoarpe self-assigned this Nov 4, 2024
@simoarpe simoarpe force-pushed the simone/youtube-fullscreen-pip branch from 32add61 to 2213fcd Compare November 11, 2024 09:37
@simoarpe simoarpe force-pushed the simone/youtube-fullscreen-pip branch from b419b06 to 5c2fc60 Compare November 21, 2024 10:25
@github-actions github-actions bot added the CI/run-upstream-tests Run upstream unit and browser tests on Linux and Windows (otherwise only on Linux) label Nov 26, 2024
@simoarpe simoarpe force-pushed the simone/youtube-fullscreen-pip branch from 3ac8cd7 to 36bb32d Compare November 27, 2024 13:30
Copy link
Contributor

github-actions bot commented Dec 2, 2024

Chromium major version is behind target branch (131.0.6778.85 vs 132.0.6834.15). Please rebase.

@github-actions github-actions bot added the chromium-version-mismatch The Chromium version on the PR branch does not match the version on the target branch label Dec 2, 2024
@simoarpe simoarpe force-pushed the simone/youtube-fullscreen-pip branch from f33ba86 to a3c42b1 Compare December 17, 2024 11:26
@github-actions github-actions bot removed the chromium-version-mismatch The Chromium version on the PR branch does not match the version on the target branch label Dec 17, 2024
FORWARD_DECLARE_TEST(YouTubeTabHelperBrowserTest, RuleMatchTestScriptFalse);
FORWARD_DECLARE_TEST(YouTubeTabHelperBrowserTest, RuleMatchTestScriptTrue);

// This class loads and stores the rules from the youtube.json file.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could have more documentation here. What are some example rules? Is the JSON part of this PR? If not, maybe an example ruleset could be useful.

Copy link
Member

@bsclifton bsclifton Dec 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK I think I have a partial idea of what this is supposed to do. This should be genericizing and centralizing any scripting that we want to do for YouTube, right? For example, we previously had logic in background_video_playback_tab_helper.cc and this PR is removing that file. The background play is one example script that gets loaded.

Where does it get loaded from?

Copy link
Member

@bsclifton bsclifton Dec 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK seems to get loaded from component updater 😄 I see the comments in youtube_component_installer.cc which has the example directory structure and then youtube_json.h has an example of the JSON.

After I figured it out, maybe the ask I have is just adding a comment like:

// - See `youtube_json.h` for an example of the JSON this class loads
// - See `youtube_component_installer.cc` for example of the component layout.
//        This is where the location where the scripts are loaded from.

(unless I didn't understand it correctly!)

Copy link
Collaborator Author

@simoarpe simoarpe Dec 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be genericizing and centralizing any scripting that we want to do for YouTube, right?

Correct! That's the idea. But I haven't created the extension (yet) I've temporarily used extension ID (lhhcaamjbmbijmjbnnodjaknblkiagon) PSST. I'm going over https://github.com/brave/brave-core-crx-packager now. Probably I won't be able to complete the full process as presumably I don't have full access. I'll post an update soon.

Maybe we could have more documentation here. What are some example rules? Is the JSON part of this PR? If not, maybe an example ruleset could be useful.

The idea that seems the best compromize to me would be to have some tests that contain the JS we are injecting.
Same as done by Shivan here https://github.com/brave/brave-core/tree/master/test/data/psst-component-data

I'm also adding the comments you suggested.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improved code comments 👉 ae6fac2 (#26355)

// |_ scripts/
// |_ keep-playing-audio.js
// |_ fullscreen.js
// See youtube_json.cc for the format of youtube.json.
Copy link
Member

@bsclifton bsclifton Dec 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was trying to locate where the component would be. I saw some branches in

But they didn't seem to be packaging a component. Looking at this extension ID (lhhcaamjbmbijmjbnnodjaknblkiagon), it seems we would be piggybacking off the Brave Privacy Settings Selection for Sites Tool (PSST) Files component. That seems to be guarded by the brave://flags/#brave-psst flag (default OFF).

@ShivanKaul does it make sense to club these YouTube specific scripts into the PSST package? For reference, PSST added here.

I also couldn't find any packaging for PSST. Usually, you'd see something in https://github.com/brave/brave-core-crx-packager which would include an npm run command (ex: npm run data-files-local-data-files) then upload to go-update. I checked the job list in ci.brave.com and didn't see anything for PSST either.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll include a better and more elaborate answer tomorrow: I've just picked a temporary extension ID for testing. Next step will be creating a new one specifically for the youtube injector component before marking this PR as ready to review.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have created a new component ID ninjlighifanhiflenpeafpnanjemako and a PEM key, everything has been uploaded to our 1Password vault, search for YouTube Script Injector Component.

You won't be able to find any packaging for the PSST component as it didn't go into production eventually. I've used it as a starting point because the structure for what we need was similar. It's now time to fully diverge.

That seems to be guarded by the brave://flags/#brave-psst flag (default OFF).

That's something I was forced to use because I was using the PSST implementation, but it's now changing.
The new logic can be found in components/youtube_script_injector/common/features.cc where the kBraveYouTubeScriptInjector will be enabled by default and probably behind griffin.

So to answer your question:

does it make sense to club these YouTube specific scripts into the PSST package?

No, I think it does not make any sense, and I'm going to commit the new component ID now.

I also couldn't find any packaging for PSST

Correct, as PSST packaging didn't go into production.

@simoarpe simoarpe force-pushed the simone/youtube-fullscreen-pip branch from 1845ee5 to 2b3ab59 Compare December 20, 2024 12:49
@simoarpe simoarpe force-pushed the simone/youtube-fullscreen-pip branch 2 times, most recently from 6f799f8 to ae6fac2 Compare December 20, 2024 15:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CI/run-upstream-tests Run upstream unit and browser tests on Linux and Windows (otherwise only on Linux) CI/skip-ios Do not run CI builds for iOS CI/skip-macos-arm64 Do not run CI builds for macOS arm64 CI/skip-macos-x64 Do not run CI builds for macOS x64 CI/skip-windows-x64 Do not run CI builds for Windows x64
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Android] YT Improvements: Fullscreen and PIP floating buttons
2 participants