Launch Native Color Picker from Context Menu Without Triggering Popup Blocker


(Matthew G. Saroff) #1

I’m working on an extension in which one can use the context menu to apply formatting to a text box.

One of the formats I want to apply is color, and I would prefer to just launch Firefox’s native color picker, but it gets caught by the popup blocker, as it should, because this is a security hole otherwise.

I am assuming that there is some sort of way of invoking the color picker programmatically that won’t create a security issue, but I’ve seen nothing out there.

Code below:

In the background script, when the menu is called, the argument is passed to the content script:

browser.menus.onClicked.addListener((info, tab, defaultMenu) => {
if (info.menuItemId.substring(0, 6) == "bbcwbx") {
    console.log(info.menuItemId);
    for (i = 0; i < defMenu.length; i++) {
        if (info.menuItemId == defMenu[i].menuId) {
            var clickArg = defMenu[i].menuArg;
            browser.tabs.sendMessage(tab.id, clickArg); // send argument to content script for execution
        }
    }
}

});

The content script listens for it, and passes the argument to another function to evaluate the argument:

var clickedElement = null;
    document.addEventListener("mousedown", function(event) {
    //right click
    if (event.button == 2) {
        clickedElement = event.target;
    }
}, true);

browser.runtime.onMessage.addListener(function(commandString, sendResponse) {
    CommandParse(commandString);
});

The command parser is a series of conditional statements, with the bit about color being this:

   async function CommandParse(argString) {
   ………
        if (argString.includes("fontcol")) { // Invoke font color wheel
            argString = getColor(argString);
        }



        clickedElement.value = firsttext + argString + lasttext;

    }

This launches the popup: (simplified from the version which will use a promise for brevity)

function getColor(mkColor) {
    var input = document.createElement("input");  //create element
    input.setAttribute('type', 'color'); //is a color input button
    input.setAttribute('id','zzzcolor'); //it's ID is zzzcolor
    document.body.appendChild(input);  // append to body
    document.getElementById("zzzcolor").click(); // click on element
}

(Matthew G. Saroff) #2

I should note that I am temporarily using sub-menus as a work around, but it’s a less than optimal UI choice:


(Niklas Gollenstede) #3

Well, as I already said, I don’t think this is desired behavior by Mozilla.

Maybe you can invoke getColor in the background page, but I don’t think so.

Firefox requires a user interaction here (and the context menu click + messaging currently doesn’t count), so you have to make the user click or press a key on the page. You could e.g. add a button that says “click me to pick the color”, but that’s not really a nice solution.


(Matthew G. Saroff) #4

I’m wondering, if as alternative, I could at least format the submenu solution so that it was in 2 or 3 columns.