<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Mozilla // William Durand</title>
    <link href="https://williamdurand.fr/mozilla.xml" rel="self"/>
    <link href="https://williamdurand.fr"/>
    <updated>2026-05-01T13:00:04+00:00</updated>
    <id>https://williamdurand.fr/</id>
    <author>
        <name>William Durand</name>
        <email>will@drnd.me</email>
    </author>

    
    <entry>
        <title>Moziversary #8</title>
        <link href="https://williamdurand.fr/2026/05/01/moziversary-8/"/>
        <updated>2026-05-01T00:00:00+00:00</updated>
        <id>https://williamdurand.fr/2026/05/01/moziversary-8</id>
        <content type="html">&lt;p&gt;&lt;em&gt;Today is my eighth Moziversary 🎂 I joined Mozilla as a full-time employee on
May 1st, 2018. I previously blogged in &lt;del&gt;2019&lt;/del&gt;, &lt;a href=&quot;/2020/05/01/moziversary-2/&quot;&gt;2020&lt;/a&gt;, &lt;a href=&quot;/2021/05/01/moziversary-3/&quot;&gt;2021&lt;/a&gt;, &lt;a href=&quot;/2022/05/01/moziversary-4/&quot;&gt;2022&lt;/a&gt;,
&lt;a href=&quot;/2023/05/01/moziversary-5/&quot;&gt;2023&lt;/a&gt;, &lt;a href=&quot;/2024/05/01/moziversary-6/&quot;&gt;2024&lt;/a&gt;, and &lt;a href=&quot;/2025/05/05/moziversary-7/&quot;&gt;2025&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You might have come across this &lt;a href=&quot;https://blog.mozilla.org/addons/tag/data-consent/&quot;&gt;built-in data consent&lt;/a&gt; thing for extensions
in Firefox. I spent a good chunk of last year working on this project, from
developing a technical proposal to implementing the feature in &lt;a href=&quot;https://firefox-source-docs.mozilla.org/overview/gecko.html&quot;&gt;Gecko&lt;/a&gt;,
Firefox for desktop and Firefox for Android.&lt;/p&gt;

&lt;p&gt;Talking about Android, I &lt;a href=&quot;https://groups.google.com/a/mozilla.org/g/governance/c/OPdtww0H07I/m/Hc5WnwwPFgAJ&quot;&gt;became the module owner&lt;/a&gt; for
&lt;a href=&quot;https://firefox-source-docs.mozilla.org/mots/index.html#fenix-add-ons&quot;&gt;&lt;em&gt;Fenix::Add-ons&lt;/em&gt;&lt;/a&gt;, a module for all the code related to
add-ons in Firefox for Android (which we call “Fenix” internally). Between the
creation of this new module, and an ever-solidifying collaboration between the
Add-ons and Android teams, the support for extensions in Firefox for Android has
a bright future! Having started my Android journey in 2023, this feels like a
noteworthy achievement.&lt;/p&gt;

&lt;p&gt;Near the end of last year, I moved back to being a full-time &lt;a href=&quot;https://addons.mozilla.org/&quot;&gt;AMO&lt;/a&gt; engineer to
support a team that was down to two engineers. I redesigned the detail page, and
started some refactoring on our security scanners, which I had originally
created back in 2019 😬&lt;/p&gt;

&lt;p&gt;In other news, I joined the AI/LLM/vibe-coding crowd thanks to my colleague
&lt;a href=&quot;https://paul.cx/&quot;&gt;Paul&lt;/a&gt;, and it took me about a month to get brain-fried… &lt;a href=&quot;https://siddhantkhare.com/writing/ai-fatigue-is-real&quot;&gt;AI
fatigue is real&lt;/a&gt;, indeed. That said, Claude code has been somewhat useful to
me, and I don’t &lt;em&gt;hate&lt;/em&gt; it, but I also don’t &lt;em&gt;love&lt;/em&gt; it.&lt;/p&gt;

&lt;p&gt;Thank you to everyone in the Add-ons team as well as to all the folks I had the
pleasure to work with so far. Cheers!&lt;/p&gt;

</content>
    </entry>
    
    <entry>
        <title>Moziversary #7</title>
        <link href="https://williamdurand.fr/2025/05/05/moziversary-7/"/>
        <updated>2025-05-05T00:00:00+00:00</updated>
        <id>https://williamdurand.fr/2025/05/05/moziversary-7</id>
        <content type="html">&lt;p&gt;&lt;em&gt;A few days ago, this was my seventh Moziversary 🎂 I joined Mozilla as a
full-time employee on May 1st, 2018. I previously blogged in &lt;del&gt;2019&lt;/del&gt;, &lt;a href=&quot;/2020/05/01/moziversary-2/&quot;&gt;2020&lt;/a&gt;,
&lt;a href=&quot;/2021/05/01/moziversary-3/&quot;&gt;2021&lt;/a&gt;, &lt;a href=&quot;/2022/05/01/moziversary-4/&quot;&gt;2022&lt;/a&gt;, &lt;a href=&quot;/2023/05/01/moziversary-5/&quot;&gt;2023&lt;/a&gt;, and &lt;a href=&quot;/2024/05/01/moziversary-6/&quot;&gt;2024&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;While I may not have the energy to reflect extensively on the past year right
now, I can say with confidence that the last 12 months have been incredibly
productive, and things are generally going well for me.&lt;/p&gt;

&lt;p&gt;Seven years later, I am still part of the Add-ons team. As a &lt;a href=&quot;/2025/03/01/senior-staff/&quot;&gt;senior staff&lt;/a&gt;
engineer, I am no longer working full time on &lt;a href=&quot;/2022/01/25/new-team-mozilla/&quot;&gt;the WebExtensions
team&lt;/a&gt;.  Instead, I am spending my time on anything related to
Add-ons within Mozilla (be it Firefox, AMO, etc.).&lt;/p&gt;

&lt;p&gt;My team went through a lot of changes over the last few years&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, with some
years more memorable than others. About a year ago, things started to head into
the right direction, and I am rather hopeful. It’s going to take some time, but
the team is really set up for success again!&lt;/p&gt;

&lt;p&gt;Shout-out to all my amazing colleagues at Mozilla, I wouldn’t be where I am
today without y’all ❤️&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Let’s talk briefly about the elephant. Mozilla has changed a lot too but I
don’t have much control over that so I tend to not think too much about it 🤷 &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
    </entry>
    
    <entry>
        <title>Firefox AI &amp; WebExtensions</title>
        <link href="https://williamdurand.fr/2025/03/24/firefox-ai-and-webextensions/"/>
        <updated>2025-03-24T00:00:00+00:00</updated>
        <id>https://williamdurand.fr/2025/03/24/firefox-ai-and-webextensions</id>
        <content type="html">&lt;p&gt;&lt;em&gt;I gave an introduction to the Firefox AI runtime and WebExtensions at a &lt;a href=&quot;https://www.clermontech.org/&quot;&gt;French
local conference&lt;/a&gt; this month. This article is a loose transcript of
what I said.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let’s talk about Firefox, AI, and WebExtensions.&lt;/p&gt;

&lt;h2 id=&quot;browser-extensions&quot;&gt;Browser extensions&lt;/h2&gt;

&lt;p&gt;Browser extensions are tiny applications that modify and/or add features to a
web browser. Nowadays, these small programs can be written in such a way that
they should be compatible with different browsers.&lt;/p&gt;

&lt;p&gt;That’s because there exists a cross-browser system called “WebExtensions”, which
– among other things – provides a set of common APIs that browser extensions can
use. In addition to that, browsers can also expose their own APIs, and we’ll see
that in a moment.&lt;/p&gt;

&lt;p&gt;You’ll find a lot more information on this &lt;a href=&quot;https://developer.mozilla.org/docs/Mozilla/Add-ons/WebExtensions&quot;&gt;MDN page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; During my talk, I used the &lt;a href=&quot;https://developer.mozilla.org/docs/Mozilla/Add-ons/WebExtensions/Your_first_WebExtension&quot;&gt;Borderify extension&lt;/a&gt;
to walk the audience through an example of a web extension. I then concluded
that it’s super easy to get started but also very powerful. Extensions like
uBlock Origin, Dark Reader, 1Password, etc. are rather powerful and
sophisticated features.&lt;/p&gt;

&lt;h2 id=&quot;firefox-ai-runtime&quot;&gt;Firefox AI runtime&lt;/h2&gt;

&lt;p&gt;Firefox has a new &lt;a href=&quot;https://firefox-source-docs.mozilla.org/toolkit/components/ml/&quot;&gt;component&lt;/a&gt; based on &lt;a href=&quot;https://huggingface.co/docs/transformers.js/&quot;&gt;Transformers.js&lt;/a&gt; and the
&lt;a href=&quot;https://onnxruntime.ai/&quot;&gt;ONNX runtime&lt;/a&gt; to perform local inference directly in the browser.  In short,
this runtime allows to use a model from &lt;a href=&quot;https://huggingface.co/&quot;&gt;Hugging Face&lt;/a&gt; (like GitHub but for
Machine Learning models) directly in Firefox&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, without the need to send data
to any servers. Every operation is performed on the user’s machine once the
model files have been downloaded by Firefox.&lt;/p&gt;

&lt;p&gt;While every website could technically load Transformers.js and a model, this
isn’t very efficient. Say two websites use the same model, you end up with two
copies of the model files. And those aren’t exactly small.&lt;/p&gt;

&lt;p&gt;This Firefox component – also known as the Firefox (AI) runtime – addresses this
problem by ensuring that models are shared. In addition, this runtime takes care
of managing resources, and model inference is isolated from the rest of Firefox
in an &lt;em&gt;inference&lt;/em&gt; process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; During my talk, I mentioned that – while we call this “AI” now –
Mozilla has been doing Machine Learning (ML) for a very long time&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. For
instance, Firefox Translations isn’t exactly &lt;a href=&quot;https://github.com/mozilla/firefox-translations&quot;&gt;new&lt;/a&gt;,
and whether you like it or not, this is clearly an application of Generative
AI&lt;sup id=&quot;fnref:3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;. Same thing, still.&lt;/p&gt;

&lt;p&gt;Anyway, let’s see how we can interact with this runtime. We’re going to generate
text that describes an image in the rest of this section.&lt;/p&gt;

&lt;p&gt;The “hacker’s approach” is probably to open a &lt;a href=&quot;https://firefox-source-docs.mozilla.org/devtools-user/browser_console/index.html&quot;&gt;Browser console&lt;/a&gt; in
&lt;a href=&quot;https://nightly.mozilla.org&quot;&gt;Nightly&lt;/a&gt;, and run some privileged JavaScript code:&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;createEngine&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ChromeUtils&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;importESModule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;chrome://global/content/ml/EngineProcess.sys.mjs&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;taskName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;image-to-text&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;modelHub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;mozilla&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;engine&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;createEngine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;engine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;https://williamdurand.fr/images/posts/2014/12/brussels.jpg&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// res =&amp;gt; { generated_text: &quot;A large poster of a man on a wall.&quot; }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As mentioned previously, the Firefox runtime is based on Transformers.js, which
is why the code looks familiar when you know Transformers already. For instance,
instead of passing an actual model here, we pass a &lt;em&gt;task name&lt;/em&gt;. That’s an
abstraction coming from Transformers. Don’t worry, we can also pass a model name
and a lot of other (pipeline) options!&lt;/p&gt;

&lt;p&gt;For those looking for a more graphical approach to play with this AI runtime,
Firefox Nightly provides an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;about:inference&lt;/code&gt; page that looks like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/2025/03/aboutinference.webp&quot; alt=&quot;Screenshot of the about:inference page&quot; /&gt;
&lt;!-- add some space between the image and the next paragraph --&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;That’s cool but… Why? Well, it turns out this example isn’t a random example.
This code snippet is an overly simplified version of a feature in Firefox’s PDF
reader (&lt;a href=&quot;https://github.com/mozilla/pdf.js&quot;&gt;PDF.js&lt;/a&gt; ❤️): alt text generation&lt;sup id=&quot;fnref:4&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p class=&quot;with-caption&quot;&gt;&lt;img src=&quot;/images/posts/2025/03/pdfjs.webp&quot; alt=&quot;&quot; /&gt;
&lt;em&gt;Screenshot of an “Edit alt text” dialog in PDF.js (inside Firefox): the image
description has been automatically generated.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: During my talk, someone asked a question about the use of GPU, for
which I didn’t have the answer. I do have it now, though. The Firefox AI runtime
runs on CPU by default, but it is possible to run on GPU via &lt;a href=&quot;https://developer.mozilla.org/docs/Web/API/WebGPU_API&quot;&gt;WebGPU&lt;/a&gt;. It’s
worth mentioning that this runtime doesn’t feel as fast as a more “native”
solution (like &lt;a href=&quot;https://ollama.com/&quot;&gt;Ollama&lt;/a&gt;) yet but the team at Mozilla is working on it!&lt;/p&gt;

&lt;p&gt;Anyhow, let’s move to the final part of this &lt;del&gt;talk&lt;/del&gt; article.&lt;/p&gt;

&lt;h2 id=&quot;webextensions-ml-api&quot;&gt;WebExtensions ML API&lt;/h2&gt;

&lt;p&gt;The best of both worlds, yay!&lt;/p&gt;

&lt;p&gt;We shipped an experimental WebExtensions API to allow extensions to do local
inference (&lt;a href=&quot;https://firefox-source-docs.mozilla.org/toolkit/components/ml/extensions.html&quot;&gt;docs&lt;/a&gt;), leveraging the Firefox AI runtime under the hood.
Expect things to evolve, it’s bleeding edge technology!&lt;/p&gt;

&lt;p&gt;At the time of writing this, we can rewrite the example from the previous
section into “extension code” as follows:&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;taskName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;image-to-text&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;modelHub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;mozilla&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;browser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;trial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ml&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createEngine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;browser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;trial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ml&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;runEngine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;https://williamdurand.fr/images/posts/2014/12/brussels.jpg&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// res =&amp;gt; { generated_text: &quot;A large poster of a man on a wall.&quot; }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This looks similar, right? That’s on purpose. For extension developers, the
WebExtensions API namespace is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;trial.ml&lt;/code&gt;, and the associated permission is
named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;trialML&lt;/code&gt;, which extensions must &lt;a href=&quot;https://developer.mozilla.org/docs/Mozilla/Add-ons/WebExtensions/API/permissions/request&quot;&gt;request at runtime&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What can we do with that, though?  Well, what if we were to provide the
alt-text-generation feature not just in PDFs but for any image on any website?&lt;/p&gt;

&lt;p&gt;That’s what we have done in a demo extension (&lt;a href=&quot;https://searchfox.org/mozilla-central/source/toolkit/components/ml/docs/extensions-api-example&quot;&gt;code&lt;/a&gt;,
&lt;a href=&quot;https://firefox-source-docs.mozilla.org/toolkit/components/ml/extensions-api-example/README.html&quot;&gt;docs&lt;/a&gt;), which we can see in action in the screencast
below:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;At 00:00, the demo extension has been loaded in Firefox Nightly.&lt;/li&gt;
  &lt;li&gt;At 00:02, we open the context menu on an image in the current web page, and we
click on “Generate Alt Text”. This menu entry has been added by the extension
using the &lt;a href=&quot;https://developer.mozilla.org/docs/Mozilla/Add-ons/WebExtensions/API/menus&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;menus&lt;/code&gt; API&lt;/a&gt; by the way.&lt;/li&gt;
  &lt;li&gt;At 00:05, we can see that Firefox is downloading the model files (the UI is
provided by the extension, which receives events from Firefox). This means the
model was not used before so the Firefox AI runtime has to download the model
files first. This step is only necessary when Firefox doesn’t already have the
model used by the extension.&lt;/li&gt;
  &lt;li&gt;At 00:09, the model inference starts.&lt;/li&gt;
  &lt;li&gt;At 00:12, the result of the inference, which is the description of the image
in this case, is returned to the extension, and the extension shows it to
the user.&lt;/li&gt;
&lt;/ul&gt;

&lt;video controls=&quot;&quot;&gt;
  &lt;source src=&quot;/images/posts/2025/03/demo_webext_trial_ml_desktop.webm&quot; type=&quot;video/webm&quot; /&gt;
  &lt;p&gt;Your browser doesn&apos;t support HTML video.&lt;/p&gt;
&lt;/video&gt;

&lt;p&gt;Previously, I mentioned that browser extensions can be cross-browser. They can
also run on different platforms as well. In &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1954362&quot;&gt;Bug 1954362&lt;/a&gt;, I updated this demo
extension so that it can run on &lt;a href=&quot;https://blog.mozilla.org/addons/2024/05/02/1000-firefox-for-android-extensions-now-available/&quot;&gt;Firefox for Android&lt;/a&gt; 😎&lt;/p&gt;

&lt;p&gt;The screencast below shows the same extension running in Firefox for Android:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;At 00:00, we can see a dialog because the extension has &lt;em&gt;just&lt;/em&gt; been installed.&lt;/li&gt;
  &lt;li&gt;At 00:01, the extension opened a page in a new tab to request permission to
interact with the Firefox AI runtime. This is pretty standard for browser
extensions to request permissions ahead of time.&lt;/li&gt;
  &lt;li&gt;At 00:06, we load a web page with an image.&lt;/li&gt;
  &lt;li&gt;At 00:10, we use long-press on the image to trigger the extension because
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;menus&lt;/code&gt; API is not supported on Android yet (&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1595822&quot;&gt;Bug 1595822&lt;/a&gt;).&lt;/li&gt;
  &lt;li&gt;At 00:12, similar to the previous screencast, Firefox starts by downloading
the model files. This takes a lot of time because my emulator isn’t exactly
fast. Do remember that this is only needed once, though.&lt;/li&gt;
  &lt;li&gt;At 01:09, the model inference starts.&lt;/li&gt;
  &lt;li&gt;At 01:12, the result of the inference, which is – again – the description of
the image, is returned to the extension, and the extension shows it to the
user.&lt;/li&gt;
&lt;/ul&gt;

&lt;video controls=&quot;&quot; height=&quot;500&quot;&gt;
  &lt;source src=&quot;/images/posts/2025/03/demo_webext_trial_ml_android.webm&quot; type=&quot;video/webm&quot; /&gt;
  &lt;p&gt;Your browser doesn&apos;t support HTML video.&lt;/p&gt;
&lt;/video&gt;

&lt;p&gt;And that’s basically it.&lt;/p&gt;

&lt;p&gt;I am personally looking forward to see what extension developers could do with
this new capability in Firefox! And since this is related to my work at Mozilla,
feel free to get in touch if you have questions.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Mozilla has its own “hub” too, so it isn’t &lt;em&gt;just&lt;/em&gt; from Hugging Face. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;I wrote a bit about my use of ML at work in 2019 &lt;a href=&quot;/2021/02/26/i-got-a-promotion/&quot;&gt;in this article&lt;/a&gt;. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Firefox Translations generates text so this can be considered Generative AI. A major difference is that this doesn’t rely on a Large Language Model (LLM). Instead, Translations uses (Marian) Neural Machine Translation (NMT) models and the &lt;a href=&quot;https://browser.mt/&quot;&gt;Bergamot&lt;/a&gt; runtime. &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;My colleague Tarek wrote &lt;a href=&quot;https://hacks.mozilla.org/2024/05/experimenting-with-local-alt-text-generation-in-firefox-nightly/&quot;&gt;an extensive Hacks article about this in 2024&lt;/a&gt;. &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
    </entry>
    
    <entry>
        <title>Senior Staff.</title>
        <link href="https://williamdurand.fr/2025/03/01/senior-staff/"/>
        <updated>2025-03-01T00:00:00+00:00</updated>
        <id>https://williamdurand.fr/2025/03/01/senior-staff</id>
        <content type="html">&lt;p&gt;I remember a conversation I had with a colleague a while back, shortly after I
joined, where they told me that promotions at Mozilla were almost
inevitable—that if you just stuck around long enough, you’d get promoted
eventually&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;It certainly didn’t feel like that to me.&lt;/p&gt;

&lt;p&gt;I’ve been working at Mozilla for about 7 years and I was last &lt;a href=&quot;/2021/02/26/i-got-a-promotion/&quot;&gt;promoted in
2021&lt;/a&gt;. I joined the &lt;a href=&quot;/2022/01/25/new-team-mozilla/&quot;&gt;WebExtensions
team in 2022&lt;/a&gt; to work on Manifest
Version 3, and then I led the engineering efforts to offer full add-ons support
for Firefox for Android in 2023. I became the tech lead for Add-ons in 2024.&lt;/p&gt;

&lt;p&gt;This month, I’ve been promoted to &lt;strong&gt;Senior Staff Software Engineer&lt;/strong&gt;! 🥳&lt;/p&gt;

&lt;p&gt;&lt;em&gt;But, what is a Senior Staff?&lt;/em&gt; Mozilla says it is an individual “recognized as
one of a small set of renowned experts in an important area”, who is able to
“lead projects requiring implementation across multiple teams”.&lt;/p&gt;

&lt;p&gt;I’m grateful to my manager and coworkers for their support and guidance over the
years. I’ve been able to achieve so much more than I thought possible thanks to
them! ❤️&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Coincidentally, and years later, another colleague told me this person had
actually worked hard to get where they were, and it wasn’t just a matter of
showing up and waiting for a promotion to happen 🙃 &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
    </entry>
    
    <entry>
        <title>Moziversary #6</title>
        <link href="https://williamdurand.fr/2024/05/01/moziversary-6/"/>
        <updated>2024-05-01T00:00:00+00:00</updated>
        <id>https://williamdurand.fr/2024/05/01/moziversary-6</id>
        <content type="html">&lt;p&gt;&lt;em&gt;Today is my sixth Moziversary 🎂 I joined Mozilla as a full-time employee on
May 1st, 2018. I previously blogged in &lt;del&gt;2019&lt;/del&gt;, &lt;a href=&quot;/2020/05/01/moziversary-2/&quot;&gt;2020&lt;/a&gt;, &lt;a href=&quot;/2021/05/01/moziversary-3/&quot;&gt;2021&lt;/a&gt;, &lt;a href=&quot;/2022/05/01/moziversary-4/&quot;&gt;2022&lt;/a&gt;,
and &lt;a href=&quot;/2023/05/01/moziversary-5/&quot;&gt;2023&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Last year, I mainly contributed to Firefox for Android as the lead engineer on a
project called “Add-ons General Availability (GA)”. The goal was to allow for
more add-ons on this platform. Success! &lt;a href=&quot;https://addons.mozilla.org/android/&quot;&gt;More than a thousand extensions are now
available on Android&lt;/a&gt; 🎉&lt;/p&gt;

&lt;p&gt;In addition, I worked on a Firefox feature called &lt;a href=&quot;https://support.mozilla.org/kb/quarantined-domains&quot;&gt;Quarantined Domains&lt;/a&gt; and
implemented a new abuse report form on &lt;a href=&quot;https://addons.mozilla.org/&quot;&gt;addons.mozilla.org&lt;/a&gt; (AMO) to comply
with the Digital Services Act (DSA). I was also involved in two other cross-team
efforts related to the Firefox installation funnel. I investigated various
issues (&lt;em&gt;e.g.&lt;/em&gt; this &lt;a href=&quot;https://bugzilla.opensuse.org/show_bug.cgi?id=1221531#c22&quot;&gt;openSUSE bug&lt;/a&gt;), and I coordinated the deprecation of
&lt;a href=&quot;https://discourse.mozilla.org/t/upgraded-add-on-signatures/129599&quot;&gt;weak add-on signatures&lt;/a&gt; and some more changes around certificates
lately, which is why I wrote &lt;a href=&quot;/xpidump/&quot;&gt;xpidump&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Phew! There is no shortage of work.&lt;/p&gt;

&lt;p&gt;When I moved to the WebExtensions team in 2022, &lt;a href=&quot;/2022/01/25/new-team-mozilla/&quot;&gt;I wrote about this incredible
challenge&lt;/a&gt;. I echoed this sentiment several months later in my &lt;a href=&quot;/2022/05/01/moziversary-4/&quot;&gt;2022
Moziversary update&lt;/a&gt;. I couldn’t imagine how much I would achieve in two
years…&lt;/p&gt;

&lt;p&gt;Back then, I didn’t know what the next step in my career would be. I have been
aiming to bridge the gap between the AMO and WebExtensions engineering teams
since at least &lt;a href=&quot;/2021/05/01/moziversary-3/&quot;&gt;2021&lt;/a&gt; and that &lt;em&gt;is&lt;/em&gt; my “next step”.&lt;/p&gt;

&lt;p&gt;I recently took a new role as Add-ons Tech Lead. This is the continuation of
what I’ve been doing for some time but that comes with new challenges and
opportunities as well. We’ll see how it goes but I am excited!&lt;/p&gt;

&lt;p&gt;I’ll be forever grateful to my manager and coworkers. Thank you ❤️&lt;/p&gt;

</content>
    </entry>
    
    <entry>
        <title>Introducing xpidump</title>
        <link href="https://williamdurand.fr/2024/04/08/introducing-xpidump/"/>
        <updated>2024-04-08T00:00:00+00:00</updated>
        <id>https://williamdurand.fr/2024/04/08/introducing-xpidump</id>
        <content type="html">&lt;p&gt;I wrote &lt;em&gt;xpidump&lt;/em&gt; to give a human-readable summary of some information about a
&lt;a href=&quot;https://addons.mozilla.org/firefox/&quot;&gt;Firefox add-on&lt;/a&gt;. It is designed to answer these two questions: is the add-on
likely&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; signed? And if so, how?&lt;/p&gt;

&lt;p&gt;This tool takes an XPI file as input. XPI files are Firefox add-ons packaged
as ZIP archives with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.xpi&lt;/code&gt; file extension. &lt;em&gt;xpidump&lt;/em&gt; currently extracts
information from up to 4 files in an XPI (depending on what is available in the
archive):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;manifest.json&lt;/code&gt;: this JSON file defines the add-on. It is required in any
add-on (packaged or not, signed or not).&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;META-INF/mozilla.rsa&lt;/code&gt;: this binary file is a &lt;a href=&quot;https://tools.ietf.org/html/rfc2315&quot;&gt;PKCS#7&lt;/a&gt; signature. Any signed
add-on should have this file (in addition to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;META-INF/mozilla.sf&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;META-INF/manifest.mf&lt;/code&gt; but &lt;em&gt;xpidump&lt;/em&gt; doesn’t read them).&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;META-INF/cose.sig&lt;/code&gt;: this binary file is a &lt;a href=&quot;https://datatracker.ietf.org/doc/html/rfc8152&quot;&gt;COSE&lt;/a&gt; signature&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. It might
not be present when the add-on isn’t signed or relatively old&lt;sup id=&quot;fnref:3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;. There
should also be a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;META-INF/cose.manifest&lt;/code&gt; file when this file exists.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mozilla-recommendation.json&lt;/code&gt;: this JSON file is generated by Mozilla’s
signing service &lt;a href=&quot;https://github.com/mozilla-services/autograph&quot;&gt;Autograph&lt;/a&gt; when an add-on is signed with recommendation
states. This is how Firefox knows that an add-on is &lt;a href=&quot;https://support.mozilla.org/en-US/kb/recommended-extensions-program&quot;&gt;recommended&lt;/a&gt; for
instance. It might or might not be present.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;xpidump&lt;/em&gt; is both a command-line tool and a web app since the latter is usually
more convenient (no need to install anything). It’s written in Rust, and
compiled to WebAssembly for the web app. You can try it at:
&lt;a href=&quot;https://williamdurand.fr/xpidump/&quot;&gt;williamdurand.fr/xpidump/&lt;/a&gt;.&lt;/p&gt;

&lt;p class=&quot;with-caption&quot;&gt;&lt;img src=&quot;/images/posts/2024/04/xpidump.webp&quot; alt=&quot;&quot; /&gt;
&lt;em&gt;xpidump is available in the browser thanks to WebAssembly!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The code is published on GitHub under the MIT license, see:
&lt;a href=&quot;https://github.com/willdurand/xpidump/&quot;&gt;willdurand/xpidump&lt;/a&gt;. I don’t have any
more plans for this weekend-ish project, it’s doing what I wanted it to be
doing… Let me know if you have ideas, though.&lt;/p&gt;

&lt;p&gt;One more thing while we’re here… If you want a tool to read the entire content
of any XPI file and get tons of information, you want to use &lt;a href=&quot;https://robwu.nl/crxviewer/&quot;&gt;CRX Viewer&lt;/a&gt;
created by my brilliant colleague Rob!&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;This tool doesn’t verify the signature, so it cannot guarantee that the
  add-on is correctly signed. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Well, a COSE sign message with a signature and serialized with &lt;a href=&quot;https://datatracker.ietf.org/doc/html/rfc7049&quot;&gt;CBOR&lt;/a&gt;,
  though we should probably refer to the protocol as COSEish because of
  &lt;a href=&quot;https://github.com/franziskuskiefer/cose-rust/issues/60&quot;&gt;this issue&lt;/a&gt;. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Mozilla started to dual-sign add-ons in 2019. &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
    </entry>
    
    <entry>
        <title>Moziversary #5</title>
        <link href="https://williamdurand.fr/2023/05/01/moziversary-5/"/>
        <updated>2023-05-01T00:00:00+00:00</updated>
        <id>https://williamdurand.fr/2023/05/01/moziversary-5</id>
        <content type="html">&lt;p&gt;&lt;em&gt;Today is my fifth&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; Moziversary 🎂 I joined Mozilla as a full-time employee
on May 1st, 2018. I previously blogged in &lt;del&gt;2019,&lt;/del&gt; &lt;a href=&quot;/2020/05/01/moziversary-2/&quot;&gt;2020&lt;/a&gt;, &lt;a href=&quot;/2021/05/01/moziversary-3/&quot;&gt;2021&lt;/a&gt;, and
&lt;a href=&quot;/2022/05/01/moziversary-4/&quot;&gt;2022&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I spent a good chunk of last year working on &lt;a href=&quot;https://blog.mozilla.org/addons/2022/11/17/manifest-v3-signing-available-november-21-on-firefox-nightly/&quot;&gt;Manifest Version 3&lt;/a&gt; (MV3) with
the rest of my team (WebExtensions / Add-ons team). My most notable “H1 2022”
contributions were probably the &lt;a href=&quot;https://developer.mozilla.org/docs/Mozilla/Add-ons/WebExtensions/API/scripting&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scripting&lt;/code&gt;&lt;/a&gt; namespace and a
&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1793925&quot;&gt;simpler versioning format&lt;/a&gt;.&lt;/p&gt;

&lt;p class=&quot;with-caption&quot;&gt;&lt;img src=&quot;/images/posts/2023/05/extensions-button.webp&quot; alt=&quot;&quot; /&gt;
&lt;em&gt;The extensions button and its panel (with 3 extensions listed) in Firefox.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Next, I worked on a new primary User Interface (UI) for Firefox Desktop: the
&lt;a href=&quot;https://support.mozilla.org/en-US/kb/extensions-button&quot;&gt;extensions button&lt;/a&gt;. This feature wasn’t unanimously
well-received&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; &lt;sup id=&quot;fnref:3&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; (like many other changes to the Firefox UI). Anyway, I
addressed different (usability) issues since then, and I will continue to do so!&lt;/p&gt;

&lt;p&gt;I also…&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;took over more &lt;a href=&quot;https://github.com/mozilla/web-ext&quot;&gt;web-ext&lt;/a&gt; maintenance (in addition to &lt;a href=&quot;https://github.com/mozilla/addons-linter&quot;&gt;addons-linter&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;contributed content to &lt;a href=&quot;https://support.mozilla.org&quot;&gt;support.mozilla.org&lt;/a&gt;
(SUMO)&lt;/li&gt;
  &lt;li&gt;added &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1437171&quot;&gt;WebMIDI support to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;navigator.permissions.query()&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;wrote my &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1805783&quot;&gt;first Web platform test&lt;/a&gt;. Pretty cool!&lt;/li&gt;
  &lt;li&gt;committed to new repositories such as &lt;a href=&quot;https://github.com/mozilla-releng/scriptworker-scripts&quot;&gt;scriptworker-scripts&lt;/a&gt;,
&lt;a href=&quot;https://github.com/mozilla-extensions/xpi-template&quot;&gt;xpi-template&lt;/a&gt;, &lt;a href=&quot;https://developer.mozilla.org/&quot;&gt;MDN&lt;/a&gt;, &lt;a href=&quot;https://github.com/mdn/browser-compat-data/&quot;&gt;browser-compat-data&lt;/a&gt;, and &lt;a href=&quot;https://github.com/mozilla-mobile/firefox-android&quot;&gt;firefox-android&lt;/a&gt;
lately&lt;/li&gt;
  &lt;li&gt;found myself involved in various incidents…&lt;/li&gt;
  &lt;li&gt;stopped hating Jira&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But wait, there is more!&lt;/p&gt;

&lt;p&gt;When I was on the AMO team, we had to maintain a feature named “Return to AMO”
(RTAMO). In short, this feature allows new users interested in an add-on on
addons.mozilla.org (AMO) to download Firefox and install the add-on when Firefox
starts for the first time (without having to go back to AMO). RTAMO was extended
to more add-ons at the beginning of 2022 (and I was involved). I became very
knowledgeable about how attribution worked and documented all of that.&lt;/p&gt;

&lt;p&gt;This is one of the reasons why I became the main owner&lt;sup id=&quot;fnref:4&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; of the &lt;a href=&quot;https://github.com/mozilla-services/stubattribution&quot;&gt;stub
attribution service&lt;/a&gt;, an HTTP server that encodes attribution
data in Firefox (for Windows) installers and – incidentally – one of the few
critical services involved when users download Firefox. Coincidentally, this
project is now at the center of different 2023 projects. Good thing I took the
time to put this project back on track 😛&lt;/p&gt;

&lt;p&gt;Phew. That was a good year! I am now involved in many cross-functional projects
and I really enjoy it. Speaking of which, I am currently working on bringing
more add-ons to Firefox for Android 🚀&lt;/p&gt;

&lt;p&gt;That’s all for now. Many thanks to everyone I worked with over the last 12
months, it’s been great working with all of you!&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;5 years or… 5 months? I moved back to France and my current employment
contract started on January 1st, heh. Still better than nothing, though. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;In case you didn’t know, many engineers read Reddit and/or other social
platforms. I’ve shared actionable feedback from public comments internally
more than once. That said, writing that the extensions button is the “worst
Mozilla idea of the decade” isn’t helpful. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;If I may, I would add that reaching out to me personally to say that you
hate the button is probably not OK. &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;I am (still) trying to build a small team around this project and &lt;a href=&quot;https://github.com/mozilla-services/go-bouncer&quot;&gt;another
one&lt;/a&gt;. If you want to join the fun, please let me know! &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
    </entry>
    
    <entry>
        <title>Developing Firefox in Firefox with Gitpod</title>
        <link href="https://williamdurand.fr/2022/05/03/developing-firefox-in-firefox-with-gitpod/"/>
        <updated>2022-05-03T00:00:00+00:00</updated>
        <id>https://williamdurand.fr/2022/05/03/developing-firefox-in-firefox-with-gitpod</id>
        <content type="html">&lt;p&gt;&lt;a href=&quot;https://gitpod.io/&quot;&gt;Gitpod&lt;/a&gt; provides Linux-based development environments on demand along with a
web editor frontend (VS Code). There is apparently no limit on what you can do
in a &lt;a href=&quot;https://www.gitpod.io/docs/workspaces&quot;&gt;Gitpod workspace&lt;/a&gt;, e.g., I ran my own toy kernel in QEMU in the browser.&lt;/p&gt;

&lt;p&gt;I like Gitpod because it…&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;avoids potential issues when setting up a new project, which is great for the
maintainers (e.g., it is easier to reproduce an issue when you have access to
the same environment) and the newcomers (e.g., no fatal error when trying to
contribute for the first time)&lt;/li&gt;
  &lt;li&gt;allows anyone to have access to a (somewhat) powerful machine because not
everyone can afford a MacBook Pro. I suppose one needs a pretty reliable
Internet connection, though&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;motivations&quot;&gt;Motivations&lt;/h2&gt;

&lt;p&gt;My main machine runs MacOS. I also have a Windows machine on my desk (useful to
debug &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1761550&quot;&gt;annoying Windows-only intermittent failures&lt;/a&gt;), which I
access with Microsoft Remote Desktop.&lt;/p&gt;

&lt;p class=&quot;with-caption&quot;&gt;&lt;img src=&quot;/images/posts/2022/05/remote-desktop.webp&quot; alt=&quot;&quot; /&gt;
&lt;em&gt;It looks like Gitpod, runs like Gitpod, and quacks like Gitpod but it isn’t Gitpod!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Except my ever growing collection of single-board computers, I don’t have a
Linux-based machine at home^W work, though. I haven’t used Virtual Machines on
Apple Silicon yet and I’d rather keep an eye on &lt;a href=&quot;https://asahilinux.org/&quot;&gt;Asahi Linux&lt;/a&gt; instead.&lt;/p&gt;

&lt;p&gt;This is why I wanted to give Gitpod a try and see if it could become my Linux
environment for working on Firefox. Clearly, this is a nice to have for me (I
don’t necessarily need to build Firefox on Linux) but that might be useful to
others.&lt;/p&gt;

&lt;p&gt;Assuming a Gitpod-based setup would work for me, this could possibly become a
strong alternative for other contributors as well. Then, &lt;em&gt;mayyybe&lt;/em&gt; I could start
a conversation about it internally in the (far) future.&lt;/p&gt;

&lt;p&gt;Note that this isn’t a novel idea, Jan Keromnes was already working on a similar
tool called &lt;a href=&quot;https://www.youtube.com/watch?v=5sNDMIh-iVw&quot;&gt;“Janitor” for Mozilla needs in 2015&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;firefox-development-with-gitpod--️&quot;&gt;Firefox development with Gitpod = ❤️&lt;/h2&gt;

&lt;p&gt;I recently put together &lt;a href=&quot;https://github.com/willdurand/gitpod-firefox-dev&quot;&gt;a proof of concept&lt;/a&gt; and played
with it since then. This GitHub repository contains the Gitpod configuration
to checkout the Firefox sources as well as the tools required to build Firefox.&lt;/p&gt;

&lt;p&gt;It takes about 7 minutes to be able to run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;./mach run&lt;/code&gt; in a fresh workspace
(artifact mode). It is not super fast, although I already improved the initial
load time by using a &lt;a href=&quot;https://hub.docker.com/r/willdurand/gitpod-firefox-dev&quot;&gt;custom Docker image&lt;/a&gt;. It is
also worth mentioning that re-opening an existing workspace is much faster!&lt;/p&gt;

&lt;p class=&quot;with-caption&quot;&gt;&lt;img src=&quot;/images/posts/2022/05/gitpod-mach-run.webp&quot; alt=&quot;&quot; /&gt;
&lt;em&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;./mach run&lt;/code&gt; executed in a Gitpod workspace&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Gitpod provides a Docker image with &lt;a href=&quot;https://www.gitpod.io/blog/native-ui-with-vnc&quot;&gt;X11 and VNC&lt;/a&gt;, which I used as the base
for my custom Docker image. This is useful to interact with Firefox as well as
observing some of the tests running.&lt;/p&gt;

&lt;p class=&quot;with-caption&quot;&gt;&lt;img src=&quot;/images/posts/2022/05/gitpod-mach-test.webp&quot; alt=&quot;&quot; /&gt;
&lt;em&gt;A “mochitest” running in a Gitpod workspace&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I don’t know if &lt;em&gt;this&lt;/em&gt; is the right approach, though. My understanding is that
Gitpod works best when its configuration lives next to the sources. For Firefox,
that would mean having the configuration in the official Mozilla &lt;a href=&quot;https://www.mercurial-scm.org/&quot;&gt;Mercurial&lt;/a&gt;
repositories but then we would need &lt;em&gt;hgpod.io&lt;/em&gt; 😅&lt;/p&gt;

&lt;p&gt;On the other hand, we develop Firefox using a &lt;a href=&quot;https://jg.gg/2018/09/29/stacked-diffs-versus-pull-requests/&quot;&gt;stacked diff&lt;/a&gt; workflow.
Therefore, we probably don’t need most of the VCS features and &lt;a href=&quot;https://www.gitpod.io/blog/gitpod-jetbrains&quot;&gt;Gitpod does not
want to be seen as an online IDE&lt;/a&gt; anyway. I personally rely
on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt; with the excellent &lt;a href=&quot;https://github.com/glandium/git-cinnabar&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git-cinnabar&lt;/code&gt; helper&lt;/a&gt;, and &lt;a href=&quot;https://moz-conduit.readthedocs.io/en/latest/phabricator-user.html#setting-up-mozphab&quot;&gt;moz-phab&lt;/a&gt;
to submit patches to Phabricator. Except for the latter, which can easily be
installed with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;./mach install-moz-phab&lt;/code&gt;, these tools are already available in
Gitpod workspaces created with &lt;a href=&quot;https://github.com/willdurand/gitpod-firefox-dev&quot;&gt;my repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In terms of limitations, cloning &lt;a href=&quot;https://mozilla-version-control-tools.readthedocs.io/en/latest/hgmozilla/unifiedrepo.html&quot;&gt;mozilla-unified&lt;/a&gt; is the most time-consuming
task at the moment. Gitpod has a feature called &lt;a href=&quot;https://www.gitpod.io/docs/prebuilds&quot;&gt;Prebuilds&lt;/a&gt; that could help
but I am not sure how that would work when the actual project repository isn’t
the one that contains the Gitpod configuration.&lt;/p&gt;

&lt;p&gt;In case you’re wondering, I also started a full build (no artifact) and it took
about 40 minutes to finish 🙁 I was hoping to have better performances out of
the box even if it isn’t &lt;em&gt;that&lt;/em&gt; bad. For comparison, it takes [~15min on my
MacBook Pro with M1 Max]&lt;sup id=&quot;fnref:tweet-m1-max&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:tweet-m1-max&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; (and 2 hours on my previous Apple
machine).&lt;/p&gt;

&lt;p&gt;There are other things that I’d like to poke around. For instance, I would love
to have &lt;a href=&quot;https://github.com/rr-debugger/rr&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rr&lt;/code&gt;&lt;/a&gt; support in Gitpod. I gave it a quick try and it does not seem
possible so far, maybe because of &lt;a href=&quot;https://github.com/rr-debugger/rr/wiki/Docker&quot;&gt;how Docker is configured&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gitpod /workspace/gitpod-firefox-dev/mozilla-unified (bookmarks/central) $ rr record -n /usr/bin/ls
[FATAL /tmp/rr/src/PerfCounters.cc:224:start_counter() errno: EPERM] Failed to initialize counter
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After a few messages exchanged on Twitter, Jan Keromnesjan (yeah, same as above)
from Gitpod filed a &lt;a href=&quot;https://github.com/gitpod-io/gitpod/issues/9687&quot;&gt;feature request to support &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rr&lt;/code&gt;&lt;/a&gt; 🤞&lt;/p&gt;

&lt;h2 id=&quot;next-steps&quot;&gt;Next steps&lt;/h2&gt;

&lt;p&gt;As I mentioned previously, this is a proof of concept but it is already
functional. I’ll personally continue to evaluate this Linux-based development
environment. If it gets &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rr&lt;/code&gt; support, this might become my debugging
environment of choice!&lt;/p&gt;

&lt;p&gt;Now, if you are interested, you can go ahead and &lt;a href=&quot;https://gitpod.io/#https://github.com/willdurand/gitpod-firefox-dev&quot;&gt;create a new
workspace&lt;/a&gt; automatically. Otherwise please reach out to me and
let’s discuss!&lt;/p&gt;

&lt;p&gt;One more thing: Mozilla employees (and many other Open Source contributors)
qualify for the &lt;a href=&quot;https://www.gitpod.io/blog/gitpod-for-opensource&quot;&gt;Gitpod for Open Source&lt;/a&gt; program.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:tweet-m1-max&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;This used to be a link to a tweet from me:&lt;/p&gt;
      &lt;blockquote class=&quot;footnote-tweet&quot;&gt;
        &lt;p&gt;This new MBP 14” with M1 Max chip seems promising: keyboard feels nice, no
distracting touch bar, and it compiles Firefox in less than 15 minutes!
(vs ~2 hours with my previous machine)&lt;/p&gt;
      &lt;/blockquote&gt;
      &lt;p&gt;&lt;a href=&quot;#fnref:tweet-m1-max&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
    </entry>
    
    <entry>
        <title>Moziversary #4</title>
        <link href="https://williamdurand.fr/2022/05/01/moziversary-4/"/>
        <updated>2022-05-01T00:00:00+00:00</updated>
        <id>https://williamdurand.fr/2022/05/01/moziversary-4</id>
        <content type="html">&lt;p&gt;&lt;em&gt;Today is my fourth Moziversary 🎂 I have been working at Mozilla as a full-time
employee for 4 years. I blogged two times before: in &lt;a href=&quot;/2020/05/01/moziversary-2/&quot;&gt;2020&lt;/a&gt; and &lt;a href=&quot;/2021/05/01/moziversary-3/&quot;&gt;2021&lt;/a&gt;. What
happened in 2019? I. Don’t. Know.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I was hired as a Senior Web Developer on &lt;a href=&quot;https://addons.mozilla.org/&quot;&gt;addons.mozilla.org&lt;/a&gt; (AMO). I am now
a &lt;a href=&quot;/2021/02/26/i-got-a-promotion/&quot;&gt;Staff Software Engineer&lt;/a&gt; in the Firefox WebExtensions team. I
officially &lt;a href=&quot;/2022/01/25/new-team-mozilla/&quot;&gt;joined this team&lt;/a&gt; in January. Since then, I became a
&lt;a href=&quot;https://www.mozilla.org/en-US/about/governance/policies/module-ownership/&quot;&gt;peer&lt;/a&gt; of the &lt;a href=&quot;https://wiki.mozilla.org/Modules/All#Add-ons_Manager&quot;&gt;Add-ons Manager&lt;/a&gt; and &lt;a href=&quot;https://wiki.mozilla.org/Modules/All#Webextensions&quot;&gt;WebExtensions&lt;/a&gt; modules.&lt;/p&gt;

&lt;h2 id=&quot;farewell-amo&quot;&gt;Farewell AMO!&lt;/h2&gt;

&lt;p&gt;As mentioned above, I moved to another team after many years in the AMO team.
If I had to summarize my time in this team, I would probably say: “I did my
part”.&lt;/p&gt;

&lt;p&gt;Earlier this year, I transferred ownership of more than 10 projects that I
either created or took over to my former (AMO) colleagues 😬 I was maintaining
these projects in addition to the bulk of my work, which has been extremely
diverse. As far as I can remember, I…&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;worked on countless user-facing features on AMO, quickly becoming the &lt;a href=&quot;https://github.com/mozilla/addons-frontend/graphs/contributors&quot;&gt;top
committer on addons-frontend&lt;/a&gt; (for what it’s worth)&lt;/li&gt;
  &lt;li&gt;contributed many improvements to the AMO backend (Django/Python). For
example, I drastically improved the reliability of the Git extraction system
that we use for signed add-ons&lt;/li&gt;
  &lt;li&gt;developed a set of anti-malware scanning and code search tools that have
been “a game changer to secure the add-ons ecosystem for Firefox”&lt;/li&gt;
  &lt;li&gt;introduced &lt;a href=&quot;https://aws.amazon.com/lambda/&quot;&gt;AWS Lambda&lt;/a&gt; to our infrastructure for some (micro) services&lt;/li&gt;
  &lt;li&gt;created prototypes, e.g., I wrote a CLI tool leveraging &lt;a href=&quot;https://spidermonkey.dev/&quot;&gt;SpiderMonkey&lt;/a&gt;
to dynamically analyze browser extension behaviors&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://blog.mozilla.org/addons/2021/01/21/promoted-add-ons-pilot-wrap-up/&quot;&gt;almost&lt;/a&gt; integrated Stripe with AMO 🙃&lt;/li&gt;
  &lt;li&gt;shipped entire features spanning many components end-to-end like the &lt;a href=&quot;https://blog.mozilla.org/addons/2020/06/10/improvements-to-statistics-processing-on-amo/&quot;&gt;AMO
Statistics&lt;/a&gt; (AMO frontend + backend, BigQuery/ETL with Airflow, and some
patches in Firefox)&lt;/li&gt;
  &lt;li&gt;created &lt;a href=&quot;/2022/03/29/some-non-production-tools-i-wrote/&quot;&gt;various dev/QA tools&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Last but not least, I started and developed a collaboration with Mozilla’s Data
Science team on a Machine Learning (security-oriented) project. This has been
one of my best contributions to Mozilla to date.&lt;/p&gt;

&lt;h2 id=&quot;what-did-i-do-over-the-last-12-months&quot;&gt;What did I do over the last 12 months?&lt;/h2&gt;

&lt;p&gt;I built the “new” &lt;a href=&quot;https://addons.mozilla.org/blog/&quot;&gt;AMO blog&lt;/a&gt;. I played with &lt;a href=&quot;https://www.11ty.dev/&quot;&gt;Eleventy&lt;/a&gt; for the first time
and wrote some PHP to tweak the WordPress backend for our needs. I also
“hijacked” our addons-frontend project a bit to &lt;a href=&quot;https://github.com/mozilla/addons-frontend/tree/5518fc1091241849f1f90634fe5d8f5d3cce2688#addons-frontend-blog-utils&quot;&gt;reuse some logic and
components&lt;/a&gt; for the “enhanced add-on cards” used on the blog
(screenshot below).&lt;/p&gt;

&lt;p class=&quot;with-caption&quot;&gt;&lt;img src=&quot;/images/posts/2022/05/amo-blog.webp&quot; alt=&quot;&quot; /&gt;
&lt;em&gt;The AMO blog with an add-on card for the “OneTab” extension. The “Add to
Firefox” button is dynamic like the install buttons on the main AMO website.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Next, I co-specified and implemented a Firefox feature to detect search
hijacking at scale. After that, I started to work on some of the new &lt;a href=&quot;https://blog.mozilla.org/addons/2021/05/27/manifest-v3-update/&quot;&gt;Manifest
V3 APIs in Firefox&lt;/a&gt; and eventually joined the WebExtensions team full-time.&lt;/p&gt;

&lt;p&gt;I also…&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;wrote a &lt;a href=&quot;https://blog.mozilla.org/addons/2021/12/07/new-javascript-syntax-support-in-add-on-developer-tools/&quot;&gt;blog post about the add-ons linter&lt;/a&gt; on the Community
Blog&lt;/li&gt;
  &lt;li&gt;interviewed candidates (if you want to discuss, &lt;a href=&quot;https://www.mozilla.org/en-US/careers/&quot;&gt;we’re hiring&lt;/a&gt; 😉)&lt;/li&gt;
  &lt;li&gt;took the time to meet new colleagues in a few &lt;a href=&quot;https://www.donut.com/&quot;&gt;donut chats&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;accidentally prevented huge unnecessary storage costs 😅&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This period has been complicated, though. The manager who hired me and helped
me grow as an engineer left last year 😭 Some other folks I used to work with
are no longer at Mozilla either. That got me thinking about my career and my
recent choices. I firmly believe that moving to the WebExtensions team was the
right call. Yet, most of the key people who could have helped me grow further
are gone. Building trustful relationships takes time and so does having
opportunities to demonstrate capabilities.&lt;/p&gt;

&lt;p&gt;Sure, I still have plenty of things to learn in my current role but I hardly
see what the next milestone will be in my career at the moment. That being
said, I love what I am doing at Mozilla and my team is fabulous ❤️&lt;/p&gt;

&lt;p&gt;Thank you to everyone in the Add-ons team as well as to all the folks I had the
pleasure to work with so far!&lt;/p&gt;

</content>
    </entry>
    
    <entry>
        <title>Some non-production tools I wrote</title>
        <link href="https://williamdurand.fr/2022/03/29/some-non-production-tools-i-wrote/"/>
        <updated>2022-03-29T00:00:00+00:00</updated>
        <id>https://williamdurand.fr/2022/03/29/some-non-production-tools-i-wrote</id>
        <content type="html">&lt;p&gt;This is a short article about 3 different tools I authored for my needs at
Mozilla.&lt;/p&gt;

&lt;p&gt;I worked on &lt;a href=&quot;https://addons.mozilla.org/&quot;&gt;AMO&lt;/a&gt; for almost 4 years and created various libraries like
&lt;a href=&quot;https://github.com/mozilla/pino-mozlog&quot;&gt;pino-mozlog&lt;/a&gt;, &lt;a href=&quot;https://github.com/willdurand/pino-devtools&quot;&gt;pino-devtools&lt;/a&gt; or an &lt;a href=&quot;https://github.com/mozilla/eslint-plugin-amo&quot;&gt;ESLint plugin&lt;/a&gt; to
name a few. These libraries have been created either to improve our developer
experience or to fulfill some production requirements.&lt;/p&gt;

&lt;p&gt;This isn’t the kind of projects I want to focus on in the rest of this article,
though. Indeed, I also wrote “non-production” tools, i.e. some side projects to
improve my day-to-day work. These tools have been extremely useful to me and,
possibly, other individuals as well. I use most of them on a weekly basis and I
maintain them on my own.&lt;/p&gt;

&lt;h2 id=&quot;amo-info&quot;&gt;amo-info&lt;/h2&gt;

&lt;p&gt;I wrote a browser extension named &lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/amo-info/&quot;&gt;amo-info&lt;/a&gt;. This extension adds a page
action button when we open the web applications maintained by the AMO/Add-ons
team. Clicking on this button reveals a pop-up with relevant information like
the environment, git tag, feature flags, etc.&lt;/p&gt;

&lt;p class=&quot;with-caption&quot;&gt;&lt;img src=&quot;/images/posts/2022/03/amo-info.webp&quot; alt=&quot;&quot; /&gt;
&lt;em&gt;The amo-info extension displaying information about addons.mozilla.org.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If this sounds familiar to you, it might be because I already mentioned this
project in my &lt;a href=&quot;/2020/09/22/feature-flags-in-real-life/&quot;&gt;article about feature flags&lt;/a&gt;. Anyway, knowing what
is currently deployed in any environment at any given time is super valuable,
and this extension makes it easy to find out!&lt;/p&gt;

&lt;p&gt;I recently added support for Firefox for Android but it &lt;a href=&quot;https://blog.mozilla.org/addons/2020/09/29/expanded-extension-support-in-firefox-for-android-nightly/&quot;&gt;only works in
Nightly&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;git-npm-release&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git npm-release&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;A different tool I use every week is the &lt;a href=&quot;https://github.com/willdurand/dotfiles/blob/8abc8da3ca5f9f7a3d8e0d629552a15a819ad2d5/git/commands/npm-release&quot;&gt;git npm-release&lt;/a&gt; command,
which automates my process to release new versions of our JavaScript packages.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ git npm-release -h
usage: git npm-release [help|major|minor|patch]

git npm-release help
        print this help message.
git npm-release major
        create a major version.
git npm-release minor
        create a minor version.
git npm-release patch
        create a patch version.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For most of our JavaScript projects, we leverage a Continuous Integration (CI)
platform (e.g., CircleCI) to automatically publish new versions on the &lt;a href=&quot;https://www.npmjs.com/&quot;&gt;npm
registry&lt;/a&gt; when a git tag is pushed to a GitHub repository.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git npm-release&lt;/code&gt; command is built on top of &lt;a href=&quot;https://hub.github.com/&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hub&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;https://docs.npmjs.com/cli/version&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm
version&lt;/code&gt;&lt;/a&gt; and a homemade &lt;a href=&quot;https://github.com/willdurand/dotfiles/blob/8abc8da3ca5f9f7a3d8e0d629552a15a819ad2d5/scripts/format-release-notes&quot;&gt;script to format release
notes&lt;/a&gt;. Running this command will (1) update the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;package.json&lt;/code&gt; file with the right version, (2) make a git tag, (3) prepare the
release notes and open an editor, (4) push the commit/tag to GitHub, and (5)
create a GitHub release.&lt;/p&gt;

&lt;p&gt;This process isn’t fully automated because (3) opens an editor with the
pre-formatted release notes. I usually provide some more high level information
in the notes, which is why this step requires manual intervention.&lt;/p&gt;

&lt;h2 id=&quot;fx-attribution-data-reader&quot;&gt;fx-attribution-data-reader&lt;/h2&gt;

&lt;p&gt;This is a tool I created not too long ago after telling a QA engineer that “he
could simply open the binary in an hex editor” 😅 I can find my way in hex dumps
because &lt;a href=&quot;/2022/03/10/spi-flash-content-analysis-and-firmware-reconstruction/&quot;&gt;my hobbies are weird&lt;/a&gt; but I get that it isn’t
everyone else’s cup of tea.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://williamdurand.fr/fx-attribution-data-reader/&quot;&gt;fx-attribution-data-reader&lt;/a&gt; web application takes a Firefox for
Windows binary and displays the attribution data that may be contained in it.
Everything is performed locally (in the browser) but the results can also be
shared (URLs are “shareable”).&lt;/p&gt;

&lt;p class=&quot;with-caption&quot;&gt;&lt;img src=&quot;/images/posts/2022/03/fx-reader.webp&quot; alt=&quot;&quot; /&gt;
&lt;em&gt;The fx-attribution-data-reader tool with a binary loaded and parsed.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Currently, this is mainly useful to debug some add-ons related features and it
is very niche. As such, this tool isn’t used very often but this is a good
example of a very simple UI built to hide some (unnecessary) complexity.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;I introduced three different tools that I am happy to use and maintain. &lt;a href=&quot;https://xkcd.com/1205/&quot;&gt;Is it
worth the time?&lt;/a&gt; I think so because it isn’t so much
about the time shaved off in this case.&lt;/p&gt;

&lt;p&gt;It is more about the simplicity and ease of use. Also, writing new tools is fun!
I often use these ideas as excuses to learn more about new topics, be it
programming languages, frameworks, libraries, or some internals.&lt;/p&gt;

</content>
    </entry>
    
    <entry>
        <title>I joined a new team (at Mozilla)</title>
        <link href="https://williamdurand.fr/2022/01/25/new-team-mozilla/"/>
        <updated>2022-01-25T00:00:00+00:00</updated>
        <id>https://williamdurand.fr/2022/01/25/new-team-mozilla</id>
        <content type="html">&lt;p&gt;The year is 2022 and I am still using my blog to share personal-ish status
updates. Today’s post is about my career.&lt;/p&gt;

&lt;p&gt;I work at Mozilla for ~4 years now (including my time as a contractor). After
having worked on &lt;a href=&quot;/2020/05/01/moziversary-2/&quot;&gt;many&lt;/a&gt;
&lt;a href=&quot;/2021/05/01/moziversary-3/&quot;&gt;things&lt;/a&gt; and getting a
&lt;a href=&quot;/2021/02/26/i-got-a-promotion/&quot;&gt;promotion&lt;/a&gt; not too long ago, I made a &lt;a href=&quot;https://www.glassdoor.com/blog/lateral-career-moves/&quot;&gt;lateral
move&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I am now a full-time &lt;strong&gt;Firefox engineer&lt;/strong&gt;, working on the &lt;a href=&quot;https://extensionworkshop.com/documentation/develop/about-the-webextensions-api/&quot;&gt;WebExtensions API&lt;/a&gt;.
I’ve been working on “web apps” for most of my career and now I’ll be writing
code for developers to write browser extensions.&lt;/p&gt;

&lt;p&gt;This is scary and maybe a bit silly (career-wise) but this is also an incredible
challenge for me. That’s what I wanted. That’s what I needed. I left a great
team to join a fantastic team where I am the least experienced in the domain we
own. It &lt;em&gt;almost&lt;/em&gt; feels like I am back at the beginning of my career, except that
I now know how much I don’t know. Ha, well. It’s going to be fine.&lt;/p&gt;

</content>
    </entry>
    
    <entry>
        <title>Moziversary #3</title>
        <link href="https://williamdurand.fr/2021/05/01/moziversary-3/"/>
        <updated>2021-05-01T00:00:00+00:00</updated>
        <id>https://williamdurand.fr/2021/05/01/moziversary-3</id>
        <content type="html">&lt;p&gt;&lt;em&gt;Three years at Mozilla, yay! 🎉 It’s my longest time at the same company, and I
am now a &lt;a href=&quot;/2021/02/26/i-got-a-promotion/&quot;&gt;Staff Software Engineer&lt;/a&gt;. What a ride!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A year ago, &lt;a href=&quot;/2020/05/01/moziversary-2/&quot;&gt;I wrote that I was starting to be more involved in
Firefox&lt;/a&gt;. I worked on very diverse projects in 2020 but one of
them was super fun: we revamped the AMO statistics and it required backend
changes on AMO, some ETL/BigQuery work, and new data collection in Firefox. I
worked on all those components and learned a lot of stuff along the way. I also
[deleted a lot of code]&lt;sup id=&quot;fnref:deleted-code&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:deleted-code&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, [changed a lot of code]&lt;sup id=&quot;fnref:black&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:black&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;,
contributed to Firefox for Android (Fenix), created new libraries to support the
work of my team, continued to work on security stuff, and even wrote some PHP
lately.&lt;/p&gt;

&lt;p&gt;My role is constantly evolving. By knowing every bit of the AMO platform and
expanding my skill sets with contributions in Firefox, I am hoping to have a
wider vision of add-ons in general, from a technical perspective. I am doing my
best to bridge the gap between the AMO and WebExtensions engineering teams,
which will be welcomed as more Product requirements need changes in both
contexts.&lt;/p&gt;

&lt;p&gt;Now, thinking about the last 12 months, there are areas that I would like to
improve.&lt;/p&gt;

&lt;p&gt;I mentioned it above, I work on very different projects and components.  It’s
exciting because I am never bored, I can help many folks and I learn a lot but
context switching is hard. My tmux session has ~10 windows open all the time
nowadays (one per project) so I had to adapt. I wrote a bunch of scripts to
automate some maintenance tasks, I started to dedicate specific days to certain
projects, and I learned to be more strict about priorities. I still have some
work to do on that front, though.&lt;/p&gt;

&lt;p&gt;I noticed that all these different projects kinda “forced” me to “move fast”,
and too fast actually. It didn’t negatively impact anything (yet) but I’ve
definitely been reminded that the answer to my question was in the GitHub issue
that I had just read. Hence I am working on taking more time to think… and
I’ll also take the opportunity to refine my communication skills.&lt;/p&gt;

&lt;p&gt;Last, I am extremely happy at Mozilla and I am super lucky to be part of the
amazing Add-ons team. I would like to thank everyone in my team as well as all
the folks I worked with so far! I wouldn’t be where I am today without you ❤️&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:deleted-code&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;This used to be a link to a tweet from me. I tweeted a
screenshot with diff stats, showing a lot of code removed after I removed a
lot of code in a project. &lt;a href=&quot;#fnref:deleted-code&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:black&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;This used to be a link to a tweet from me. I tweeted a screenshot with
diff stats, showing a lot of changed code after having applied a python code
formatter on a large codebase. &lt;a href=&quot;#fnref:black&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
    </entry>
    
    <entry>
        <title>Yes, it happened on Slack</title>
        <link href="https://williamdurand.fr/2021/04/29/yes-it-happened-on-slack/"/>
        <updated>2021-04-29T00:00:00+00:00</updated>
        <id>https://williamdurand.fr/2021/04/29/yes-it-happened-on-slack</id>
        <content type="html">&lt;p&gt;This is one of those moments worth calling out explicitly.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Yes, it happened on Slack&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here, &lt;em&gt;it&lt;/em&gt; refers to a decision, an agreement, or some important results. All of
these should NOT have been left on Slack alone. At the very least, the Slack
threads or some key messages should have been copied into some more open and
permanent places like Bugzilla or GitHub (in public issues).&lt;/p&gt;

&lt;p&gt;It won’t come as a surprise; I don’t like Slack (but it wasn’t always like
that). There is a reason for that: it is &lt;strong&gt;the antithesis of working in the
open&lt;/strong&gt;. What happens in Slack stays in Slack. What stays in Slack is basically
lost forever. “Chat apps” aren’t the right tools for decision-making, especially
when working with external contributors and distributed teams across the globe.&lt;/p&gt;

&lt;p&gt;I understand the need for synchronous communication, but (1) we have Matrix at
Mozilla, which is open at least, and (2) we should not use Slack for
asynchronous communication. Let’s just use it for quick feedback, instant chats
about sensitive topics, GIFs, and emojis on every other message. Jokes aside,
it’s easier to restrict some content than to publish private content more
broadly.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://wiki.mozilla.org/Working_open&quot;&gt;Working in the open&lt;/a&gt; is what makes Firefox and other Mozilla
products so special: anyone can contribute. Each individual can find information
about a decision on GitHub or Bugzilla. I personally dig into old GitHub issues
at least once a week, usually with a question in mind like “why did we do
that?”. Back then, everything was either relatively well documented on
GitHub/Bugzilla or captured in broadly accessible Google Docs, which makes it
possible to answer my question. Nowadays, it’s not uncommon for me to “request
access” to some docs I have to read for my own work…&lt;/p&gt;

&lt;p&gt;We should continue to use open and accessible platforms to capture not only the
decisions but also the “why” (context), and keep them available for the future.
Not only will this be useful to us, but it will also allow our contributors to
participate even more and feel more “in the loop”.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: this article reflects my experience within my team at Mozilla, but the
views expressed may be relevant beyond that context.&lt;/em&gt;&lt;/p&gt;

</content>
    </entry>
    
    <entry>
        <title>I got a promotion!</title>
        <link href="https://williamdurand.fr/2021/02/26/i-got-a-promotion/"/>
        <updated>2021-02-26T00:00:00+00:00</updated>
        <id>https://williamdurand.fr/2021/02/26/i-got-a-promotion</id>
        <content type="html">&lt;p&gt;Long story short, I have been promoted to &lt;strong&gt;Staff Software Engineer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Julia Evans explains &lt;a href=&quot;https://jvns.ca/blog/senior-engineer/&quot;&gt;what a senior engineer’s job is&lt;/a&gt; and her blog post
describes my role well enough, which is why I won’t go into details here.
Instead, I chose to write a more personal “status update”.&lt;/p&gt;

&lt;p&gt;First of all, Mozilla has a great [career path for engineers]&lt;sup id=&quot;fnref:7&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:7&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, which doesn’t
force folks who like to code to become managers, a very common practice in
French companies (and maybe elsewhere, ugh!). It’s such a relief!&lt;/p&gt;

&lt;p&gt;Second, this new title won’t change my day to day work right now: I have been
promoted because I was already doing some of the job of a staff engineer and I
likely proved that I was a good fit for this role. I still have many new things
to learn, though, and that’s very exciting!&lt;/p&gt;

&lt;h2 id=&quot;3615-my-life&quot;&gt;3615 My Life&lt;/h2&gt;

&lt;p&gt;I joined Mozilla as a frontend developer. I exclusively worked on the AMO
frontend in 2018 and eventually became &lt;a href=&quot;https://github.com/mozilla/addons-frontend/graphs/contributors&quot;&gt;a major contributor&lt;/a&gt;. During this
time, I started to maintain some side-projects (eslint config/plugin). After a
year, I decided to become more proficient with python so I started to contribute
to our main backend/API project. This allowed me to work on much bigger features
by myself, and I learned a lot more about add-ons and the AMO platform.&lt;/p&gt;

&lt;p&gt;In 2019, my main focus was on hardening the AMO platform, a topic that is
unfortunately confidential. This work started as a research-y project because we
didn’t really know what we could come up with. I chose to use what I learned
during &lt;a href=&quot;/2016/05/16/phd-check/&quot;&gt;my PhD&lt;/a&gt;: I studied the “state of the art”. After that, I built several
prototypes and presented the results of my initial work to different people, got
feedback, iterated, and eventually proposed a plan to move forward. Some
prototypes became “production-ready” and are now running in production while
others have been shelved.&lt;/p&gt;

&lt;p&gt;During this period, I also started a collaboration between a Machine Learning
(ML) team and my own team. We wanted to give ML a try but we didn’t know exactly
how. I looked into that on my own first! I wanted to be able to ask good
questions and, to me, it was necessary to be more familiar with ML and have an
idea of how things should be designed. I played with scikit-learn and Jupyter to
have some preliminary results that I shared with the ML team along with a lot of
questions to ask. I don’t know if that was the “right” thing to do but it worked
and the collaboration is still on-going.&lt;/p&gt;

&lt;p&gt;In 2020, I worked on various projects between my parental leave and the rounds
of layoffs… I started to contribute to Firefox (more on that later) and I
adopted a few more projects that needed some maintenance. I also realized that I
could bridge the gap between the AMO and WebExtensions (Firefox) teams, so I
tried (and continues) to do that.&lt;/p&gt;

&lt;p&gt;I didn’t really have any goal in mind when I joined Mozilla (except not being
fired because I was a fraud, maybe). Over time, I started to look into new
topics because I needed to learn something new and things in front of me were
interesting. I feel lucky to have been assigned to this security topic back in
2019, it had a huge impact on my career because I could show what I was able to
do. I chose not to be too specialized because that’s not who I am anyway (I suck
at being good at one thing so I try to be average on many things instead). I
think that works well.&lt;/p&gt;

&lt;p&gt;I wouldn’t be there without my amazing colleagues in the Add-ons team. Thanks to
all of you! A special note to my current manager (who hired me too): you were
already on my “list” of people who largely influenced my career and therefore my
life, and you continue to have an immense positive impact. I’ll be forever
grateful, thank-you.&lt;/p&gt;

&lt;p&gt;Last but not least, I couldn’t end this section without mentioning my partner.
She’s been very supportive and did an amazing job at taking care of our little
one while I was at work last year &amp;lt;3&lt;/p&gt;

&lt;p&gt;This now sounds like an Oscar speech so let’s talk about something else.&lt;/p&gt;

&lt;h2 id=&quot;in-other-news&quot;&gt;In other news&lt;/h2&gt;

&lt;p&gt;The Firefox codebase was (and still is) kinda scary to me. This is one of those
&lt;em&gt;things&lt;/em&gt; where I thought I could never contribute to it. That’s a huge project,
with a lot of users (I know what you’re thinking!), and developed by many
contributors every day. Thanks to &lt;a href=&quot;/2019/12/20/sigcont/&quot;&gt;my amazing self-confidence&lt;/a&gt; (follow the
link if you don’t get the irony), I decided to contribute to Firefox roughly &lt;a href=&quot;/2020/05/01/moziversary-2/&quot;&gt;a
year ago&lt;/a&gt;, and this became my personal development goal for the rest of the
year. I landed trivial patches and made all the possible mistakes. I learned a
lot with Rob and then Luca.&lt;/p&gt;

&lt;p&gt;In Q3 2020, I worked on &lt;a href=&quot;https://blog.mozilla.org/addons/2020/06/10/improvements-to-statistics-processing-on-amo/&quot;&gt;new AMO statistics&lt;/a&gt; for add-on developers, which
involved various components&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; and required some Firefox changes. I was able to
land some patches in Firefox in order to support the rest of my work. That was
really cool because I worked on ALL the building blocks.&lt;/p&gt;

&lt;p&gt;Last month, I got &lt;a href=&quot;https://www.mozilla.org/en-US/about/governance/policies/commit/access-policy/&quot;&gt;Commit Access Level 3&lt;/a&gt; on Firefox! It’s rewarding because
it means I earned the trust of my peers.&lt;/p&gt;

&lt;p&gt;I am so happy!&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:7&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;This used to be a link to a &lt;a href=&quot;https://twitter.com/Gankra_/status/1046438955439271936&quot;&gt;tweet from @Gankra_&lt;/a&gt;:&lt;/p&gt;
      &lt;blockquote class=&quot;footnote-tweet&quot;&gt;
        &lt;p&gt;i really like that mozilla has an engineer track that just tries to
capture the depth/responsibility of the tasks you’re currently tackling,
and doesn’t necessarily involve moving on to management roles&lt;/p&gt;

        &lt;p&gt;[screenshot of a spreadsheet with the Mozilla’s career ladder]&lt;/p&gt;
      &lt;/blockquote&gt;
      &lt;p&gt;&lt;a href=&quot;#fnref:7&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;I was working on a project involving some frontend work and a lot of
  backend changes for AMO. I also had to prototype the ETL queries and
  implemented a feature to collect data I needed in Firefox. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</content>
    </entry>
    
    <entry>
        <title>Feature flags in real life</title>
        <link href="https://williamdurand.fr/2020/09/22/feature-flags-in-real-life/"/>
        <updated>2020-09-22T00:00:00+00:00</updated>
        <id>https://williamdurand.fr/2020/09/22/feature-flags-in-real-life</id>
        <content type="html">&lt;p&gt;Many folks are familiar with the concept of &lt;a href=&quot;https://martinfowler.com/articles/feature-toggles.html&quot;&gt;feature
toggles&lt;/a&gt; (also known as
&lt;em&gt;feature flags&lt;/em&gt;) but they do not necessarily use them because &amp;lt;insert reason
here&amp;gt;. This is a very powerful technique that allows teams to ship new
features and/or experiments in a controlled way. My team uses different flavors
of feature toggles on the &lt;a href=&quot;https://addons.mozilla.org&quot;&gt;AMO&lt;/a&gt; platform, and that
is what I am going to describe in this article.&lt;/p&gt;

&lt;h2 id=&quot;backend-toggles&quot;&gt;Backend toggles&lt;/h2&gt;

&lt;p&gt;The AMO server-side is mainly powered by a Django application and we are using
&lt;a href=&quot;https://waffle.readthedocs.io/&quot;&gt;Waffle&lt;/a&gt; to implement the different feature
toggles. Waffle has three types of feature flippers: &lt;em&gt;flags&lt;/em&gt;, &lt;em&gt;switches&lt;/em&gt; and
&lt;em&gt;samples&lt;/em&gt;, depending on the needs. I am not very familiar with the last one,
which seems to be a better packaged version of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rand()&lt;/code&gt;, so I’ll only introduce
the first two flippers.&lt;/p&gt;

&lt;h3 id=&quot;flags&quot;&gt;Flags&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://waffle.readthedocs.io/en/stable/types/flag.html&quot;&gt;Flags&lt;/a&gt; are probably
what most people have in mind when thinking about feature toggles. They are
convenient to roll out features according to various conditions, like specific
users or percentage of traffic.&lt;/p&gt;

&lt;p&gt;My team uses flags to progressively enable new features in production. This can
be useful when the feature can only be fully tested in production, e.g., because
it is not possible to set up a realistic (enough) environment or it has privacy
implications. Flags can certainly be used for other purposes but I am mainly
familiar with these ones.&lt;/p&gt;

&lt;p&gt;This is how I shipped the &lt;a href=&quot;https://blog.mozilla.org/addons/2020/06/10/improvements-to-statistics-processing-on-amo/&quot;&gt;new usage statistics on
AMO&lt;/a&gt;
to end users earlier this year for instance. That was handy to iterate quickly
and give early access to &lt;a href=&quot;https://en.wikipedia.org/wiki/Quality_assurance&quot;&gt;Quality
Assurance&lt;/a&gt; (QA) folks,
Project/Product Managers (PMs), and key users (in this case, developers of very
popular add-ons to measure the performance impacts). Later, we updated the flag
configuration to perform a rollout (25/50/75/100%). During this rollout, users
got access to a “beta mode” (the new feature I was working on) in addition to
the legacy feature but it does not have to be this way.&lt;/p&gt;

&lt;p&gt;It is also possible to use a toggle to change a feature entirely for everyone,
and that is the strategy I used for the &lt;a href=&quot;https://blog.mozilla.org/addons/2020/09/17/download-statistics-update/&quot;&gt;download stats on
AMO&lt;/a&gt;
lately. This is useful to preview a feature without risking a production
incident!&lt;/p&gt;

&lt;h3 id=&quot;switches&quot;&gt;Switches&lt;/h3&gt;

&lt;p&gt;Being able to turn a feature on and off for everyone in production can also be
achieved by a
&lt;a href=&quot;https://waffle.readthedocs.io/en/stable/types/switch.html&quot;&gt;switch&lt;/a&gt;. Switches
cannot target specific users or things like that, but it is what we use the most
on AMO.&lt;/p&gt;

&lt;p&gt;For example, we have switches that act as &lt;a href=&quot;https://en.wikipedia.org/wiki/Kill_switch&quot;&gt;emergency
switches&lt;/a&gt; to quickly react to
potential outages in production. Our kinda monolithic server-side application
talks to some smaller services and if one of them goes crazy, we can quickly
shunt it so that it does not take the entire platform down.&lt;/p&gt;

&lt;p&gt;We also use switches to change parts of our application that run in the
background like cron jobs or asynchronous tasks. In the case of the new AMO
statistics, I used switches to change the data source of the tasks that compute
particular values (e.g., average daily users, etc.). After having tested the new
behavior in our non-production environments, we turned the switches on in
production at a given time and we monitored the first executions.&lt;/p&gt;

&lt;p&gt;Similar to flags, switches are great to ship big features incrementally and
allow long periods of tests in non-production environments. That way, we can
detect and fix most issues early, preventing disasters when we go “live”.&lt;/p&gt;

&lt;h2 id=&quot;frontend-toggles&quot;&gt;Frontend toggles&lt;/h2&gt;

&lt;p&gt;We do not have the exact same concept in our main frontend application, but we
do have some sort of client-side feature toggles. We came up with &lt;a href=&quot;https://github.com/mozilla/addons-frontend/issues/6362&quot;&gt;a
convention&lt;/a&gt; to implement
switches on top of &lt;a href=&quot;https://github.com/lorenwest/node-config&quot;&gt;node-config&lt;/a&gt; and
&lt;a href=&quot;https://github.com/mozilla/addons-frontend/blob/79b846383e639f51f6e78d989348c057e2bad203/src/core/client/config.js&quot;&gt;our very own client-side
implementation&lt;/a&gt;
for it. We use frontend switches quite often so that QA can verify the changes
before they are deployed in production. In addition to that, we can start
conversations with PMs and &lt;a href=&quot;https://en.wikipedia.org/wiki/User_experience&quot;&gt;User
eXperience&lt;/a&gt; (UX) people while we
are implementing the changes.&lt;/p&gt;

&lt;p&gt;Our feature flipper implementation may appear naive, it works great for us. We
shipped new pages, homepage redesigns, and other minor features behind such
switches. That being said, this approach is not as flexible as its server
equivalent because it requires a deployment to update the values of the
switches.&lt;/p&gt;

&lt;h2 id=&quot;how-do-we-test-our-code&quot;&gt;How do we test our code?&lt;/h2&gt;

&lt;p&gt;Django Waffle stores its configuration in the database and provides &lt;a href=&quot;https://waffle.readthedocs.io/en/stable/testing/automated.html&quot;&gt;helper
functions&lt;/a&gt; to
create flags or switches in a test case. We usually write similar tests with the
feature toggle enabled and disabled.&lt;/p&gt;

&lt;p&gt;Most of our frontend code is written with React. We use a pattern that consists
in passing a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_config&lt;/code&gt; prop whose default value is the actual node config and we
override it in the test case with a fake config object. That way, we can unit
test all possible conditions:&lt;/p&gt;

&lt;div class=&quot;language-jsx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Welcome&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;Hello, &lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_config&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;enableFeatureXYZ&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;XYZ&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;World&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// test file&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;renders Hello, World when the XYZ feature is disabled&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;getFakeConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;enableFeatureXYZ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;renderWelcome&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_config&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toHaveText&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Hello, World&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;renders Hello, XYZ when the XYZ feature is enabled&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;getFakeConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;enableFeatureXYZ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;renderWelcome&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_config&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toHaveText&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Hello, XYZ&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When adding a new behavior behind a toggle to an existing feature, we usually
update the test suite to work as before and we add new test cases for the new
behavior. This often implies the addition of very similar test cases but it is
not so bad as we always plan to delete some code later on.&lt;/p&gt;

&lt;h2 id=&quot;a-note-on-code-quality&quot;&gt;A note on code quality&lt;/h2&gt;

&lt;p&gt;Every time we introduce a Waffle flag, a switch or a frontend toggle, we file a
GitHub issue to clean up the code once there is no need for it anymore. If the
author forgets about it, this is usually raised during the code review. This is
how we mitigate the risk of having &lt;a href=&quot;https://en.wikipedia.org/wiki/Spaghetti_code&quot;&gt;spaghetti
code&lt;/a&gt;. Some toggles (like
emergency switches) are more permanent, though.&lt;/p&gt;

&lt;p&gt;In the server codebase, we delete the Waffle flag or switch using a database
migration, then we remove the old code (including the toggle) and we update the
test suite accordingly.&lt;/p&gt;

&lt;h2 id=&quot;bonus-amo-info&quot;&gt;Bonus: amo-info&lt;/h2&gt;

&lt;p&gt;I created a &lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/amo-info/?utm_source=williamdurand.fr&amp;amp;utm_medium=referral&amp;amp;utm_content=featureflags&quot;&gt;Firefox extension called
“amo-info”&lt;/a&gt;
to display various information about the public-facing part of the AMO platform.
Among other things, this extension shows the configuration of our frontend
toggles to quickly see which features are enabled/disabled in our different
environments:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/2020/09/amo-info.png&quot; alt=&quot;Screenshot of the amo-info Firefox extension&quot; /&gt;&lt;/p&gt;

&lt;p&gt;That’s it for today :-) Are you using feature toggles too? I’d be interested in
knowing how you manage them and what you do differently than us. Don’t
hesitate to get in touch!&lt;/p&gt;
</content>
    </entry>
    
    <entry>
        <title>Moziversary #2</title>
        <link href="https://williamdurand.fr/2020/05/01/moziversary-2/"/>
        <updated>2020-05-01T00:00:00+00:00</updated>
        <id>https://williamdurand.fr/2020/05/01/moziversary-2</id>
        <content type="html">&lt;p&gt;&lt;em&gt;Today is my second Moziversary. I joined Mozilla as a full-time employee on May
1st, 2018, not too long after contracting with them via my previous company.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I am part of the Firefox Add-ons team and I work on
&lt;a href=&quot;https://addons.mozilla.org/&quot;&gt;AMO&lt;/a&gt;, which is much more than “just a website”. I
spent 2019 working on the &lt;a href=&quot;https://github.com/mozilla/addons-server/&quot;&gt;server
stack&lt;/a&gt; as well as creating and
deploying new security tools to cope with malicious activities. Everyone seems
happy with my work, I received positive feedback from my peers and manager and I
even “over-performed” last year. In 2020, I started to work on the Firefox
codebase and that’s exciting!&lt;/p&gt;

&lt;p&gt;Now, if I ask you to name the first thing about your current employer when you
think about it, what would it be? For me, and that might sound dumb but it is
the truth, my first thought is “Mozilla Firefox”, that piece of software I
installed on every computer I could when I was 16-17 years old because “it was
much faster than Internet Explorer” and… free. That was in the early 2000s.&lt;/p&gt;

&lt;p&gt;My father was working for the main telecommunications company in France back
then. Once my parents could afford a personal computer at home in the late 1990s
(an &lt;a href=&quot;https://en.wikipedia.org/wiki/IBM_Aptiva&quot;&gt;IBM Aptiva&lt;/a&gt; &amp;lt;3), we were able to
get &lt;a href=&quot;https://www.youtube.com/watch?v=gsNaR6FRuO0&quot;&gt;56k Internet&lt;/a&gt;, then 128k
(&lt;a href=&quot;https://en.wikipedia.org/wiki/Integrated_Services_Digital_Network&quot;&gt;ISDN&lt;/a&gt;) and
later DSL. That’s how I met the Internet but it took me a few more years and bad
grades in high school to grow an interest in computers.&lt;/p&gt;

&lt;p&gt;I never imagined that I could work for a company whose icon was sitting on the
Windows 98 Desktop of my parents’ computer one day. And yet, here I am, and
that’s why Mozilla is and will always be special to me. It’s an immense part of
my teenager memories, it reminds me where I come from (including my privilege).&lt;/p&gt;

&lt;p&gt;Contrary to many of my colleagues, I wasn’t a
&lt;a href=&quot;https://www.mozilla.org/en-US/contribute/&quot;&gt;volunteer&lt;/a&gt; before joining Mozilla
and I knew little to nothing about Mozilla Corporation. I was following some of
the Mozilla Foundation initiatives but I wasn’t a
&lt;a href=&quot;https://mozillians.org&quot;&gt;Mozillian&lt;/a&gt;. I fixed that since then ;-)&lt;/p&gt;

&lt;p&gt;I am grateful to my current manager (who hired me) as well as all my colleagues
in the Add-ons team and beyond. They are all amazing folks! I learned tons of
things about everything, including myself, and these two years have been
absolutely fantastic. Thanks y’all!&lt;/p&gt;
</content>
    </entry>
    
</feed>
