Distribution of software is a critical problem any software company has to solve for. For SaaS companies, there’s conveniently not much to it these days. At CoApp, we have a relatively interesting, complex ecosystem of software that has to be secured for distribution for in the cloud, in confidential environments, and on-premise. You could consider our initial implementation of the CoApp Browser Extension to be naive, in that we heavily relied on the Chrome Web Store and Edge Stores for distribution. They work great for what they are but have ultimately introduced a ton of complexity into our lives and have created barriers for us to get the latest CoApp software to our customers. For B2C implementations, these web stores are not necessarily relevant, in my opinion.

  • We have to follow the web store rules and guidelines (not that we necessarily want to break them, but we’re not serving individual consumers, the model is simply different!).
  • We are held hostage by their strange review cycles that appear to be vastly inconsistent in terms of what they review and host
  • We are also held hostage by review times. This is the biggest issue, in terms of distribution, as we can’t easily plan for major releases – particularly between Edge and Chrome.

In addition to the Web Stores simply not meeting our business needs, ensuring workstations are always operating with the latest CoApp extensions has become difficult. We’ve found IT groups implement group policies in different ways and depending on the usage of the computer itself, it’s easy for some computers to fall behind.

 

Why does this matter?

For our customers, security and reliability are not negotiable. An outdated browser extension could:

  • Introduce vulnerabilities

  • Break integrations with critical point-of-sale or practice management systems

  • Fail compliance audits

By ensuring that updates are detected and installed immediately, CoApp delivers an extension platform that is:

  • Secure — New patches are applied as soon as they’re released

  • Reliable — Bugs are fixed rapidly without user intervention

  • Compliant — Version control is provable and auditable

 

Solution

We’re super excited to finally have rolled out our solution to these distribution woes and I’d like to share how we dealt with forcing extensions to update from our own hosted extension store. This has essentially guaranteed us the ability to ensure workstations always have the latest and greatest without relying on unknown timeframes from Chrome and Edge.

Self Hosting

We now host all versions of our own chromium extensions within our cloud. In order to accomplish this, we maintain our own App ID and publish it in an XML file that IT groups can reference in their group policies.

 

Example Update File:

<gupdatexmlns=”http://www.google.com/update2/responseprotocol=”2.0>
<appappid=”123123123123myappid>
<updatecheckcodebase=”https://mydomain.com/ext/env/env-1.2.3.crxversion=”1.2.3/>
</app>
</gupdate>
Example Group Policy (for a Mac)
<?xml version=”1.0″ encoding=”UTF-8″?>
<!DOCTYPE plist PUBLIC “-//Apple//DTD PLIST 1.0//EN” “http://www.apple.com/DTDs/PropertyList-1.0.dtd”>
<plist version=”1.0″>
<dict> <key>ExtensionInstallForcelist</key>
<array> <string>123123123123myappid;https://mydomain.com/ext/my-update-file.xml</string> </array>
</dict>
</plist>
Updates to the manifest file – mandatory for extensions to continue to update properly
“update_url”: “https://mydomain.com/ext/my-update-file.xml”,

Forcing Timely Extension Updates

Self hosting solved our first distribution woe but forcing updates quickly was the next hurdle we’re super excited to have solved. Chrome exposes a RequestUpdateCheck that will “check” for new updates available (based on your update_url) and, misleadingly, download the new CRX behind the scenes. When the Browser eventually reloads, the new Extension will be installed. RequestUpdateCheck cannot be pinged regularly, in fact, we found that more than 1-2 times within a few hours will result in chromium throttling the browser – this meant we couldn’t just keep checking for updates, even though we’re self hosting. What we do is manage updates via CoApp, as a result, and resort to Chrome only when we definitely have an update to download.

 

  • We leverage Chrome’s alarms API to schedule regular update checks

chrome.alarms.create(‘checkForExtensionUpdate’, { periodInMinutes: 1 });

 

  • Smart Version Comparison along with handling if an update is in progress OR if we’ve been throttled:

get extensionUpdateInProgress

if extensionUpdateInProgress === true break

get extensionUpdateRetryBackoff

if extensionUpdateRetryBackoff > Date.now() break

 

set extensionUpdateInProgress = true

currentVersion = chrome.runtime.getManifest().version

targetVersion = getCoAppLatestVersion (this reads from our update.xml, essentially)

 

if (currentVersion !== targetVersion && currentVersion < targetVersion)

call RequestUpdateCheck

 

if status = update_available

wait 60 seconds

 

chrome.runtime.reload

 

if status = no_update_available

some kind of problem on coapp’s side

 

if status = throttled

extensionUpdateRetryBackoff = 24 hours

 

  • Pick up pending updates in the case of failure
// this actually does not occur on reload but is helpful if the browser is closed and reopened
chrome.runtime.onStartup.addListener(async () => {
check_for_pending_updates
});
check_for_pending_updates

Additional CoApp Extension Features

  • We’ve built enterprise-grade logging into our CoApp Extension so that we have full visibility over our distribution woes and successes.