Firefox extension for opening a file with custom extension

Hello,

Windows 10
Firefox 128

The extension I am developing a custom image file format (xpx) and would like to open it in Firefox. Here is the initial code:

manifest.json

    {
      "manifest_version": 2,
      "name": "XPX Image File Opener",
      "version": "1.0",
      "description": "Open xpx, a zlib-compressed binary image file.",
      "background": {
        "scripts": ["background.js"]
      },
      "permissions": [
        "tabs",
        "activeTab",
        "webNavigation"
      ],
      "content_scripts": [
        {
          "matches": ["<all_urls>"],
          "js": ["xpx.js"],
          "css": ["style.css"]
        }
      ],
      "web_accessible_resources": [
        "pako.min.js"
      ],
      "browser_action": {
        "default_icon": {
          "48": "icon.png"
        },
        "default_title": "XPX Image File Opener"
      }
    }

background.js

browser.browserAction.onClicked.addListener((tab) => {
  browser.tabs.executeScript(tab.id, {
    file: 'xpx.js'
  });
});

xpx.js

console.log("Hello");

// Handle dropped files
document.addEventListener('drop', handleDrop, false);

function handleDrop(e) {
  const dt = e.dataTransfer;
  const files = dt.files;

  if (files.length > 0) {
    const file = files[0];
    const fileExtension = file.name.split('.').pop().toLowerCase();
    if (fileExtension === 'xpx') {
      console.log(fileExtension);
      //handleCustomFile(file);
    }
  }
}

Instead of executing the extensions files, it shows file ā€œOpenā€ & ā€œSave Asā€ dialog window. How do I resolve the problem?

Cheers

I think you need to call:

e.preventDefault();

(for example on the top of your handleDrop function)
That will prevent the default action, which is the ā€œSave asā€ dialog.

More info:

Hello @juraj.masiar
Here is new code as per the link you have suggested:
manifest.json

{
  "manifest_version": 2,
  "name": "Drop Interceptor",
  "version": "1.0",
  "description": "Intercepts file drops to prevent default browser behavior.",
  "permissions": ["<all_urls>"],
  "background": {
    "scripts": ["background.js"]
   },
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["content.js"]
    }
  ]
}

content.js

// Prevent default drag behaviors
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
  document.addEventListener(eventName, preventDefaults, false)
});

function preventDefaults(e) {
  e.preventDefault();
  e.stopPropagation();
}

// Handle dropped files
document.addEventListener('drop', handleDrop, false);

function handleDrop(e) {
  const dt = e.dataTransfer;
  const files = dt.files;
  if (files.length > 0) {
    const file = files[0];
    const fileExtension = file.name.split('.').pop().toLowerCase();
    if (fileExtension === 'xpx') {
      console.log(fileExtension);
    }
  }
}

background.js

browser.webNavigation.onCompleted.addListener(function(details) {
    console.log(details.url);
});

Still it shows ā€œOpenā€ & ā€œSave Asā€ dialog instead of calling the extension scripts.

Works for me.
Firefox 128.0 in Linux Mint 21.3

If you add a console.log() message to content.js, it lets you see if FF actually injects the content script into a tab.
E.g. when you create a new tab with Ctrl-T, FF doesnā€™t inject any content scripts until you navigate the tab to a URL.

edit:

  • The new manifest.json doesnā€™t have the ā€œwebNavigationā€ permissions, so browser.webNavigation.onCompleted.addListener in background.js causes an error.
  • You donā€™t need "permissions": ["<all_urls>"] , because in MV2, "matches": ["<all_urls>"] implicitly grants the ā€œ<all_urls>ā€ host permission.

edit 2:
Did you drag the .xpx file into an existing tab?
Or did you drag it into the tab bar?

@hans_squared
I open a new tab in the Firefox and drop the xpx file from file explorer. I have removed ā€˜background.jsā€™, removed ā€˜permissionsā€™ from ā€˜manifest.jsonā€™. Created a zip file containing ā€œmanifest.jsonā€ and ā€œcontent.jsā€ and load the zip file as extension. No errors or warnings but when I drop a xpx file, still it opens the dialog window.

Add some console logs to make sure the content script is really there and running.
For example in the dragstart and dragover handlers.

@juraj.masiar

Here is the new ā€œcontent.jsā€ and none of the console messages are getting printed.

console.log("Hello World");

// Prevent default drag behaviors
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
    console.log("Prevent defaults");
    document.addEventListener(eventName, preventDefaults, false)
});

function preventDefaults(e) {
  e.preventDefault();
  e.stopPropagation();
}

['dragenter', 'dragover'].forEach(eventName => {
  console.log("drag enter over");
});

['dragleave', 'drop'].forEach(eventName => {
  console.log("drag leave drop");
});

// Handle dropped files
document.addEventListener('drop', handleDrop, false);

function handleDrop(e) {
  const dt = e.dataTransfer;
  const files = dt.files;

  if (files.length > 0) {
    const file = files[0];
    const fileExtension = file.name.split('.').pop().toLowerCase();
    if (fileExtension === 'xpx') {
      console.log(fileExtension);
    }
  }
}

Lol :smiley:, are you using ChatGPT to generate this code based on our replies?
Or are you a chatbot? :smiley:

1 Like

See ā€œCreating a Custom Image File Dropping Firefox Extension on Windows 10ā€ on a website called ā€œdevcodef1ā€ (link removed).
Which is obivously AI-generated, because it uses the non-existent browser.tabs.onDrop listener.

I donā€™t know if OP generated the DevCodeF1 page, or if he found it and is now trying to follow the garbage ā€œtutorialā€.

OP asked the same question on Stackoverflow @ A Firefox extension to open custom image file by dropping on it

# I Have No Idea What Iā€™m Doing

1 Like

I myself is asked this question on stackoverflow yesterday but some one down voted it because of not enough research have done it before posting it. Thatā€™s why I have posted this question here.

Here is one more thing to laugh. I have asked this question on Microsoftā€™s Copilot because right now itā€™s freely available and than it just pasted back my post from stackoverflow as an answer. Than this happened:

copilot

Still the extension is not working. :smiley:

Ok,

Finally itā€™s working & Iā€™ll post the code soon. The reason is that I was dropping the file on an empty or newly opened tab. When I drop the file on a tab where a url is opened, the extension is working and I believe this property in the ā€œmanifest.jsonā€ is responsible for it.

"matches": ["<all_urls>"],

I need a way that can handle no url also. How do I do it?