Web browsers are the modern operating system. Google’s Chrome OS, an operating system that runs the Chrome Browser exclusively, is now the second most popular desktop operating system. Additionally, the rise of Electron and similar cross-platform frameworks means that many of the applications we use every day (e.g., Slack) are actually browser applications in disguise.
The ubiquity of browsers has cemented their critical role in consumer productivity and self-efficacy. Given this importance, I wanted to learn how browser extensibility has evolved over the years. Since I couldn’t find a complete history, I set out to write my own.
Disclaimer #1: I’m going to gloss over many details to keep this post as non-technical as possible. I won’t, for example, dig into the distinction between a browser and a rendering engine.
Disclaimer #2: If I make any mistakes or omit anything you feel is important, please post in the comments. As I have not personally had much exposure to browsers in non-English-speaking countries, there will undoubtedly be gaps in this post.
In the beginning, there was Tim Berners-Lee’s WorldWideWeb browser (1990). However, Marc Andreessen’s Mosaic (1993) was the first browser to gain mainstream popularity, as it was easy to install, displayed graphics, and provided customer support. Andreessen then went on to launch Netscape, which would battle Internet Explorer (first released in 1995) for dominance in the browser wars of the late ‘90s. The browser wars culminated with Microsoft facing antitrust action over its integration of Internet Explorer and Windows.
The early web only supported static content. Plug-ins — native executables that render dynamic content in the browser — opened the door for multimedia, enterprise applications, and gaming. Internet Explorer supported plug-ins via its ActiveX technology, while other browsers supported NPAPI.
On the consumer side, you basically couldn’t browse the web without installing the Flash (1996) and Java (1998) plug-ins.
As native executables, plug-ins were a chronic source of security vulnerabilities and instability. Despite these problems, it wasn’t until the adoption of the HTML5 standard and modern Web APIs in 2014 that browsers could rid themselves of plug-ins without sacrificing functionality.
Desktop browsers began dropping support for plug-ins in 2015, with Chrome leading the charge. On mobile, iOS (2003) famously did not offer Flash from the outset.
The Flash plug-in has been the longest holdout due to the ubiquity of Flash content. Firefox, for instance, refused to drop support for Flash until the beginning of this year.
With multiple browsers on the market and growing incompatibilities in site rendering, Tim Berners-Lee founded the World Wide Web Consortium (W3C) in 1994 to develop cross-browser standards.
One of these standards was 1996’s Cascading Style Sheets (CSS) specification. CSS defines support for “stylesheets” that tell a browser how to style the content on a page. Stylesheets can come from three different sources:
- Document author: The author of the website
- User: The user of the browser
- User agent: The default style for the user agent (i.e., the browser)
In 1998, Opera 3.5 was the first browser to support CSS and included support for user stylesheets. Internet Explorer followed suit with the release of Internet Explorer 4 in 1999.
In 2005, with the introduction of Jason Barnabe’s Stylish extension, consumer styling began shifting to style manager browser extensions. Compared to user stylesheets, style managers offer more flexible controls, sharing features, and ease of use.
Chrome dropped support for user stylesheets in 2014. Firefox still has support via the
userContent.css stylesheet, but the user stylesheet hasn’t been accessible from the main interface since 2019.
Correction 6/5/2021: Safari still supports a user stylesheet from the Advanced tab in preferences. Here’s a history of custom stylesheets in Safari
For example, here’s a bookmarklet that opens the historical versions of a page in the Internet Archive’s Wayback Machine:
Bookmarklets hit a road bump in 2004 with the introduction of W3C’s Content Security Policy (CSP) specification. Designed to protect sites against malicious user content and third party code, CSP enabled site owners to lock-down code origins and network requests.
However, wanting to main extensibility, the CSP Specification specifies that bookmarklets and other extensibility features should be exempt from CSP restrictions:
Policy enforced on a resource SHOULD NOT interfere with the operation of user-agent features like addons, extensions, or bookmarklets. These kinds of features generally advance the user’s priority over page authors, as espoused in [HTML-DESIGN].
In practice, things are different. In Firefox, bookmarklets are subject to the site’s CSP, preventing bookmarklets from being run on many pages. In Chrome, bookmarklets aren’t subject to the CSP. But, by default, Chrome only shows bookmarks on the New Tabs page; users must configure the bookmarks bar to be shown on web pages.
The modern approach to browser extensibility, browser extensions, kicked off in 1999 when Internet Explorer added support in Internet Explorer 4. The new extensions supported “Explorer Bars” (i.e., the toolbar) and added entries to context menus.
Firefox launched with extension support in 2004, with the other mainstream browsers following suit in 2009–2010. As early as 2005, the “Mozilla Update” page was bustling with activity:
The major browser vendors each maintain their own browser extension marketplace where extensions undergo a security review and updates can be automatically distributed to users.
Unfortunately, because browser extensions have access to a user’s browsing activity, they’re an attractive attack vector for malicious actors.
To curb abuse, Chrome, in particular, has taken steps to restrict how browser extensions are distributed. In 2014, Chrome introduced restrictions so that Windows users could only install extensions from the Chrome Web Store.
Mozilla and Firefox’s user interface was implemented using a language called XUL, the XML User Interface Language. The XUL defines a user interface that is rendered on the fly.
In Firefox, browser extensions could modify the XUL, thus allowing them to change core parts of the user interface (e.g., adding toolbars).
Firefox discontinued XUL for extensions in 2017 because it led to vulnerabilities and instability when multiple extensions modified the UX. Technical users can still make limited modifications to the Firefox interface via its userChrome.css settings file.
The Netscape browser was open-sourced in 1998 and used to build the Mozilla browser suite. Mozilla Firefox, the first mainstream open-source browser, was subsequently released in 2004.
In 2008, Google released the Chromium open-source browser project. Google uses Chromium as the basis for its Chrome web browser. By being open-source, developers can “fork” the browser, modify it, and distribute their own custom versions.
There have been a lot of alternative browsers, many of which have not stood the test of time. Some notable examples include:
- GNU IceWeasel/IceCat (2005–): Firefox distribution without proprietary plug-ins.
- Flock (2005–2011): Browser with integrated social media features. Originally based on Firefox and later based on Chromium. Was purchased by Zynga, a social games company.
- Tor Browser Bundle (2008–): Firefox distribution that makes use of the Tor network for private browsing.
- Microsoft Edge (2019–): Microsoft’s Chromium-based browser after their in-house browser (also called Edge) failed.
Userscripts provide many benefits over bookmarklets: they can run automatically on a page, aren’t subject to length restrictions, and can run outside of a site’s CSP.
The first userscript manager, Greasemonkey, was released for Firefox in 2005. There are now several variations to choose from, including Tampermonkey (2010) and Violentmonkey (2013). These variation all use the same Greasemonkey-style scripts.
In 2019, Firefox added formal support for userscripts in extensions, providing additional security guarantees. Chromium has a separate sandbox feature to run code in isolation, but has no formal userscript support. However, as I will touch on a bit later, the end is nigh for userscripts in Chromium browsers.
Abandoning XUL-based extensions in 2017, Firefox switched to the defacto standard WebExtensions API by and large mimicking Chromium’s API.
Firefox’s shift means that the vast majority of browser extensions are now using the APIs defined by Chrome’s Manifest Version 2, first released way back in 2012 (although additional incremental API functionality has been introduced since then).
Due to its waning market share, Firefox chose to support the
chrome API namespace in addition to the vendor-agnostic
browserAPI namespace. In many cases, Chrome extensions can be ported over to Firefox with no code modifications. Firefox also provides a polyfill for developers to make their vendor-agnostic code compatible with Chrome.
Writing extensions for Safari traditionally involved writing them using Apple’s XCode development tools. Starting with Safari 14 in 2020, Safari also adopted the WebExtensions API.
In January 2021, Chrome released its controversial Manifest Version 3 (V3) of the WebExtensions APIs. “Manifest” refers to both the technical integration points and the policies Chrome enforces when reviewing extensions for its Chrome Web Store.
In line with previous browser API changes, the stated goals of Manifest V3 are security, speed, and reliability. The major changes introduced in Manifest V3 are:
- Making network request modification declarative (speed/security)
- Using service workers for background operations, vs. a persistent background page (reliability)
Manifest V3 is controversial in the browser extension community because it breaks the functionality of many popular extensions.
For the general public, the most worrisome is that popular content and adblockers (e.g., uBlock Origin and Privacy Badger) will no longer be supported. These blockers work by maintaining a large ruleset to block network requests. Such large and dynamic rulesets are not supported in Manifest V3. (To be fair, in response to the outrage, the Chrome team has increased the number of rules per extension.)
Ever since mainstream browsers added support for extensions, the developer community has built an incredible ecosystem of extensions that gives consumers control over their browsing experience:
- Style managers (2005–): Customize style of a page.
- Userscript managers (2005–2022?): Run custom code automatically.
- Content/adblockers (2002–): Block network requests and elements.
- Context menu managers (?–): Add context menu items (e.g., opening a new URL dynamically based on the selected text).
- Web clippers (?–): clip information from a page; customize what’s clipped and where it’s sent.
Despite the number of extensions published (the Chrome Web Store has 189K extensions), there is still a lot of room to innovate. In particular, the pairing of advances in no-code + API-fication with browser extensions has the potential to increase consumer productivity and self-efficacy dramatically.
To realize this vision, I founded PixieBrix. At PixieBrix, we are working to create an open-source browser extension for consumers and companies to customize their browsing experience to fit the way they work. PixieBrix is no/low-code — you configure and combine “bricks” to add missing functionality, integrate sites without APIs, and automate repetitive tasks.
Personally, I’m very excited by the surge of interest in this space. One notable startup I’ve come across is Insight Browser, an iOS browser that allows users to build and share simple extensions. In the enterprise world, Extension.dev is another low-code builder for internal enterprise extensions (check out their comprehensive “What internal extensions are people building?” page).
If you’re interested in working or investing in this space, I’d love to hear from you. Want to follow us on our journey? Follow us on Twitter, star our GitHub repository, or subscribe to our newsletter.