122

How can an extension find out that it is being run for the first time or has just been updated, so that the extension can perform some specific actions? (e.g. open a help page or update settings)

Alvin Wong
  • 12,210
  • 5
  • 51
  • 77
rack1
  • 1,221
  • 2
  • 9
  • 3
  • why you didn't chose this one? http://stackoverflow.com/a/14957674/4548520 it's right anwser - official event for first extension install – user25 Aug 04 '16 at 20:21

4 Answers4

201

In newer versions of Chrome (since Chrome 22), you can use the chrome.runtime.onInstalled event, which is much cleaner.

Example:

// Check whether new version is installed
chrome.runtime.onInstalled.addListener(function(details){
    if(details.reason == "install"){
        console.log("This is a first install!");
    }else if(details.reason == "update"){
        var thisVersion = chrome.runtime.getManifest().version;
        console.log("Updated from " + details.previousVersion + " to " + thisVersion + "!");
    }
});
aderchox
  • 3,163
  • 2
  • 28
  • 37
Alvin Wong
  • 12,210
  • 5
  • 51
  • 77
  • 3
    Thank you for this! All I've found around the Internet is to store the extension's version in localStorage until I eventually stumbled across this answer, which was of course a workable solution, but I was so surprised that chrome didn't have something built-in for this! I'm so glad that I have not been let down :) – JMTyler Sep 11 '13 at 00:38
  • 3
    Since Chrome 22, released in Sep 2012 – Redzarf Dec 12 '13 at 11:44
  • 1
    chrome.runtime.onInstalled detects when the app or extension is installed in the background. What it does not do, however, is detect a first firing of the chrome.app.runtime.onLaunched event... – realkstrawn93 Jan 26 '14 at 01:16
  • 5
    I used this code for a while and it worked great, until my extension requested a new permission on an update (which suspends the extension until the user accepts the permission). When the permission was accepted and the extension was unsuspended, the onInstalled event never fired and thus the update script never ran. Worth mentioning for those who run update scripts onInstalled, you might need to listen for a different event in situations where you have requested a new permission. – Elimn Feb 11 '14 at 20:46
  • 2
    @Elimm seems like Chrome's bug, you should report on the bug tracker. – Alvin Wong Feb 12 '14 at 02:02
  • 1
    There are also spurious update events, but you can detect them with a couple of lines of additional code: https://code.google.com/p/chromium/issues/detail?id=303481 – Roland Pihlakas Dec 28 '14 at 06:38
  • How can I get this to work on an unpacked chrome extension? I added the above code to my background.js but no luck – Janac Meena Apr 03 '16 at 19:09
  • note that you don't see this console msgs .. use alerts for debugging – kofifus Aug 08 '17 at 23:53
  • console.log works, certainly at least for the last few years but you have to open the background page for your extension using the chrome://extensions entry for your extension. – strattonn Jun 05 '21 at 01:35
  • Actually, good old `localStorage` is a better option than `onInstalled`. Because `onInstalled` fires after the top level bg code is finished running and with this event there is no easy way to run code only when the extension was started without being installed. – traxium Feb 13 '22 at 16:30
86

Updated answer to reflect v3 of manifest:

Chromium now has a chrome.runtime set of APIs, which allow you to fetch the version of the extension.

To get the current version:

chrome.runtime.getManifest().version

To listen when the extension has been first installed, when the extension is updated to a new version, and when Chromium is updated to a new version, you can use the onInstalled event.

chrome.runtime.onInstalled.addListener((details) => {
   const currentVersion = chrome.runtime.getManifest().version
   const previousVersion = details.previousVersion
   const reason = details.reason
   
   console.log(`Previous Version: ${previousVersion }`)
   console.log(`Current Version: ${currentVersion }`)

   switch (reason) {
      case 'install':
         console.log('New User installed the extension.')
         break;
      case 'update':
         console.log('User has updated their extension.')
         break;
      case 'chrome_update':
      case 'shared_module_update':
      default:
         console.log('Other install events within the browser')
         break;
   }

})

Thats all!


Old answer, prior to 2011

If you want to check if the extension has been installed or updated, you can do something like this:

function onInstall() {
    console.log("Extension Installed");
  }

  function onUpdate() {
    console.log("Extension Updated");
  }

  function getVersion() {
    var details = chrome.app.getDetails();
    return details.version;
  }

  // Check if the version has changed.
  var currVersion = getVersion();
  var prevVersion = localStorage['version']
  if (currVersion != prevVersion) {
    // Check if we just installed this extension.
    if (typeof prevVersion == 'undefined') {
      onInstall();
    } else {
      onUpdate();
    }
    localStorage['version'] = currVersion;
  }
Mohamed Mansour
  • 39,445
  • 10
  • 116
  • 90
  • If I run getVersion() in a content script in Gmail, I get the Gmail app version's number. I should point out there are a number of problems that will prevent this type of script from working: a) when you install a plugin, which needs to inject a content script into a page, and the page is already loaded, the content script does not get injected into the page, the page has to be reloaded). b) getting the version number of the plugin can be done from the background script, however the background script can't access the localStorage, only the content script can, which is not yet loaded... – Victor S Dec 18 '11 at 03:59
  • 3
    this post is great... you should mark this one as an answer. Thanks Mohamed! – frenetix Feb 02 '12 at 14:36
  • 3
    @VictorS the above is intended to be used within the background page, if your planning to use this in a content script, then just call chrome.app.getDetails().version directly. The reason why I did getVersion before is because in the early days of Chrome Extension development, there was no chrome.app object, so we had to XHR the manifest. You could do all this in a closure so you can guarantee your calling the right method. I usually encapsulate everything in a class object. – Mohamed Mansour Feb 02 '12 at 23:13
  • 1
    Great, this worked for me. Note that the above code is missing a semicolon, and "undefined" shouldn't have quotes. – mpoisot Oct 08 '12 at 17:23
  • @mpoisot Sorry to say, you are wrong about "undefined". (I know I'm very late to this party but this may be important for others who stumble across here such as myself.) He is *not* trying to check `prevVersion == 'undefined'`... he is checking `typeof prevVersion == 'undefined'`. It is much more robust to use `typeof` when checking if a variable is undefined... see here to learn why: http://stackoverflow.com/a/3550319/130691 – JMTyler Sep 11 '13 at 00:50
  • @JMTyler you're right about `undefined`. It's been too long so I can't remember why I put that. – mpoisot Sep 11 '13 at 21:37
  • @MohamedMansour, **This requires storage permission though.** – Pacerier Sep 10 '17 at 10:17
  • @Pacerier i though the storage permission just relates to `chrome.storage` not `localStorage`? – RedSparr0w Sep 16 '17 at 01:56
  • Thanks @MohamedMansour – Touseef Murtaza Jun 27 '19 at 13:34
21

Fortunately, there are now events for this (since Chrome version 22, and 25 for update events).

For an installed event:

chrome.runtime.onInstalled.addListener(function() {...});

For an OnUpdateAvailable event:

chrome.runtime.onUpdateAvailable.addListener(function() {...});

An important excerpt about OnUpdateAvailable from the developer docs says:

Fired when an update is available, but isn't installed immediately because the app is currently running. If you do nothing, the update will be installed the next time the background page gets unloaded, if you want it to be installed sooner you can explicitly call chrome.runtime.reload().

JVillella
  • 1,029
  • 1
  • 11
  • 21
9

Simple. When the extension first runs, the localStorage is empty. On first run, you can write a flag there to mark all consequent runs as non-first.

Example, in background.htm:

var first_run = false;
if (!localStorage['ran_before']) {
  first_run = true;
  localStorage['ran_before'] = '1';
}

if (first_run) alert('This is the first run!');

EDIT: To check whether the extension has just been updated, store the version instead of a simple flag on first run, then when the current extension version (get it by XmlHttpRequesting the manifest) doesn't equal the one stored in localStorage, the extension has been updated.

Max Shawabkeh
  • 37,799
  • 10
  • 82
  • 91
  • Careful not to do that in a content script. localStorage is shared with other code and extensions on the page. So this wouldn't work in a content script. – huyz Jul 20 '11 at 01:52
  • For packaged apps, this is indeed a definite solution for use in background pages as a packaged app's `localStorage` is indeed in its own separate window and not shared with other code and extensions on the page as @huyz mentioned. For extensions, however, this is not the case. – realkstrawn93 Jan 26 '14 at 01:13
  • 1
    **This requires storage permission though.** – Pacerier Sep 10 '17 at 10:19