15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2009 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @fileoverview CFInstall.js provides a set of utilities for managing
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the Chrome Frame detection and installation process.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @author slightlyoff@google.com (Alex Russell)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)(function(scope) {
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // bail if we'd be over-writing an existing CFInstall object
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (scope['CFInstall']) {
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * returns an item based on DOM ID. Optionally a document may be provided to
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * specify the scope to search in. If a node is passed, it's returned as-is.
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {string|Node} id The ID of the node to be located or a node
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Node} doc Optional A document to search for id.
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @return {Node}
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var byId = function(id, doc) {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (typeof id == 'string') ? (doc || document).getElementById(id) : id;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /////////////////////////////////////////////////////////////////////////////
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Plugin Detection
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /////////////////////////////////////////////////////////////////////////////
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Checks to find out if ChromeFrame is available as a plugin
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @return {Boolean}
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var isAvailable = function() {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // For testing purposes.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (scope.CFInstall._force) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return scope.CFInstall._forceValue;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Look for CF in the User Agent before trying more expensive checks
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var ua = navigator.userAgent.toLowerCase();
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ua.indexOf("chromeframe") >= 0) {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (typeof window['ActiveXObject'] != 'undefined') {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      try {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        var obj = new ActiveXObject('ChromeTab.ChromeFrame');
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (obj) {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          obj.registerBhoIfNeeded();
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return true;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } catch(e) {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // squelch
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Creates a style sheet in the document containing the passed rules.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var injectStyleSheet = function(rules) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    try {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var ss = document.createElement('style');
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ss.setAttribute('type', 'text/css');
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (ss.styleSheet) {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ss.styleSheet.cssText = rules;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ss.appendChild(document.createTextNode(rules));
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var h = document.getElementsByTagName('head')[0];
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var firstChild = h.firstChild;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      h.insertBefore(ss, firstChild);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } catch (e) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // squelch
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /** @type {boolean} */
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var cfStyleTagInjected = false;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /** @type {boolean} */
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var cfHiddenInjected = false;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Injects style rules into the document to handle formatting of Chrome Frame
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * prompt. Multiple calls have no effect.
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var injectCFStyleTag = function() {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (cfStyleTagInjected) {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Once and only once
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var rules = '.chromeFrameInstallDefaultStyle {' +
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   'width: 800px;' +
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   'height: 600px;' +
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   'position: absolute;' +
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   'left: 50%;' +
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   'top: 50%;' +
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   'margin-left: -400px;' +
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   'margin-top: -300px;' +
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 '}' +
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 '.chromeFrameOverlayContent {' +
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   'position: absolute;' +
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   'margin-left: -400px;' +
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   'margin-top: -300px;' +
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   'left: 50%;' +
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   'top: 50%;' +
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   'border: 1px solid #93B4D9;' +
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   'background-color: white;' +
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   'z-index: 2001;' +
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 '}' +
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 '.chromeFrameOverlayContent iframe {' +
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   'width: 800px;' +
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   'height: 600px;' +
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   'border: none;' +
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 '}' +
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 '.chromeFrameOverlayCloseBar {' +
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   'height: 1em;' +
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   'text-align: right;' +
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   'background-color: #CADEF4;' +
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 '}' +
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 '.chromeFrameOverlayUnderlay {' +
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   'position: absolute;' +
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   'width: 100%;' +
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   'height: 100%;' +
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   'background-color: white;' +
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   'opacity: 0.5;' +
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   '-moz-opacity: 0.5;' +
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   '-webkit-opacity: 0.5;' +
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   '-ms-filter: ' +
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      '"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";' +
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   'filter: alpha(opacity=50);' +
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   'z-index: 2000;' +
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 '}';
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    injectStyleSheet(rules);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cfStyleTagInjected = true;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Injects style rules to hide the overlay version of the GCF prompt.
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Multiple calls have no effect.
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var closeOverlay = function() {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // IE has a limit to the # of <style> tags allowed, so we avoid
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // tempting the fates.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (cfHiddenInjected) {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var rules = '.chromeFrameOverlayContent { display: none; }' +
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                '.chromeFrameOverlayUnderlay { display: none; }';
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    injectStyleSheet(rules);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Hide the dialog for a year (or until cookies are deleted).
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var age = 365 * 24 * 60 * 60 * 1000;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    document.cookie = "disableGCFCheck=1;path=/;max-age="+age;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cfHiddenInjected = true;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Plucks properties from the passed arguments and sets them on the passed
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * DOM node
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Node} node The node to set properties on
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Object} args A map of user-specified properties to set
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var setProperties = function(node, args) {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var srcNode = byId(args['node']);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    node.id = args['id'] || (srcNode ? srcNode['id'] || getUid(srcNode) : '');
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(slightlyoff): Opera compat? need to test there
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var cssText = args['cssText'] || '';
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    node.style.cssText = ' ' + cssText;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var classText = args['className'] || '';
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    node.className = classText;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // default if the browser doesn't so we don't show sad-tab
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var src = args['src'] || 'about:blank';
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    node.src = src;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (srcNode) {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      srcNode.parentNode.replaceChild(node, srcNode);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Creates an iframe.
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Object} args A bag of configuration properties, including values
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *    like 'node', 'cssText', 'className', 'id', 'src', etc.
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @return {Node}
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var makeIframe = function(args) {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var el = document.createElement('iframe');
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    el.setAttribute('frameborder', '0');
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    el.setAttribute('border', '0');
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    setProperties(el, args);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return el;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Adds an unadorned iframe into the page, taking arguments to customize it.
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Object} args A map of user-specified properties to set
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var makeInlinePrompt = function(args) {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    args.className = 'chromeFrameInstallDefaultStyle ' +
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        (args.className || '');
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var ifr = makeIframe(args);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(slightlyoff): handle placement more elegantly!
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ifr.parentNode) {
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var firstChild = document.body.firstChild;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      document.body.insertBefore(ifr, firstChild);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Adds a styled, closable iframe into the page with a background that
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * emulates a modal dialog.
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Object} args A map of user-specified properties to set
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var makeOverlayPrompt = function(args) {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (byId('chromeFrameOverlayContent')) {
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return; // Was previously created. Bail.
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var n = document.createElement('span');
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    n.innerHTML = '<div class="chromeFrameOverlayUnderlay"></div>' +
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      '<table class="chromeFrameOverlayContent"' +
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             'id="chromeFrameOverlayContent"' +
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             'cellpadding="0" cellspacing="0">' +
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        '<tr class="chromeFrameOverlayCloseBar">' +
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          '<td>' +
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // TODO(slightlyoff): i18n
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            '<button id="chromeFrameCloseButton">close</button>' +
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          '</td>' +
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        '</tr>' +
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        '<tr>' +
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          '<td id="chromeFrameIframeHolder"></td>' +
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        '</tr>' +
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      '</table>';
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var b = document.body;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Insert underlay nodes into the document in the right order.
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (n.firstChild) {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      b.insertBefore(n.lastChild, b.firstChild);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var ifr = makeIframe(args);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    byId('chromeFrameIframeHolder').appendChild(ifr);
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    byId('chromeFrameCloseButton').onclick = closeOverlay;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var CFInstall = {};
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Checks to see if Chrome Frame is available, if not, prompts the user to
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * install. Once installation is begun, a background timer starts,
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * checkinging for a successful install every 2 seconds. Upon detection of
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * successful installation, the current page is reloaded, or if a
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * 'destination' parameter is passed, the page navigates there instead.
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Object} args A bag of configuration properties. Respected
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *    properties are: 'mode', 'url', 'destination', 'node', 'onmissing',
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *    'preventPrompt', 'oninstall', 'preventInstallDetection', 'cssText', and
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *    'className'.
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @public
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CFInstall.check = function(args) {
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    args = args || {};
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We currently only support CF in IE
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(slightlyoff): Update this should we support other browsers!
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var ua = navigator.userAgent;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var ieRe = /MSIE (\S+); Windows NT/;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var bail = false;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ieRe.test(ua)) {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We also only support Win2003/XPSP2 or better. See:
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //  http://msdn.microsoft.com/en-us/library/ms537503%28VS.85%29.aspx
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (parseFloat(ieRe.exec(ua)[1]) < 6 &&
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // 'SV1' indicates SP2, only bail if not SP2 or Win2K3
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ua.indexOf('SV1') < 0) {
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bail = true;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Not IE
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bail = true;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (bail) {
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Inject the default styles
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    injectCFStyleTag();
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (document.cookie.indexOf("disableGCFCheck=1") >=0) {
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If we're supposed to hide the overlay prompt, add the rules to do it.
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      closeOverlay();
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // When loaded in an alternate protocol (e.g., "file:"), still call out to
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the right location.
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var currentProtocol = document.location.protocol;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var protocol = (currentProtocol == 'https:') ? 'https:' : 'http:';
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(slightlyoff): Update this URL when a mini-installer page is
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //   available.
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var installUrl = protocol + '//www.google.com/chromeframe';
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!isAvailable()) {
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (args.onmissing) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        args.onmissing();
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      args.src = args.url || installUrl;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var mode = args.mode || 'inline';
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var preventPrompt = args.preventPrompt || false;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!preventPrompt) {
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (mode == 'inline') {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          makeInlinePrompt(args);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else if (mode == 'overlay') {
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          makeOverlayPrompt(args);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          window.open(args.src);
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (args.preventInstallDetection) {
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Begin polling for install success.
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var installTimer = setInterval(function() {
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // every 2 seconds, look to see if CF is available, if so, proceed on
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // to our destination
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (isAvailable()) {
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (args.oninstall) {
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              args.oninstall();
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            clearInterval(installTimer);
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // TODO(slightlyoff): add a way to prevent navigation or make it
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            //    contingent on oninstall?
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            window.location = args.destination || window.location;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }, 2000);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CFInstall._force = false;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CFInstall._forceValue = false;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CFInstall.isAvailable = isAvailable;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // expose CFInstall to the external scope. We've already checked to make
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // sure we're not going to blow existing objects away.
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scope.CFInstall = CFInstall;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)})(this['ChromeFrameInstallScope'] || this);
358