0

I am trying to make a chrome extension that will provide ctrl+left arrow and ctrl+right arrow to backward or forward the YouTube video by 2 seconds. Here is my script :

const player = document.querySelector('ytd-player').getPlayer();
const seconds = 2;
window.addEventListener('keydown', function (e) {
  if (e.ctrlKey) {
    if (e.keyCode === 37) {
      player.seekToStreamTime(player.getCurrentTime() - seconds)
    }
    else if (e.keyCode === 39) {
      player.seekToStreamTime(player.getCurrentTime() + seconds)
    }
  }
})
console.log('youtube-seconds extension loaded.');

The script is working if I run directly from the chrome devTools but if I make an extension with the same code it doesn't work.

After investigating the code I noticed the issue comes from getPlayer function.
The document.querySelector('ytd-player') works well if I console.log but getPlayer returns nothing from the script. How would one explain that ? and how can I make this work ? am I missing a permission or something ?

vdegenne
  • 12,272
  • 14
  • 80
  • 106
  • 1
    I'm guessing the code runs too soon; you probably need to wait until the page has loaded completely. Try wrapping it in a `setTimeout` –  May 11 '20 at 17:22
  • @ChrisG I did that before asking. even I wait 5 seconds it stills returns `undefined` – vdegenne May 11 '20 at 17:25
  • Does this answer your question? [Insert code into the page context using a content script](https://stackoverflow.com/questions/9515704/insert-code-into-the-page-context-using-a-content-script) –  May 11 '20 at 17:44

1 Answers1

3

Content scripts share the same DOM as the original page, but have different JS contexts.

This means that you can't access JS that's on the original page.

What you can do to overcome this is to inject a JS script in the original page. Considering you have access to the same DOM you can use document.createElement('script') to create a script and populate it with your JS code.

Then you can use window.postMessage to send messages to and from your content and injected script.

Radu Diță
  • 13,476
  • 2
  • 30
  • 34
  • OP says they log `document.querySelector('ytd-player')` and it works, so this doesn't seem to be the case. –  May 11 '20 at 17:25
  • You have access to the same DOM, so `document.querySelector*` will work, but as soon you try to access any JS it will stop working. Think about it like this: you only get half of access, when you try to access the other part, it fails. If you are wondering how they achieve this: you have different window objects, but window.document points to the same object. – Radu Diță May 11 '20 at 17:28
  • Ok it makes sense when I read you. `getPlayer` is in the scope of the element's JS! I will try what you suggest to inject code directly into the page. Thanks – vdegenne May 11 '20 at 17:28
  • @RaduDiță ok now it works. Accepting your answer as the solution. – vdegenne May 11 '20 at 17:33
  • 1
    Glad it helped you. – Radu Diță May 11 '20 at 17:34
  • See also [Insert code into the page context using a content script](https://stackoverflow.com/a/9517879) – wOxxOm May 11 '20 at 17:40