Search code examples
chromiumuserscriptstampermonkey

Is there a way to do a relative file:// @require in Tampermonkey on Chromium?


Is there a way to tell a Tampermonkey script running in Chromium to use a relative @require file path? For example, if I have the following script header:

// ==UserScript==
// @name         test
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  test script
// @author       me
// @match        *://*/*
// @require      file://relative/path/to/external.js
// @grant        GM_setValue
// @grant        GM_getValue
// ==/UserScript==

Am I able to use @require with file:// and make it relative to my user's Chromium profile or the Tampermonkey extension directory? If that's not possible, is there a way to pass a parameter to the Tampermonkey script at time of Chromium launch or include the external .js file in a different way inside the script?

To clarify, I'm trying to create a Kiosk system and the users need the ability to specify which dashboards are displayed and some of those require logins. I want to allow them to specify the required information in an external .js file. Here is the code and example external file.

sample logins.js

var config =
{
  "sites": [
    {
      "description": "All X dashboards",
      "site": "https://dashboards.X.com/index.php?return=",
      "username": "username",
      "password": "password",
      "form": "form-login",
      "username_field": "login",
      "password_field": "password",
      "submit_button": "button-login",
      "redirect": ""
    }
};

Tampermonkey script that uses external file

// ==UserScript==
// @name         test
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  test script
// @author       me
// @match        *://*/*
// @require      file://relative/path/to/logins.js
// @grant        GM_setValue
// @grant        GM_getValue
// ==/UserScript==

var delay = 500;
var attempts = 0;
var maxAttempts = 40;

(function() {
    'use strict';

    var url = GM_getValue("redirect");
    if (url !== undefined && url !== null)
    {
        GM_setValue("redirect", null);
        document.location.href = url;
        return;
    }

    var site = null;
    for (var i = 0, len = config.sites.length; i < len; i++)
    {
        if (document.location.href.includes(config.sites[i].site))
        {
            site = config.sites[i];
            break;
        }
    }

    if (site === null)
        return;

    setTimeout(doLogin.bind(null, site), delay);

})();

function doLogin(site)
{
    var form = document.forms[site.form];
    if (!form)
        form = document.forms[0];

    var username = form[site.username_field];
    var password = form[site.password_field];

    if (!form || !username || !password)
    {
        attempts++;
        if (attempts > maxAttempts)
            return;

        setTimeout(doLogin.bind(null, site), delay);
    }

    username.value = site.username;
    password.value = site.password;

    var login = form[site.submit_button];

    if (site.redirect && site.redirect.length > 0)
        GM_setValue("redirect", site.redirect);

    if (login)
        login.click();
    else
        form.submit();
}

Due to the nature of the kiosk and Chromium, I would like to have this path relative and not absolute since being absolute would mean I have to hard code a path and hard coding anything is bad.


Solution

  • Doing some testing with scripts and Process Monitor, I don't believe there's a way to do an actual relative path, but if I specify file:///filename.js or even try to make that relative by using something like file:///../filename.js, Chromium will attempt to read the file from the directory that contains chrome.exe.

    For my purposes, the path to the chrome.exe file is known and controlled by me, I can place my "relative" path scripts in that directory and reference them as file:///filename.js

    Again, just to be clear in case someone else finds this useful. If I have my chrome.exe file in c:\kiosk\chrome\chrome.exe and I use @require file:///filename.js then chrome will attempt to load:

    c:\kiosk\chrome\filename.js

    This will also work for any relative path inside the chrome directory, i.e. file:///scripts/filename.js will resolve to c:\kiosk\chrome\scripts\filename.js