How to write your first Firefox add-on?

How to write your first Firefox add-on?

Due to U.S. trade controls law restrictions, your GitHub account has been restricted.

This is the message that’s been recently sent to Iranian developers from GitHub, stating their accounts has been restricted.

The political reasons and consequences of this action is not what I’m going to talk about (this is not the right place), Instead I’m gonna focus on what happened after this announcement to GitHub site: A horrendous yellow banner, screaming our misfortunes on top of every GitHub page:

github

So I thought this might be a good time to try writing my first add-on for Firefox. It seemed like a trivial task and I was curious how much it’s going to take my time. Simple tasks must be simple to do.

At first I tried to remove the banner in browser inspector. All I had to do was to set display property to none for the element and it was gone.

So, that’s what we want our add-on to do: To simply set a CSS property for an element.

Write the extension

MDN web docs has a page called Your first extension and I followed the steps it said:

At first I created a directory for my add-on.

Then I created manifest.json file. This file is the skeleton of your extension; What files does it include, a short description, extension version, icons and everything else.

content_scripts section is the most interesting part: You define in what domains, which scripts must be injected.

I wanted to modify appearance of GitHub, which means all I wanted to do was to add a CSS property. So I modified content_scripts in manifest.json to look like this:

"content_scripts": [
  {
    "matches": ["*://*.github.com/*"],
    "css": ["github-warn.css"],
  }

And in github-warn.css I wrote this:

div.position-relative.js-header-wrapper > div.js-notice.flash-warn {
    display: none
}

Run and debug

Now let’s test the add-on. First we must load it into the browser. To do so go to about:debugging in FireFox and click on “Load Temporary add-on”. By selecting a file in your add-on directory it will be loaded in FireFox.

And now when we go to GitHub we no longer see the banner.

But there’s a problem: It seems it take a little bit of time before we see our CSS effects in browser. When you open the site you can see the banner when page is being loaded and after a few seconds it disappears.

To solve this issue we have to change when the CSS get’s injected. It can be altered by run_at property in content_scripts: "run_at" : "document_start"

It worth to take a glance of content_scripts parameters in here.

Publish

There are two options for add-on publishing:

  • Self publish: You will be given the signed .xpi file that you can distribute yourself.

  • Publishing on FireFox Add-on’s page (AMO)

In either cases first you have to login to Mozilla Developer Hub and upload your zipped add-on directory. To do so, go to your add-on directory and run:

zip -r github-warn.zip . 

Tip: If you’re on macOS, to avoid warnings make sure .DS_Store and __MACOSX are not included in zip file. You can delete them by executing this command:

zip -d github-warn.zip __MACOSX/* .DS_Store

After you’ve uploaded the zip file you can choose between self-publishing and publishing on AMO. In case you choose the latter, it might take about a day or two before your extensions be approved and becomes publicly available. Self

You can access the add-on code explained in this post on GitHub.

Essential skills that we didn’t learn in university

It’s been about a year that I’m monkey coding in a some-how large scale company and getting my head around real coding. In a year that I spend in industry I found some of most important tools and concepts that I use in my every day job, are the the ones that I didn’t heard a word about them in school. Here’s the three most important God-knows-why-they-do-not-teach-us-in-university things that are at top of my head :tdd2

First and foremost is TDD : I can’t even remember how did I wrote programs without unit tests, I literally can’t. I mean did we just open up an editor and start writing code ? How did we change the code ? How were we confident about it working as expected ? All we learned was waterfall design and UML. Heaven forbid !

Second one is Version control : It’s no longer about code bases of two or three hundreds lines of throw-away code that you would normally do for your final projects in university, We’re now talking about thousands lines of code. Version control is the only way that you cope with immense amount of complexity in large code bases and it also helps me to take baby steps toward a solution.

vcs

refactoringAnd finally the third one, Refactoring : In university what matters is you can provide expected behavior, before project deadline. After that your code gonna be worthless. No one else will read it, you’re not expected to add more features and who gives a damn about bugs ? ( They just don’t have to pop up during presentation )
For me refactoring is synonym to responsibility. Your code is your responsibility and you have to take good care of it.

Editing Code whilst preserving its formatting

Earlier in one of my posts, I explained how can you reformat your code using NRefactory library. But, as matter of fact what you really want in your day to day task is not reformatting code, au contraire, you want its formatting to be preserved. You don’t want to commit dozens of files to your repository merely because their formatting’s changed !

Now this question arises that whether is this quest possible in NRefactory or not ? Well of course it is, and it’s really easy. ( Once you know what you have to do, who you have to call and … ) BTW, NRefactory is an essential part of SharpDevelop IDE and we don’t want our idea to reformat our code every time we use intellisens.

NRefactory has a class that’s dedicated to do such and it’s called DocumentScript.

Document scripts works by manipulating IDocument objects, which are specialization of string builder class. This class gives you this opportunity to change your document based on text location that were already stored in syntax tree. It also keeps track of latest modification and map them to current document, so you don’t have to worry about whether multiple changes on the same document will be applied correctly or not.

IDocument document = new StringBuilderDocument("Your code source");
CSharpFormattingOptions policy = FormattingOptionsFactory.CreateAllman();
var options = new TextEditorOptions();

var script = new DocumentScript(document, policy, options);

Now you can use methods like Replace, Remove, scriptInsertAfter and etc. on you AST. It works with both AST nodes as well as offsets.

Beside that, there are some predefined methods on

script.ChangeModifier(declaration, Modifiers.Public);

Binary Operator Expressions

Suppose in a hypothetical scenario you want to reverse all binary operation in your file, and also you want them to be fully parenthesized. What would you do ?
One solution is using recursion which might be a little messy an unclear. Another solution to this problem can be achieved by taking advantage of binary operator expressions in NRefactory.
Fortunately with NRefactory this operation is rather a trivial task. A little tricky, but still simple.
You can use this feature to process any kind of binary operation and interpret it the way you like. ( like generating code )

First, let’s create a test fixture for it ( Hooray ! Now you know what TDD is : )

[Test]
public void BinaryVisitorTest()
{
	string input = " a > b || ( x > y && y > z )";
	var parser = new CSharpParser();
	Expression expression = parser.ParseExpression(input);

	var visitor = new BinaryOpVisitor();
	expression.AcceptVisitor(visitor);
}

Since we’re interested in visiting an expression we don’t bother by parsing a whole C# file, we give the parser our expression as text, and it gives use the expression as AST.
In next step, we create a visitor class and visit binary and identifier expressions :

public class BinaryOpVisitor : DepthFirstAstVisitor
{
	public override void VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression)
	{
		Console.Write("(");
		binaryOperatorExpression.Right.AcceptVisitor(this);
		Console.Write(binaryOperatorExpression.OperatorToken);
		binaryOperatorExpression.Left.AcceptVisitor(this);
		Console.Write(")");
	}

	public override void VisitIdentifierExpression(IdentifierExpression identifierExpression)
	{
		Console.Write(identifierExpression.Identifier);
		base.VisitIdentifierExpression(identifierExpression);
	}
}

Be careful as opposed to what we do regularly in node visiting ( or actually what depth first visiting is all about ), we didn’t call base visitor in binary operator expression visitor.

Now, for this special case, the output will be :

(((z>y)&&(y>x))||(b>a))

Easy peasy !

For readers with data structure background I’d like to mention that what we did in here was actually an in-order visit of the nodes in AST. You can simply turn it into post/pre-order by putting base class call before/after your code in the visitor.

PrettyPrint C# codes via NRefactory

Well, yet another code example via NRefactory. This time we intend to take advantage of reformatting capabilities in NRefactory library.
What does it mean ?  Well, when you become engage in Code generating activities, you usually don’t want to be involved in details of code formatting, indentation and these kind of stuff. All you wanna do, is to concatenate some codes, one behind another and create you desired code. After you’re done with your code, you may have a program in one line, with no indentation. This is where NRefactory steps in.
It can take your code, and by considering tons of available options, automatically reformat your code. easy peasy !

I have created a rudimentary example of this operation that you can download from here. It’s quite simple and straightforward.

PS : I’ve uploaded binary files in here. In case you already download the previous sample, you don’t need to download binary files again. Now all you have to do is to reference to these binary files to be able to build the project.

Oops ! I made an honest mistake and used Formatters. I’ve applied changes and updated the code.
Formatters are appropriate tools when you want to apply modifications in IDE ( like preserving correct indentation after copy-paste or when IDE fills some fields for you ).
In our case, proper tool would be OutputVisitors. We create parse tree of out code, then visit it by CSharpOutputVisitor and … Boom !