About the author
This month, I've learnt how to build a Firefox add-on, and learnt that if one desires to do so, there's practically no difference between a Firefox add-on and a Chrome add-on, so, it's theoretically possible to build an add-on that runs on both Firefox and Chrome.
Mozilla has some restrictions, for example, if you use a third-party library, you must use an unmodified copy of the library. But barring these restrictions, if your add-on is entirely self-contained, the add-on is approved pretty quickly. Also, if your add-on does not present a UI, the same add-on can run on both mobile and desktop browsers.
The guide to writing a Firefox add-on can be viewed here.
I'm going to limit this blog post to Firefox, and share about my experience in building an add-on.
An add-on consists of these files:
Here's an example of my manifest.json:
{ "manifest_version": 2, "name": "chuacw's Firefox add-on", "short_name": "chuacw's Firefox add-on", "version": "0.998.6", "description": "Automatically logout from somedomain", "browser_specific_settings": { "gecko": { "id": "{c12679fd-4f07-4f4c-b1c2-fbeb2627651f}" } }, "icons": { "16": "icons/icon16.png", "32": "icons/icon32.png", "128": "icons/icon128.png" }, "content_scripts": [ { "matches": [ "https://*.somedomain.com/*" ], "js": [ "loaded.min.js" ], "run_at": "document_idle" }, { "matches": [ "https://*.somedomain.com/*" ], "js": [ "startup.min.js" ], "run_at": "document_start" } ] }
For the above manifest, when I visit any domains that ends in somedomain.com, when the document starts loading, I want startup.min.js to run. And when the document is loaded completely, I want loaded.min.js to run.
Here's what loaded.js looks like, and it can be compressed, using tools such as uglifyjs, minify, etc, to minimize the Javascript.
(function () { console.log(`${new Date()} 0.998.6 shutdown loaded.`); var logoutClicked = false; function setupLogoutObserver() { console.log(`${new Date()} observer setup and monitoring.`); const avatar = document.querySelector('[alt="Avatar image"]'); if (avatar && !logoutClicked) { console.log(`${new Date()} avatar found!`); avatar.click(); const logoutLink = document.querySelector('[href="/logout"]'); if (logoutLink) { console.log(`${new Date()} Logging out.`) logoutLink.click(); logoutClicked = true; } } if (avatar && !logoutClicked) setTimeout(setupLogoutObserver, 50); } setupLogoutObserver(); })();
The location of the Javascript files are specified relative to the manifest.
So, what the above script does is look for an HTML element that contains the attribute alt, which has the value "Avatar image", once it matches that, it looks for an element with href which has the value "/logout" and click on it.
So after creating the above, what's needed to build the Firefox add-on is to build and sign the add-on.
In my case, after installing web-ext with npm install -g web-ext, I ran the following command:
web-ext build zips up the files, and creates a zip fileweb-ext sign then uploads the zip onto Mozilla's extensions site, and downloads the newly signed xpi (which is actually a renamed zip file that's signed), after some form of automated review, about 5-10 minutes after, back into the location where you ran the web-ext command.
The signing process fails pretty quickly if some files are missing, or values in the manifest are incorrect or missing.
If one so desires, one can open up the xpi and be able to view the Javascript source.
Continued discussion of undocumented Delphi 8 Property Access Specifiers, and other ways of adding and removing delegates / events handlers, including clearing the list of all the delegates / event handlers.