3

I am trying to build a Chrome Extension that can interact with videos in YouTube.

I can get the player element and use the Youtube's IFrame API functions on them in my browser console without no issue, like:

var player = document.getElementById('movie_player');
player.playVideo()
player.pauseVideo()
player.seekTo(30)
player.getStatsForNerds(0)

But I want to do these kinds of operation through a Chrome Extension. The issue is when I try to use the player element to use these functions in an extension it returns errors like this:

Uncaught TypeError: player.playVideo is not a function

I thought I may need to load the IFrame API, but when I try to load it it returns:

Refused to load the script 'https://www.youtube.com/iframe_api' because it violates the following Content Security Policy directive: "script-src 'self'". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.

My project directory:

├── manifest.json
├── content-scripts.js
└── background.js

manifest.json:

{
  "name": "My Project",
  "description": "Some Description",
  "version": "1.0",
  "manifest_version": 3,
  "background": {
    "service_worker": "background.js"
  },
  "content_scripts": [
    {
      "matches": ["https://www.youtube.com/*"],
      "exclude_matches": ["https://studio.youtube.com/*"],
      "js": ["content-scripts.js"]
    }
  ],
  "web_accessible_resources": [
    {
      "resources": ["content-scripts.js"],
      "matches": ["https://www.youtube.com/*"]
    }
  ],
  "permissions": [
    "activeTab",
    "tabs",
    "contextMenus",
    "storage",
    "scripting"
  ],
  "host_permissions": ["https://www.youtube.com/*"]
}

content-scripts.js:

function inject_yt() {
    player = document.getElementById('movie_player');

    var speeds = new Array();
    var resolutions = new Array();
    var times = new Array();
    var buffer = new Array();

    stats_collect = setInterval(stats, 1000);
}

function stats() {
    try {
        bandwidth = player.getStatsForNerds(0).bandwidth_kbps;
        res = player.getStatsForNerds(0).resolution;
        buffers = player.getStatsForNerds(0).buffer_health_seconds;

        speeds.push(bandwidth);
        resolutions.push(res);
        buffer.push(buffers);
        currentTime = player.getCurrentTime();
        times.push(currentTime);
    }
    catch(err) {
        console.error(err);
    }
}

var tag = document.createElement('script');
tag.src = 'https://www.youtube.com/iframe_api';
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

function onYouTubeIframeAPIReady() {
    console.log('--- the YT player API is ready from content script! ---');
};

inject_yt()

And background.js is just an empty file.

How can I make this work?

bhdrozgn
  • 167
  • 10
  • 1
    No need to load the iframe API. You need to insert the code that accesses it in [page context](/a/9517879) (your first snippet). – wOxxOm Mar 29 '22 at 13:23

0 Answers0