Building a Chrome Extension using Flutter

Souvik Biswas
Flutter Community
Published in
9 min readMay 20, 2022

Flutter is out there in the wild for quite a while and has got a pretty amazing response from the community since the initial Flutter 1.0 launch on Dec 4th, 2018.

If you are here, you probably already know about Flutter — a cross-platform framework introduced by Google that is capable of running on Android, iOS, Web, macOS, Linux, Windows, and a few more kinds of devices.

With the introduction of Flutter 3.0, stable support has arrived on macOS and Linux platforms as well. So, now Flutter can be called a truly adaptive and multiplatform framework with stable support for Android, iOS, Web, macOS, Linux, and Windows — which is just amazing! 🥳

But wait… what about those “few more kinds of devices”?

These include various well-known IoT devices (Raspberry Pi and Arduino), smartwatches (Apple Watch and Google’s WearOS devices), VR headsets (Meta Quest 2), gaming consoles (Xbox), and also a few more unique ways to run a Flutter app.

Flutter is still being tested on these platforms (and hoping soon there would be stable releases on them) — if you wanna have a look at how you can use Flutter to interact with IoT devices, check out this article written by me:

Today, we will explore a unique way to run a Flutter app as a chrome extension — trust me it’s really easy 😁.

TL;DR: You can just generate a Flutter web build using the HTML renderer with --csp flag, and you are good to use it as a chrome extension.

For more information, follow along.

Before we dive deeper into building the extension, let’s have an overview of chrome extensions in general.

What’s a Chrome extension?

Extensions are lightweight software programs that can be installed in the browser. They are easily accessible inside the browser and help in enhancing the experience of the user.

You can check out and install any extension from the Chrome Web Store, there’s a variety of extensions available like productivity tools, shopping, fun games, etc.

Extensions are very similar to web apps as they use the same core technologies such as HTML, JavaScript, and CSS. But they run in a separate sandboxed execution environment.

Overview of the extension

Just to give you some context, today we would be building a QR code generator extension using Flutter.

Using this extension, you can easily generate a QR code by providing a text or URL. The color of the QR code will be customizable, you will be able to modify both the QR code's foreground and background colors.

Exploring basic Flutter project

Let’s get started by creating a new Flutter project.

You can use exactly the same Flutter command that’s used for creating any basic Flutter project:

flutter create qr_code_extension

Here, qr_code_extension is the name of the Flutter project. FYI, I’m currently on Flutter version 3.0.

Once the project is created, open it using your favorite IDE. I will be using VS Code, if you have its CLI setup, just run the following command to open the project:

code qr_code_extension

If you are familiar with Flutter, then you already know that the generated project is the demo counter app (the code’s present in lib/main.dart file).

Before proceeding further, test the demo Flutter app by running on Chrome (you can test on any browser but as we’ll be building a chrome extension, so anyways you need to have Chrome installed on your system).

If you are inside VS Code, just select Chrome as the target platform (from the bottom bar) and press “fn + F5” to build and launch the app. Otherwise, you can use the following command to run the app on Chrome:

flutter run -d Chrome

This will launch the counter app on the Chrome browser:

You can quit the running app, either by clicking the stop button of your IDE or by typing “q” inside the terminal from where you had launched the app.

Modifying to run as an extension

Now, coming to the most important section — how can you run this basic Flutter web app as a chrome extension? 🤔

Just three steps…

1. Remove non-supported scripts from index.html

Navigate to web/index.html file and remove all the <script>..</script> tags:

Then only insert the following <script> tag inside the <body>:

<script src="main.dart.js" type="application/javascript"></script>

2. Set the extension view dimensions

Extensions have a fixed dimension, so you need to explicitly specify the width and height values of the extension view inside the HTML.

Just replace the starting <html> tag with the following:

<html style="height: 600px; width: 350px">

This will set the extension view’s height and width to 600 pixels and 350 pixels respectively.

3. Make some changes in manifest.json

Navigate to web/manifest.json file and replace the entire content with the following:

{
"name": "QR Code Extension",
"description": "QR Code Extension",
"version": "1.0.0",
"content_security_policy": {
"extension_pages": "script-src 'self' ; object-src 'self'"
},
"action": {
"default_popup": "index.html",
"default_icon": "icons/Icon-192.png"
},
"manifest_version": 3
}

Trying out the extension

With the required changes done, you are ready to build and run it as a Chrome extension.

By default, when you run a Flutter web build using the following command:

flutter build web

It uses the HTML renderer for a mobile browser and CanvasKit renderer for a desktop browser.

To give a little bit of context, Flutter web has support for two types of renderers (according to the Docs):

HTML renderer

Uses a combination of HTML elements, CSS, Canvas elements, and SVG elements. This renderer has a smaller download size.

CanvasKit renderer

This renderer has faster performance with higher widget density (supports operation on pixel level) but adds about 2MB in download size.

But in order to use it as an extension, you have to specifically generate the build only using the HTML renderer. It can be done using the following command:

flutter build web --web-renderer html

🛑 Don’t run the command yet!

Finally, you have to use the --csp flag in order to disable the dynamic generation of code in the generated output which is necessary to satisfy CSP restrictions.

🟢 RUN this command:

flutter build web --web-renderer html --csp

You will find the generated files inside build/web folder present in your root Flutter project directory.

To install and use this extension, go to this URL from the Chrome browser:

chrome://extensions

This page lists all the Chrome extensions if you have any installed.

1. Enable the Developer mode toggle present in the top-right corner of the webpage.

2. Click Load unpacked.

3. Select the <flutter_project_dir>/build/web folder.

You will see that the new extension is now added to that page.

The extension will get automatically installed, you will be able to access it just like any regular extension by clicking on the extension icon present in the top bar (it can also be pinned for easy access).

Practical implementation

Let’s jump into a practical implementation now and build the QR code generator extension using Flutter.

First of all, go to the main.dart file present inside the lib directory. Replace the entire content of that page with the following:

This is just to simplify the starting point of the app and remove the code related to the demo counter app.

Next, create a new file inside the lib folder named as qr_view.dart. In this file, we would be adding code for building the QR code extension UI and some logic for generating the QR code according to the text present in a TextField.

To render the QR code in the UI, we would be using a Flutter package called qr_flutter. Run the following command from the root Flutter directory to install this package:

flutter pub add qr_flutter

Add the following code to the qr_view.dart file:

In the above code, we have imported the qr_flutter package and have also initialized a few variables for the TextField widget and for getting access to the currently selected background and foreground color of the QR code.

Now, create another file inside the lib directory called color_list.dart and add the list of colors to display as the QR code background and foreground color selection.

Finally, complete the extension’s user interface.

Here’s the complete code of the QRView widget along with the UI of the extension:

Go to the web/index.html file, and change the dimensions defined inside the starting <html> tag to the following:

<html style="height: 350px; width: 650px">

The extension view dimensions have to be defined explicitly, the above dimensions should accommodate the extension UI properly.

With this, you have successfully created a QR code generator extension. Run the same flutter build command for re-generating the Flutter web files:

flutter build web --web-renderer html --csp

Install the extension by following the same steps as we had discussed earlier.

Woohoo! your QR code generator extension is ready to use. 🎉

Limitations

As exciting as it looks, there are certain limitations as well.

The following are some of the limitations that I faced while I was exploring how to build chrome extensions using Flutter (some of these might be fixable, it’s something that requires just more exploration).

1. Restricted to HTML renderer

One more addition that would have made the QR code generator extension even cooler was the addition of a “Save as Image” button. Using this you would have been able to save the generated QR codes as normal image files.

But unfortunately, as extensions don’t support CanvasKit renderer so you can’t use the toImage() method on any RenderRepaintBoundary object (which is required to convert any Flutter widget to an image format).

2. Couldn’t use Firebase (should be possible)

If you remember, initially we modified the index.html file to remove most of the <script> tags. This is to satisfy the Content Security Policy (CSP) rules. Manifest V3 doesn’t support the inline execution of third-party URLs.

BUT I have tried to run an older project which doesn’t use the Dart-only initialization of Firebase in Flutter (most probably that should solve it as you won’t need to define the Firebase plugins inside the<script> tag in that case).

3. Widget state gets lost

This might not be considered a limitation, rather just a point you should keep in mind while building an extension using Flutter. Whenever you click outside the extension view to close it, all your app states would be lost.

You should use a Flutter plugin for storing the state locally, for example, the shared_preferences plugin (it works fine, I’ve already tested it inside the extension).

See you soon

Hope you have found this article interesting.

There are a lot of unique ways in which Flutter can be used, it’s just a matter of time until people figure out the optimized way to run Flutter on them.

Best of luck in your Flutter exploration! 👍

GitHub repo of the QR code generator Chrome extension is available at the following link:

References

You can follow me on Twitter and find some of my projects on GitHub. Also, don’t forget to checkout my Website. Thank you for reading, if you enjoyed the article make sure to show me some love by hitting that clap (👏) button!

Happy coding…

Souvik Biswas

https://twitter.com/FlutterComm

--

--

Souvik Biswas
Flutter Community

Mobile Developer (Android, iOS & Flutter) | Technical Writer (FlutterFlow) | IoT Enthusiast | Avid video game player