0

I'm using GM to write a custom script for a website. The script adds an embed Youtube player to the page, so I'm calling the Youtube API. Here is the beginning of the code :

// ==UserScript==
// @author       mens
// @match        http://thewebsite.com
// @grant        none
// ==/UserScript==

///////////// YOUTUBE

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

// API loaded
window.onYouTubeIframeAPIReady = function()
{
    console.log("API loaded");
}

With this code, everything works fine. The first few lines call the API, when it's loaded it fires onYouTubeIframeAPIReady, then later on my script generates the player.

You will notice that @grant is set to none. The problem is when I change this line, even the slightest. I use GM_getResourceURL to access external files (like graphics).

So when I set :

// @grant        GM_getResourceURL

...the API doesn't work anymore : onYouTubeIframeAPIReady is never called !

From what I gathered in the GM documentation, @grant none is the default mode that means maximum access to all APIs used in the code. When changing @grant more restrictions may appear... I think that's part of the problem but I have no idea how to work with it.

Thanks for your help !!

mens
  • 43
  • 6
  • Have you considered using `@require` in place of inserting a `script` tag? – arcyqwerty Oct 09 '15 at 17:35
  • yes I tried it, then I get an error : `Uncaught TypeError: YT.Player is not a function`... it seems the YT object used to create the player is not fully loaded – mens Oct 09 '15 at 17:53
  • question whose answer will solve this issue http://stackoverflow.com/questions/13485122/accessing-variables-from-greasemonkey-to-page-vice-versa/13485650 (but technically isn't a duplicate) –  Oct 10 '15 at 01:52

2 Answers2

0

So the trick was simple (but quite mysterious) : I changed window to unsafeWindow by renaming the function :

unsafeWindow.onYouTubeIframeAPIReady = function()
{
    console.log("API loaded");
}

From the GM doc :

unsafeWindow

The unsafeWindow object provides full access to the pages javascript functions and variables.

It seems any @grant other than none puts the window object into a sandbox with limited access from external APIs. I'm still unsure how to set these restrictions correctly, but unsafeWindow bypass them completely.

mens
  • 43
  • 6
0

Instead of this

// API loaded
window.onYouTubeIframeAPIReady = function()
{
    console.log("API loaded");
}

do this

function apiReady() {
    console.log("API loaded");
}
exportFunction(apiReady, unsafeWindow, {defineAs: "onYouTubeIframeAPIReady"});

See Mozilla docs for explanation of exportFunction

However, I'm not 100% convinced yet myself that this is any more "secure" (in greasemonkey) than using unsafeWindow directly

From what I gathered in the GM documentation, @grant none is the default mode that means maximum access to all APIs used in the code.

This is incorrect. What @grant none does is explicitly turn off ALL greasemonkey API's (the GM* functions) and run the script without a sandbox, as there is no possibility of rogue websites using greasemonkey against you.

Jaromanda X
  • 53,868
  • 5
  • 73
  • 87