summaryrefslogtreecommitdiffstats
path: root/chrome_frame/CFInstall.js
diff options
context:
space:
mode:
authorslightlyoff@chromium.org <slightlyoff@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-24 05:11:58 +0000
committerslightlyoff@chromium.org <slightlyoff@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-24 05:11:58 +0000
commitf781782dd67077478e117c61dca4ea5eefce3544 (patch)
tree4801f724123cfdcbb69c4e7fe40a565b331723ae /chrome_frame/CFInstall.js
parent63cf4759efa2373e33436fb5df6849f930081226 (diff)
downloadchromium_src-f781782dd67077478e117c61dca4ea5eefce3544.zip
chromium_src-f781782dd67077478e117c61dca4ea5eefce3544.tar.gz
chromium_src-f781782dd67077478e117c61dca4ea5eefce3544.tar.bz2
Initial import of the Chrome Frame codebase. Integration in chrome.gyp coming in a separate CL.
BUG=None TEST=None Review URL: http://codereview.chromium.org/218019 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@27042 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome_frame/CFInstall.js')
-rw-r--r--chrome_frame/CFInstall.js222
1 files changed, 222 insertions, 0 deletions
diff --git a/chrome_frame/CFInstall.js b/chrome_frame/CFInstall.js
new file mode 100644
index 0000000..915f958
--- /dev/null
+++ b/chrome_frame/CFInstall.js
@@ -0,0 +1,222 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview CFInstall.js provides a set of utilities for managing
+ * the Chrome Frame detection and installation process.
+ * @author slightlyoff@google.com (Alex Russell)
+ */
+
+(function(scope) {
+ // bail if we'd be over-writing an existing CFInstall object
+ if (scope['CFInstall']) {
+ return;
+ }
+
+ /**
+ * returns an item based on DOM ID. Optionally a document may be provided to
+ * specify the scope to search in. If a node is passed, it's returned as-is.
+ * @param {string|Node} id The ID of the node to be located or a node
+ * @param {Node} doc Optional A document to search for id.
+ * @return {Node}
+ */
+ var byId = function(id, doc) {
+ return (typeof id == 'string') ? (doc || document).getElementById(id) : id;
+ };
+
+ /////////////////////////////////////////////////////////////////////////////
+ // Plugin Detection
+ /////////////////////////////////////////////////////////////////////////////
+
+ var cachedAvailable;
+
+ /**
+ * Checks to find out if ChromeFrame is available as a plugin
+ * @return {Boolean}
+ */
+ var isAvailable = function() {
+ if (typeof cachedAvailable != 'undefined') {
+ return cachedAvailable;
+ }
+
+ cachedAvailable = false;
+
+ // Look for CF in the User Agent before trying more expensive checks
+ var ua = navigator.userAgent.toLowerCase();
+ if (ua.indexOf("chromeframe") >= 0 || ua.indexOf("x-clock") >= 0) {
+ cachedAvailable = true;
+ return cachedAvailable;
+ }
+
+ if (typeof window['ActiveXObject'] != 'undefined') {
+ try {
+ var obj = new ActiveXObject('ChromeTab.ChromeFrame');
+ if (obj) {
+ cachedAvailable = true;
+ }
+ } catch(e) {
+ // squelch
+ }
+ }
+ return cachedAvailable;
+ };
+
+
+ /** @type {boolean} */
+ var cfStyleTagInjected = false;
+
+ /**
+ * Creates a style sheet in the document which provides default styling for
+ * ChromeFrame instances. Successive calls should have no additive effect.
+ */
+ var injectCFStyleTag = function() {
+ if (cfStyleTagInjected) {
+ // Once and only once
+ return;
+ }
+ try {
+ var rule = '.chromeFrameInstallDefaultStyle {' +
+ 'width: 500px;' +
+ 'height: 400px;' +
+ 'padding: 0;' +
+ 'border: 1px solid #0028c4;' +
+ 'margin: 0;' +
+ '}';
+ var ss = document.createElement('style');
+ ss.setAttribute('type', 'text/css');
+ if (ss.styleSheet) {
+ ss.styleSheet.cssText = rule;
+ } else {
+ ss.appendChild(document.createTextNode(rule));
+ }
+ var h = document.getElementsByTagName('head')[0];
+ var firstChild = h.firstChild;
+ h.insertBefore(ss, firstChild);
+ cfStyleTagInjected = true;
+ } catch (e) {
+ // squelch
+ }
+ };
+
+
+ /**
+ * Plucks properties from the passed arguments and sets them on the passed
+ * DOM node
+ * @param {Node} node The node to set properties on
+ * @param {Object} args A map of user-specified properties to set
+ */
+ var setProperties = function(node, args) {
+ injectCFStyleTag();
+
+ var srcNode = byId(args['node']);
+
+ node.id = args['id'] || (srcNode ? srcNode['id'] || getUid(srcNode) : '');
+
+ // TODO(slightlyoff): Opera compat? need to test there
+ var cssText = args['cssText'] || '';
+ node.style.cssText = ' ' + cssText;
+
+ var classText = args['className'] || '';
+ node.className = 'chromeFrameInstallDefaultStyle ' + classText;
+
+ // default if the browser doesn't so we don't show sad-tab
+ var src = args['src'] || 'about:blank';
+
+ node.src = src;
+
+ if (srcNode) {
+ srcNode.parentNode.replaceChild(node, srcNode);
+ }
+ };
+
+ /**
+ * Creates an iframe.
+ * @param {Object} args A bag of configuration properties, including values
+ * like 'node', 'cssText', 'className', 'id', 'src', etc.
+ * @return {Node}
+ */
+ var makeIframe = function(args) {
+ var el = document.createElement('iframe');
+ setProperties(el, args);
+ return el;
+ };
+
+ var CFInstall = {};
+ /**
+ * Checks to see if Chrome Frame is available, if not, prompts the user to
+ * install. Once installation is begun, a background timer starts,
+ * checkinging for a successful install every 2 seconds. Upon detection of
+ * successful installation, the current page is reloaded, or if a
+ * 'destination' parameter is passed, the page navigates there instead.
+ * @param {Object} args A bag of configuration properties. Respected
+ * properties are: 'mode', 'url', 'destination', 'node', 'onmissing',
+ * 'preventPrompt', 'oninstall', 'preventInstallDetection', 'cssText', and
+ * 'className'.
+ * @public
+ */
+ CFInstall.check = function(args) {
+ args = args || {};
+
+ // We currently only support CF in IE
+ // TODO(slightlyoff): Update this should we support other browsers!
+ var ieRe = /MSIE (\S+)/;
+ if (!ieRe.test(navigator.userAgent)) {
+ return;
+ }
+
+
+ // TODO(slightlyoff): Update this URL when a mini-installer page is
+ // available.
+ var installUrl = '//www.google.com/chromeframe';
+ if (!isAvailable()) {
+ if (args.onmissing) {
+ args.onmissing();
+ }
+
+ args.src = args.url || installUrl;
+ var mode = args.mode || 'inline';
+ var preventPrompt = args.preventPrompt || false;
+
+ if (!preventPrompt) {
+ if (mode == 'inline') {
+ var ifr = makeIframe(args);
+ // TODO(slightlyoff): handle placement more elegantly!
+ if (!ifr.parentNode) {
+ var firstChild = document.body.firstChild;
+ document.body.insertBefore(ifr, firstChild);
+ }
+ } else {
+ window.open(args.src);
+ }
+ }
+
+ if (args.preventInstallDetection) {
+ return;
+ }
+
+ // Begin polling for install success.
+ var installTimer = setInterval(function() {
+ // every 2 seconds, look to see if CF is available, if so, proceed on
+ // to our destination
+ if (isAvailable()) {
+ if (args.oninstall) {
+ args.oninstall();
+ }
+
+ clearInterval(installTimer);
+ // TODO(slightlyoff): add a way to prevent navigation or make it
+ // contingent on oninstall?
+ window.location = args.destination || window.location;
+ }
+ }, 2000);
+ }
+ };
+
+ CFInstall.isAvailable = isAvailable;
+
+ // expose CFInstall to the external scope. We've already checked to make
+ // sure we're not going to blow existing objects away.
+ scope.CFInstall = CFInstall;
+
+})(this['ChromeFrameInstallScope'] || this);