This Banner is For Sale !!
Get your ad here for a week in 20$ only and get upto 15k traffic Daily!!!

My first Firefox extension – DEV Community


A few weeks in the past, I spent the weekend creating one other CFP submission helper within the type of a Firefox extension. It was not a stroll within the park. To assist others who could also be involved in doing the identical (and my future self), this is my journey.



Context

I’ve written a number of posts about my conference submission workflow. To sum up:

  • The whole lot relies on a Trello board
  • I created an app that registered a webhook on the board
  • After I transfer a convention from one lane to a different, it begins or continues a workflow on the app aspect

I supply the board by web sites, primarily Papercall and Sessionize, and manually copying convention knowledge on playing cards. Two automation choices can be found:

  1. Automating convention sourcing
  2. Automating a card creation

I believed lengthy and arduous concerning the first half. If I automate it, it is going to create an extended record of Trello playing cards, which I am going to must filter anyway. I concluded that it is higher to filter them earlier than.

Nevertheless, I created the cardboard manually by copy-pasting related knowledge: identify, dates, due date, CFP hyperlink, and web site. It is exactly what a Firefox extension may also help one with.



Necessities and design

The person story is fairly simple:

AS A: Lazy developer
I WANT TO: Routinely add CFP knowledge on Trello whereas shopping an online web page on Papercall or Sessionize
SO AS: To spend my time doing extra enjoyable stuff than copy-paste

— My single person story

My solely requirement is that it must work with Firefox.

My first thought is a button to set off the creation, however I do not care a lot the place it’s: contained in the web page as an overlay or someplace on the browser. Within the first case, it must be a JavaScript injected client-side; on the opposite, a Firefox extension. I selected the second possibility as a result of I wanted to determine find out how to obtain the primary.

I additionally needed first to create my extension in Rust with WebAssembly. Spoiler: I did not.



A easy Firefox extension

I had no clue about writing a Firefox extension, as this was the primary time I did write one. My first step was to observe the tutorial. It explains the fundamentals of an extension construction. Then, I adopted the second tutorial. It explains find out how to create a pop-up menu for the extension however not find out how to work together with the net web page. At this level, I made a decision to be taught by doing, a way that works nicely for me.

A Firefox extension begins with a manifest. Here is the one from the primary tutorial, simplified:

{
  "manifest_version": 2,
  "identify": "Borderify",
  "model": "1.0",
  "content_scripts": [
    {
      "js": ["borderify.js"]
    }
  ]
}
Enter fullscreen mode

Exit fullscreen mode

doc.physique.fashion.border = '5px strong crimson';
Enter fullscreen mode

Exit fullscreen mode

I discovered the event suggestions loop good. Think about that you’ve adopted the tutorial and created all the required information above. You possibly can go to about:debugging#/runtime/this-firefox and click on on the “Load Short-term Add-on” button.

Load a temporary Firefox extension

Then, level to your manifest file. Firefox masses the extension: it is now lively.

A new temporary Firefox extension loaded

Within the above instance, the JavaScript from the tutorial provides a crimson border round each internet web page. It is ineffective, we are able to do higher, however it reveals the way it works. We will change the script to alter the colour, e.g., from crimson to inexperienced. To make Firefox reload any change, together with modifications to the manifest, click on on the “Reload” button on the short-term extension panel.



Interacting with the extension

As I discussed above, I need a button to set off the creation of the Trello Card. Firefox permits a number of interplay choices: direct set off or opening of a pop-up window. I needn’t enter any parameter, so the previous is sufficient in my case.

Firefox permits a number of locations so as to add buttons: the browser’s toolbar, a sidebar, or contained in the browser’s URL bar. I used the toolbar for no purpose than as a result of it was what the second tutorial demoed. In the end, it solely modifications a bit, and transferring from one to a different is simple.

Including the button takes place within the manifest:

"browser_action": {
  "default_area": "navbar",                            #1
  "default_icon": "icons/trello-tile.svg"              #2
}
Enter fullscreen mode

Exit fullscreen mode

  1. Set the button on the navigation bar. For extra particulars on the button location, please verify the documentation
  2. Configure the icon. One can use bitmaps in numerous codecs, however it’s a lot simpler to set an SVG

At this level, every thing was positive and dandy. Afterward, I misplaced many hours making an attempt to know the completely different sorts of scripts and the way they work together. I am going to make it a devoted part.



Scripts, scripts in all places

The default language for scripts in extensions is JavaScript. Nevertheless, relying on their location, they play completely different roles. Worse, they should “speak” with each other.

Let’s begin with the content-script I used within the above manifest.json. Content material scripts are certain to an online web page. As such, they will entry its DOM. They run when Firefox masses the web page. The script provides a crimson border across the internet web page’s physique within the tutorial.

Nevertheless, we want one other form of script: one to set off after we click on on the button. Such scripts ought to run together with the extension however can hearken to occasions. They’re often called background scripts.

Background scripts are the place to place code that should preserve long-term state, or carry out long-term operations, independently of the lifetime of any explicit internet pages or browser home windows.

Background scripts are loaded as quickly because the extension is loaded and keep loaded till the extension is disabled or uninstalled, except persistent is specified as false. You should use any of the WebExtension APIs within the script, so long as you’ve requested the required permissions.

background scripts

Let’s create such a script. It begins with the manifest – as typical:

"background": {
  "scripts": [ "background.js" ]
}
Enter fullscreen mode

Exit fullscreen mode

We will now create the script itself:

operate foo() {
    console.log('Hiya from background')
}

browser.browserAction.onClicked.addListener(foo)    //1
Enter fullscreen mode

Exit fullscreen mode

  1. Register the foo operate as an occasion listener to the button. When one clicks the extension button, it calls the foo operate



Debugging the extension

Let’s cease for a second to speak about debugging. I misplaced a number of hours as a result of I did not know what had occurred. After I began to develop JavaScript 20 years in the past, we “debugged” with alert(). It was not the most effective developer expertise you would hope for. Extra fashionable practices embrace logging and debugging. Spoiler: I did not handle to get debugging working, so I am going to deal with logging.

First issues first, content material scripts work within the context of the web page. Therefore, logging statements work within the common console. Background scripts do work in one other context. To observe their log statements, we have to have one other Firefox developer console. You possibly can open it on the extension panel by clicking the “Examine” button.

Developer Console for the background script extension



Communication throughout scripts

Now that we all know find out how to log, it is potential to go additional and describe communication throughout scripts. Here is an outline of the general stream:

Overview of the communication flow across scripts

Let’s change the code a bit in order that background.js sends a message:

operate sendMessage(tab) {
    browser.tabs
           .sendMessage(tab.id, 'message in from background')
           .then(response => {
               console.log(response)
           })
           .catch(error => {
               console.error(`Error: ${error}`)
           })
}

browser.browserAction.onClicked.addListener(sendMessage)
Enter fullscreen mode

Exit fullscreen mode

Now, we alter the code of content material.js:

browser.runtime.onMessage.addListener((message, sender) => {
    return Promise.resolve('message again from content material')
});
Enter fullscreen mode

Exit fullscreen mode



Getting the content material

To this point, we have now carried out a back-and-forth stream between the background and the content material scripts. The meat is to get content material from the web page within the content material script and cross it again to the background through a message. Keep in mind that solely the content material script can entry the web page! The code itself makes use of the Doc API, e.g., doc.querySelector(), doc.getElementsByClassName(), and many others. Specifics are unimportant.

The subsequent subject is that the construction of Sessionize and Papercall are completely different. Therefore, we want completely different scraping codes for every web site. We may develop a single script that checks the URL, however the extensions can maintain it for us. Let’s change the manifest:

"content_scripts" : [{
  "matches": [ "https://sessionize.com/*" ],            #1
  "js": [                                               #2
    "content/common.js",                                #4
    "content/sessionize.js"
  ]
},
{
  "matches": [ "https://www.papercall.io/*" ],          #1
  "js": [                                               #3
    "content/common.js",                                #4
    "content/papercall.js"
  ]
}]
Enter fullscreen mode

Exit fullscreen mode

  1. Match completely different websites
  2. Scripts for Sessionize
  3. Scripts for Papercall
  4. Code shared on each websites

At this level, we managed to get the required knowledge and ship it again to the background script. The final step is to name Trello with the information.



Dealing with authentication credentials

Utilizing Trello’s REST requires authentication credentials. I need to share the code on GitHub, so I can’t hard-code credentials: I want configuration.

We will configure a Firefox extension through a devoted choices web page. To take action, the manifest presents a devoted options_ui part the place we are able to present the trail to the HTML web page:

  "options_ui": {
    "web page": "settings/choices.html"
  }
Enter fullscreen mode

Exit fullscreen mode

The web page can instantly reference the scripts and stylesheet it wants. The script must:

  1. Retailer credentials within the browser storage on save
  2. Load credentials from the browser storage when the settings web page opens

It is fairly simple with the provided example.

My code is kind of related; it simply wants three fields as a substitute of 1:

operate saveOptions(e) {
    browser.storage.sync.set({                                               //1
        listId: doc.querySelector('#list-id').worth,
        key: doc.querySelector('#key').worth,
        token: doc.querySelector('#token').worth,
    })
}

operate restoreOptions() {
    browser.storage.sync.get()                                               //1
           .then(knowledge => , error => {
               console.error(`Error: ${error}`)
           })
}

doc.addEventListener('DOMContentLoaded', restoreOptions)                //2
doc.querySelector('kind').addEventListener('submit', saveOptions)       //3
Enter fullscreen mode

Exit fullscreen mode

  1. Makes use of the Firefox storage API
  2. Learn from the storage when the web page masses
  3. Save to the storage when the person submits the HTML kind

We additionally must ask the storage permission within the manifest:

  "permissions": [ "storage" ]
Enter fullscreen mode

Exit fullscreen mode

We will now retailer the Trello credentials (in addition to the required Trello record id) on the settings web page:

Firefox extension settings page

We will use the identical storage API within the Trello calling code to learn credentials.

At this level, I used to be pleased with my setup. I simply added one other round-trip from the background to the content material to show an alert with Trello’s card identify and URL.

Final result



Conclusion

It was the primary extension I wrote, and although the start was difficult, I achieved what I needed. Now, I can navigate to a Papercall and a Sessionize web page, click on the extension button, and get the convention on my Trello board. It took me a few days and was enjoyable; it was nicely value it. I proceed engaged on it to enhance it little by little.

The entire supply code for this publish will be discovered on GitHub:

To go additional:

Initially printed at A Java Geek on April 2nd, 2023

The Article was Inspired from tech community site.
Contact us if this is inspired from your article and we will give you credit for it for serving the community.

This Banner is For Sale !!
Get your ad here for a week in 20$ only and get upto 10k Tech related traffic daily !!!

Leave a Reply

Your email address will not be published. Required fields are marked *

Want to Contribute to us or want to have 15k+ Audience read your Article ? Or Just want to make a strong Backlink?