Maximizing Extension Functionality: A Guide to Ensuring Stability during Updates

Nischal Goyal
WhatfixEngineeringBlog
6 min readFeb 24, 2023

Introduction

In this technical blog, we will delve into the issue of maintaining extension stability during updates in Chrome. As developers, we know that creating and deploying an extension is only half the battle. Keeping it updated and functional for users is a continuous challenge. One of the most prevalent issues that developers face is ensuring a stable connection between the content script and background script after an extension update, which can lead to broken functionality and a poor user experience for users. We will explore the common pitfalls of chrome extension updates, the reasons behind them, and strategies to avoid them. We will examine various methods and techniques that can be used to prevent these issues and ensure a smooth update process for both the developer and the user. Additionally, we will discuss the different permissions required for these methods and the best practices to follow while implementing them. By the end of this blog, you will better understand how to maintain your extensions' stability during updates.

Messaging Between Content and Background Script

Message passing is a technique used in chrome extensions to communicate between the different scripts that make up the extension. The content script is responsible for interacting with the web page and the background script is responsible for handling the logic and functionality of the extension. In order to communicate, the scripts send messages to each other using the “chrome.runtime.sendMessage()” and “chrome.runtime.onMessage.addListener()” methods.

//content.js
chrome.runtime.sendMessage({greeting: “hello”}, function(response) {
console.log(response.farewell);
});
//background.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log(request.greeting);
sendResponse({farewell: “goodbye”});
}
);

In this example, the content script sends a message with the greeting “hello” to the background script. The background script receives the message and logs the greeting to the console. The background script sends a response message with the farewell “goodbye” to the content script, which logs the farewell to the console.

During an extension update, the above communication between the content script and the background script will break. This can happen because the extension is loaded into memory before the update, and the new version of the extension is loaded after the update. This can cause the old version of the content script to communicate with the new version of the background script, leading to broken functionality.

To understand this better, let’s take an example of an extension that allows users to highlight text on a web page and save it to a list. The content script listens for the user to select text and sends a message to the background script with the selected text. The background script then adds the selected text to a list and sends an acknowledgment back to the content script to highlight the selected text. However, during an extension update, if the message passing API changes or the background script is reloaded, this connection can be lost, causing the extension to stop working properly and the selected text would not be highlighted.

The diagram on the left illustrates the standard communication process, while the diagram on the right represents the communication process after the extension update.

Maintaining Communication during Updates: A Comparison of Approaches

For maintaining communication between a background script and a content script in a Chrome extension, there are two main approaches: long connections and re-establishing connections. Long connections use APIs like “chrome.runtime.onConnect” or “chrome.alarms” to keep a continuous link between the scripts, but they may not work during updates. Re-establishing connections involve methods to reconnect the scripts after a disconnection has occurred. One example of this is the “chrome.tabs.executeScript” API, which allows the background script to inject a new content script into a tab.

chrome.tabs.executeScript

We decided to use the chrome.tabs.executeScript method for maintaining communication between the content script and background script during updates. This method allows the background script to directly execute a script in the context of the current page, allowing for a more direct and efficient way to communicate with the content script.

One of the main advantages of using chrome.tabs.executeScript is that it allows for more precise control over the communication between the scripts. Unlike the chrome.runtime.onConnect and chrome.alarms() methods, which rely on establishing and maintaining a connection, the chrome.tabs.executeScript method allows the background script to directly execute a script in the context of the current page. This can be useful for applications that need to exchange information frequently and with low latency.

Another advantage of the chrome.tabs.executeScript method is that it can be used in conjunction with the “chrome.runtime.onInstalled” event. This event is triggered when the extension is first installed or when it is updated, allowing the background script to check for updates and take appropriate action. Using chrome.tabs.executeScript in combination with the chrome.runtime.onInstalled event allows for seamless communication between the content script and background script, even during updates. This is because the background script can detect the update and re-inject the content script using chrome.tabs.executeScript, ensuring that the communication between the two scripts is not disrupted.

Here is an example of the code used to implement this approach:

chrome.runtime.onInstalled.addListener(function (details) {
if (details.reason === “install” || details.reason === “update”) {
chrome.tabs.executeScript(tab.id, {file: “content_script.js”});
}
});

In this example, the background script is listening for the chrome.runtime.onInstalled event and, when triggered, checks the reason for the event. If the reason is “install” or “update”, the script then uses the chrome.tabs.executeScript method to re-inject the content script. This approach allows for seamless communication between the content script and background script, even during updates.

Adding New Permissions to an Extension: Prerequisites, Challenges, and Best Practices

In order to use certain features of the chrome extension API such as chrome.tabs.executeScript(), certain permissions must be added to the extension’s manifest file. In this case, the “tabs” and “scripting” permissions must be added to the manifest file. This can be done by including the following in the “permissions” field of the manifest file:

{
"name": "My Extension",
"version": "1.0",
"permissions": [
"tabs",
"scripting"
],
...
}

However, adding new permissions to an existing extension can be a challenging task, as it has the potential to disable the extension for the users. When an extension updates and includes new permissions, Chrome will automatically disable the extension and prompt the user to review and accept the new permissions. Additionally, when submitting an update to the Chrome Web Store that includes new permissions, additional justification for the new permissions may be required.

To avoid this, it’s a best practice to implement a phased roll-out strategy. This involves releasing the updated extension to a small percentage of users initially, and gradually increasing the percentage as the extension is deemed stable. This allows for quick identification and resolution of any issues that may arise from the new permissions. This way, your users will not be affected by the new permissions, and you will be able to fix the issues with the new permissions before rolling it out to all the users.

Another best practice is to clearly communicate the need for the new permissions to the users, and provide justification for why they are necessary. This can be done through in-app messaging, email, or other communication channels. This will help your users understand why the new permissions are necessary, and why it is important that they accept them.

Lastly, it’s always a good idea to keep a backup of the previous version of the extension in case of any issues arise so that it can be quickly rolled back. This will give you the flexibility to quickly fix any issues that may arise with the new permissions, and restore the extension to its previous working state.

In conclusion, adding new permissions to an existing chrome extension can be a challenging task, but by following best practices such as implementing a phased roll-out strategy, clearly communicating the need for the new permissions, and keeping a backup of the previous version of the extension, the process can be made more manageable.

Wrapping Up: Implementing Best Practices for Extension Stability

In conclusion, ensuring extension stability during updates is a crucial aspect of developing and maintaining a successful browser extension. By effectively messaging between content and background scripts and maintaining communication during updates, developers can ensure that their extensions continue to function seamlessly for users. Additionally, understanding the prerequisites, challenges, and best practices for adding new permissions to an extension can help developers to make informed decisions and avoid common pitfalls. Overall, following the guidelines outlined in this comprehensive guide can help developers to create stable and reliable extensions that users can rely on. As a developer, it’s our responsibility to ensure that the extensions we build are robust and user-friendly. By following best practices and staying up-to-date with the latest developments in browser extension development, we can provide our users with the best possible experience.

--

--