Ok, what is happening is that your add-on code and the page do not run in the same environment. This is why you donât have directly access to the YouTube API.
When the page loads, it runs its own javascript context, where the YouTube scripts add dynamically their API like, like function setPlaybackRate()
, to an object associated to DOM DIV element #move_player
(by default this object is a HTMLDivElement which does not support function setPlaybackRate()
).
When you use the page console, you run in this same page environment. This is why you can call document.getElementById("movie_player").setPlaybackRate()
.
However, the content code your add-on injects into the page (using browser.tabs.executeScript()
or content_scripts
in manifest.json
) runs in a separate environment. This one accesses the same DOM structure, but in a different javascript context. This is why when you call document.getElementById("movie_player")
, you get a plain HTMLDivElement
that has not been modified by the YouTube scripts to add functions like setPlaybackRate()
.
Disclaimer: iâm not 100% sure the method below will work with WebExtensions, but i know i used it successfully in the former add-on SDK API.
What you should try is, from the add-on content code, to inject into the page environment a script that does what you want. You should be able to do so, by creating a <script>
element that contains the code you want to execute.
For instance:
// code to be executed by the add-on once you are sure
// the page DOM loaded and YouTube scripts did their
// job installing the API
var script = document.createElement("script");
var code = `if(typeof chrome==="undefined")
document.getElementById("movie_player").setPlaybackRate(2);`;
var codeElement = document.createTextNode(code);
script.appendChild(codeElement);
document.querySelector("head").appendChild(script);
So the add-on code modifies the DOM, and as this DOM is shared with the page environment, this last one will execute the code inside the <script>
element. Of course the add-on content environment will also try to execute that code, this is the reason for the if(typeof chrome==="undefined")
test.
Obviously, if you plan to give control of the YouTube API to the add-on, this solution is not very convenient (but still worth the try to validate the concept).
I would suggest using the HTML5 Window messaging API to make the 2 environments to communicate with each other (use window.addEventListener("message",...)
and window.postMessage(...)
), so that requests from the add-on can be proxied to your code in the page (that you injected with the method above) which will execute them (and possibly will return a result by sending a message back).
I hope this makes sense.