What's new? | Help | Directory | Sign in
Google
             
Search
for
Updated Nov 15, 2008 by pilgrim
Labels: is-article, about-dom
ArticleDetectFlash  
HOWTO detect whether the user has Flash installed (goog.userAgent.flash)

As much as Google loves and advocates the open web, there are still a few things that can be done with Flash. If you need to use Flash, you need to react gracefully if Flash is not installed.

The code

This code relies on functions explained elsewhere:

This code is within an anonymous function block and sets two global variables with its results. There is no function to call; the code is executed as soon as the script is executed, and the results are always available in the goog.userAgent.flash.HAS_FLASH and goog.userAgent.flash.VERSION variables.

(function() {
  /**
   * Derived from Apple's suggested sniffer.
   * @param {String} desc e.g. Shockwave Flash 7.0 r61
   * @return {String} 7.0.61
   */
  function getFlashVersion(desc) {
    var matches = desc.match(/[\d]+/g);
    matches.length = 3;  // To standardize IE vs FF
    return matches.join('.');
  }

  var hasFlash = false;
  var flashVersion = '';

  if (navigator.plugins && navigator.plugins.length) {
    var plugin = navigator.plugins['Shockwave Flash'];
    if (plugin) {
      hasFlash = true;
      if (plugin.description) {
        flashVersion = getFlashVersion(plugin.description);
      }
    }

    if (navigator.plugins['Shockwave Flash 2.0']) {
      hasFlash = true;
      flashVersion = '2.0.0.11';
    }

  } else if (navigator.mimeTypes && navigator.mimeTypes.length) {
    var mimeType = navigator.mimeTypes['application/x-shockwave-flash'];
    hasFlash = mimeType && mimeType.enabledPlugin;
    if (hasFlash) {
      flashVersion = getFlashVersion(mimeType.enabledPlugin.description);
    }

  } else {
    try {
      // Try 7 first, since we know we can use GetVariable with it
      var ax = new ActiveXObject('ShockwaveFlash.ShockwaveFlash.7');
      hasFlash = true;
      flashVersion = getFlashVersion(ax.GetVariable('$version'));
    } catch (e) {
      // Try 6 next, some versions are known to crash with GetVariable calls
      try {
        var ax = new ActiveXObject('ShockwaveFlash.ShockwaveFlash.6');
        hasFlash = true;
        flashVersion = '6.0.21';  // First public version of Flash 6
      } catch (e) {
        try {
          // Try the default activeX
          var ax = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');
          hasFlash = true;
          flashVersion = getFlashVersion(ax.GetVariable('$version'));
        } catch (e) {
          // No flash
        }
      }
    }
  }

  /**
   * Whether we can detect that the browser has flash
   * @type Boolean
   */
  goog.userAgent.flash.HAS_FLASH = hasFlash;


  /**
   * Full version information of flash installed, in form 7.0.61
   * @type String
   */
  goog.userAgent.flash.VERSION = flashVersion;

})();


/**
 * Whether the installed flash version is as new or newer than a given version.
 * @param {String} version The version to check.
 * @return {Boolean}
 */
goog.userAgent.flash.isVersion = function(version) {
  return goog.userAgent.compare(goog.userAgent.flash.VERSION, version) >= 0;
};

The code walkthrough

The first step is to define a helper function that extracts and normalizes the Flash version. Even at this low level, there is cross-browser weirdness -- the format of the version string varies depending on the route we use to access it (navigator.plugins vs. ActiveXObject). We truncate the version at three decimal places and return it as a string.

  function getFlashVersion(desc) {
    var matches = desc.match(/[\d]+/g);
    matches.length = 3;  // To standardize IE vs FF
    return matches.join('.');
  }

OK, the first place to look for Flash is navigator.plugins, which is supported by every browser except Internet Explorer. If one of the plugins has the key "Shockwave Flash", then the version is probably stored in plugin.description.

  var hasFlash = false;
  var flashVersion = '';

  if (navigator.plugins && navigator.plugins.length) {
    var plugin = navigator.plugins['Shockwave Flash'];
    if (plugin) {
      hasFlash = true;
      if (plugin.description) {
        flashVersion = getFlashVersion(plugin.description);
      }
    }

For reasons that no one remembers, Flash 2 (yes, that's old) does not announce its version string properly in plugin.description. We'll hard-code 2.0.0.11 (the last in the Flash 2 series) and pray for the soul of the end user who is stuck in the 20th century.

    if (navigator.plugins['Shockwave Flash 2.0']) {
      hasFlash = true;
      flashVersion = '2.0.0.11';
    }

The next place to check is navigator.mimeTypes, which holds a list of all the MIME types registered in the browser. The MIME type of Flash is application/x-shockwave-flash. If this key is found in the MIME type array, we can access the plugin through the mimeType.enabledPlugin property and then get the Flash version as above.

  } else if (navigator.mimeTypes && navigator.mimeTypes.length) {
    var mimeType = navigator.mimeTypes['application/x-shockwave-flash'];
    hasFlash = mimeType && mimeType.enabledPlugin;
    if (hasFlash) {
      flashVersion = getFlashVersion(mimeType.enabledPlugin.description);
    }

That's it for the non-IE browsers. The rest is to deal with the accumulated cruft of Flash differences within Internet Explorer.

The first ActiveX test is to look for the ShockwaveFlash.7 object, which, unsurprisingly, is available in Flash 7 and later. Modern versions of Flash support the GetVariable method to get the exact version string.

  } else {
    try {
      var ax = new ActiveXObject('ShockwaveFlash.ShockwaveFlash.7');
      hasFlash = true;
      flashVersion = getFlashVersion(ax.GetVariable('$version'));

The second ActiveX test is to look for the ShockwaveFlash.6 object, which is available in Flash 6 and later. This object does not support the GetVariable method, so we need to hard-code the version string.

    } catch (e) {
      try {
        var ax = new ActiveXObject('ShockwaveFlash.ShockwaveFlash.6');
        hasFlash = true;
        flashVersion = '6.0.21';  // First public version of Flash 6

The final ActiveX test is to look for the default ShockwaveFlash object.

      } catch (e) {
        try {
          var ax = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');
          hasFlash = true;
          flashVersion = getFlashVersion(ax.GetVariable('$version'));
        }
      }

If all tests fail, we have no Flash plug-in available.

        } catch (e) {
          // No flash
        }

Further reading


Comment by dybber, May 14, 2008

In Firefox (and maybe other browsers) you shouldn't care about this: the browser knows where to get the plugin and guides you through and installation when it spots a Flash application.

Comment by sven.clement, May 16, 2008

But if you develop for a broader audience, you should not presume that 1. they have the skill to folow the "simple" instructions (or are willing, because they fear to break something) and 2. that most enterprises prohibit their employees to install software as the flash player, so I think you should care!


Sign in to add a comment