summaryrefslogtreecommitdiffstats
path: root/chrome_frame
diff options
context:
space:
mode:
authorerikwright@chromium.org <erikwright@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-04 17:22:10 +0000
committererikwright@chromium.org <erikwright@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-04 17:22:10 +0000
commitcdaf67c70b346fa9fa8bab1973d96e0d495aba4b (patch)
treec15a8dd9b6cc42789d0f7d3bef0ab807d3422dcc /chrome_frame
parentbeb288919aa2ebf9908b4d161705a90417485212 (diff)
downloadchromium_src-cdaf67c70b346fa9fa8bab1973d96e0d495aba4b.zip
chromium_src-cdaf67c70b346fa9fa8bab1973d96e0d495aba4b.tar.gz
chromium_src-cdaf67c70b346fa9fa8bab1973d96e0d495aba4b.tar.bz2
Publish the source for CFInstall.min.js .
BUG=None TEST=./build.sh and then load file:///path/to/local_testing.html in IE (without CF). Click the "This site requires Chrome Frame" link and observe the dialog that pops up. Review URL: http://codereview.chromium.org/8467005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@108675 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome_frame')
-rw-r--r--chrome_frame/cfinstall/.gitignore2
-rw-r--r--chrome_frame/cfinstall/README7
-rwxr-xr-xchrome_frame/cfinstall/build.sh62
-rw-r--r--chrome_frame/cfinstall/examples/jquery.html71
-rw-r--r--chrome_frame/cfinstall/examples/local_testing.html38
-rw-r--r--chrome_frame/cfinstall/examples/simple.html25
-rw-r--r--chrome_frame/cfinstall/src/common/cf-interactiondelegate-externs.js13
-rw-r--r--chrome_frame/cfinstall/src/common/interactiondelegate.js49
-rwxr-xr-xchrome_frame/cfinstall/src/implementation/crossdomaininstall.js111
-rwxr-xr-xchrome_frame/cfinstall/src/implementation/dialoginteractiondelegate.js161
-rw-r--r--chrome_frame/cfinstall/src/miniclosure/base.js77
-rw-r--r--chrome_frame/cfinstall/src/miniclosure/style.js29
-rwxr-xr-xchrome_frame/cfinstall/src/stub/cf-activex-externs.js16
-rw-r--r--chrome_frame/cfinstall/src/stub/cfinstall.js118
-rwxr-xr-xchrome_frame/cfinstall/src/stub/chromeframe.js90
-rw-r--r--chrome_frame/cfinstall/src/stub/frame.js46
-rw-r--r--chrome_frame/cfinstall/src/stub/inlinedelegate.js87
-rw-r--r--chrome_frame/cfinstall/src/stub/installer.js43
-rw-r--r--chrome_frame/cfinstall/src/stub/overlaydelegate.js156
-rw-r--r--chrome_frame/cfinstall/src/stub/prompt.js210
20 files changed, 1411 insertions, 0 deletions
diff --git a/chrome_frame/cfinstall/.gitignore b/chrome_frame/cfinstall/.gitignore
new file mode 100644
index 0000000..f92e804
--- /dev/null
+++ b/chrome_frame/cfinstall/.gitignore
@@ -0,0 +1,2 @@
+/deps/
+/out/
diff --git a/chrome_frame/cfinstall/README b/chrome_frame/cfinstall/README
new file mode 100644
index 0000000..622ebb1
--- /dev/null
+++ b/chrome_frame/cfinstall/README
@@ -0,0 +1,7 @@
+This directory contains the source code for CFInstall.min.js, a useful site for
+prompting web site visitors to install Chrome Frame.
+
+Please visit the following page for further information about compiling and
+using these scripts:
+
+https://sites.google.com/a/chromium.org/dev/developers/how-tos/chrome-frame-cfinstall \ No newline at end of file
diff --git a/chrome_frame/cfinstall/build.sh b/chrome_frame/cfinstall/build.sh
new file mode 100755
index 0000000..354262c
--- /dev/null
+++ b/chrome_frame/cfinstall/build.sh
@@ -0,0 +1,62 @@
+#!/bin/sh
+# Copyright (c) 2011 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.
+
+OPTIMIZATION_LEVEL="ADVANCED_OPTIMIZATIONS"
+EXTRA_FLAGS=""
+
+while getopts l:d o
+do case "$o" in
+ l) EXTRA_FLAGS="$EXTRA_FLAGS -f --define=google.cf.installer.Prompt.\
+DEFAULT_IMPLEMENTATION_URL='${OPTARG}cf-xd-install-impl.js'";;
+ d) OPTIMIZATION_LEVEL="SIMPLE_OPTIMIZATIONS"
+ EXTRA_FLAGS="$EXTRA_FLAGS -f --formatting=PRETTY_PRINT";;
+ [?]) echo >&2 "Usage: $0 [-l //host.com/path/to/scripts/dir/] [-p] [-d]"
+ echo >&2 " -l <URL> The path under which the generated"
+ echo >&2 " scripts will be deployed."
+ echo >&2 " -d Disable obfuscating optimizations."
+ exit 1;;
+ esac
+done
+
+DEPS_DIR=deps
+OUT_DIR=out
+SRC_DIR=src
+CLOSURE_LIBRARY_DIR=$DEPS_DIR/closure_library
+CLOSURE_BUILDER=$CLOSURE_LIBRARY_DIR/closure/bin/build/closurebuilder.py
+CLOSURE_COMPILER_ZIP=$DEPS_DIR/compiler-latest.zip
+CLOSURE_COMPILER_JAR_ZIP_RELATIVE=compiler.jar
+CLOSURE_COMPILER_JAR=$DEPS_DIR/$CLOSURE_COMPILER_JAR_ZIP_RELATIVE
+
+mkdir -p $DEPS_DIR &&
+mkdir -p $OUT_DIR &&
+{ [[ -e $CLOSURE_LIBRARY_DIR ]] || \
+ svn checkout http://closure-library.googlecode.com/svn/trunk/ \
+ $CLOSURE_LIBRARY_DIR; } && \
+{ [[ -e $CLOSURE_COMPILER_JAR ]] ||
+ { wget http://closure-compiler.googlecode.com/files/compiler-latest.zip \
+ -O $CLOSURE_COMPILER_ZIP && \
+ unzip -d $DEPS_DIR $CLOSURE_COMPILER_ZIP \
+ $CLOSURE_COMPILER_JAR_ZIP_RELATIVE >/dev/null; }; } &&
+$CLOSURE_BUILDER \
+ --root=$CLOSURE_LIBRARY_DIR --root=src/common/ \
+ --root=src/implementation/ \
+ --namespace="google.cf.installer.CrossDomainInstall" \
+ --output_mode=compiled --compiler_jar=$CLOSURE_COMPILER_JAR \
+ $EXTRA_FLAGS \
+ -f "--compilation_level=$OPTIMIZATION_LEVEL" \
+ -f "--output_wrapper='(function (scope){ %output% })(window)'" \
+ -f "--externs=src/common/cf-interactiondelegate-externs.js" \
+ --output_file=out/cf-xd-install-impl.js && \
+$CLOSURE_BUILDER \
+ --root=src/miniclosure/ --root=src/common/ \
+ --root=src/stub/ \
+ --namespace="google.cf.installer.CFInstall" \
+ --output_mode=compiled --compiler_jar=$CLOSURE_COMPILER_JAR \
+ $EXTRA_FLAGS \
+ -f "--compilation_level=$OPTIMIZATION_LEVEL" \
+ -f "--output_wrapper='(function (scope){ %output% })(window)'" \
+ -f "--externs=src/stub/cf-activex-externs.js" \
+ -f "--externs=src/common/cf-interactiondelegate-externs.js" \
+ --output_file=out/CFInstall.min.js
diff --git a/chrome_frame/cfinstall/examples/jquery.html b/chrome_frame/cfinstall/examples/jquery.html
new file mode 100644
index 0000000..ef2e4d6
--- /dev/null
+++ b/chrome_frame/cfinstall/examples/jquery.html
@@ -0,0 +1,71 @@
+<!--
+ Copyright 2011 Google Inc. All rights reserved.
+-->
+<html>
+ <head>
+ <meta http-equiv="X-UA-Compatible" content="chrome=1" />
+ <link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css"
+ rel="stylesheet" type="text/css"/>
+ <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js">
+ </script>
+ <script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js">
+ </script>
+
+ <script src='//google.com/tools/dlpage/res/chromeframe/script/CFInstall.min.js'> </script>
+ <script>
+ $(document).ready(function() {
+ var interactionDelegate = {
+ dialog: null,
+ getIFrameContainer: function() {
+ var self = this;
+ this.dialog = $("#dialog").dialog(
+ {modal: true,
+ width: 'auto',
+ height: 'auto',
+ resizable: false,
+ close: function() {
+ var el = document.getElementById('dialog');
+ if (el.firstChild)
+ el.removeChild(el.firstChild);
+ }
+ });
+ var widget = this.dialog.dialog('widget')[0];
+ widget.style.left = -5000;
+ widget.style.top = -5000;
+ return document.getElementById('dialog');
+ },
+ show: function() {
+ var dialogEl = $("#dialog");
+ dialogEl.width($("#dialog iframe").outerWidth(true) +
+ dialogEl.innerWidth() - dialogEl.width());
+ var widgetEl = this.dialog.dialog('widget');
+ widgetEl.width(dialogEl.outerWidth(true) +
+ widgetEl.innerWidth() - widgetEl.width());
+ dialogEl.height('auto');
+ this.dialog.dialog('option', 'position', 'center')
+ },
+ customizeIFrame: function(iframe) {},
+ reset: function() {
+ this.dialog.dialog('close');
+ }
+ };
+ CFInstall.setInteractionDelegate(interactionDelegate);
+ });
+ </script>
+ </head>
+ <body>
+ <b>Chrome Renderer Active?:</b>
+ <span class="labeled" id="ChromeActive"></span><br />
+ <script>
+ var ua = navigator.userAgent.toLowerCase();
+ document.getElementById('ChromeActive').innerHTML =
+ ua.indexOf('chrome/') >= 0 ? "Yes" : "No";
+ </script>
+ <p>
+ <a href="javascript:CFInstall.require()">
+ This site requires Google Chrome Frame. Click here to install it now.
+ </a>
+ </p>
+ <div id="dialog" style="padding:0px; height:auto;"></div>
+ </body>
+</html>
diff --git a/chrome_frame/cfinstall/examples/local_testing.html b/chrome_frame/cfinstall/examples/local_testing.html
new file mode 100644
index 0000000..89bf7327
--- /dev/null
+++ b/chrome_frame/cfinstall/examples/local_testing.html
@@ -0,0 +1,38 @@
+<!--
+ Copyright 2011 Google Inc. All rights reserved.
+-->
+<html>
+ <head>
+ <script src='../out/CFInstall.min.js'> </script>
+ <script>
+ // This is only required if you are hosting your own copy of the
+ // implementation script and have not set the implementation path during
+ // compilation. (See build.sh -l 'PATH').
+ CFInstall.setImplementationUrl('../out/cf-xd-install-impl.js');
+
+ // The following are only required when running this example from a local
+ // file. The default behaviour is to use the same scheme as this page,
+ // which is file://, and thus wrong.
+ CFInstall.setDownloadPageUrl('http://google.com/chromeframe/eula.html');
+ CFInstall.setSameDomainResourceUri('http://example.com/robots.txt');
+ </script>
+ </head>
+ <body>
+ <b>Chrome Frame Installed?:</b>
+ <span class="labeled" id="ChromeInstalled"></span><br />
+ <p>
+ Note that Chrome Frame will never render local pages (i.e., from 'file://'
+ URLs). The above message will, however, tell you whether Chrome Frame is
+ installed.
+ </p>
+ <script>
+ document.getElementById('ChromeInstalled').innerHTML =
+ CFInstall.isAvailable() ? "Yes" : "No";
+ </script>
+ <p>
+ <a href="javascript:CFInstall.require()">
+ This site requires Google Chrome Frame. Click here to install it now.
+ </a>
+ </p>
+ </body>
+</html>
diff --git a/chrome_frame/cfinstall/examples/simple.html b/chrome_frame/cfinstall/examples/simple.html
new file mode 100644
index 0000000..812a717
--- /dev/null
+++ b/chrome_frame/cfinstall/examples/simple.html
@@ -0,0 +1,25 @@
+<!--
+ Copyright 2011 Google Inc. All rights reserved.
+-->
+<html>
+ <head>
+ <meta http-equiv="X-UA-Compatible" content="chrome=1" />
+ <script
+ src='//google.com/tools/dlpage/res/chromeframe/script/CFInstall.min.js'>
+ </script>
+ </head>
+ <body>
+ <b>Chrome Renderer Active?:</b>
+ <span class="labeled" id="ChromeActive"></span><br />
+ <script>
+ var ua = navigator.userAgent.toLowerCase();
+ document.getElementById('ChromeActive').innerHTML =
+ ua.indexOf('chrome/') >= 0 ? "Yes" : "No";
+ </script>
+ <p>
+ <a href="javascript:CFInstall.require()">
+ This site requires Google Chrome Frame. Click here to install it now.
+ </a>
+ </p>
+ </body>
+</html>
diff --git a/chrome_frame/cfinstall/src/common/cf-interactiondelegate-externs.js b/chrome_frame/cfinstall/src/common/cf-interactiondelegate-externs.js
new file mode 100644
index 0000000..805c1ee
--- /dev/null
+++ b/chrome_frame/cfinstall/src/common/cf-interactiondelegate-externs.js
@@ -0,0 +1,13 @@
+// Copyright (c) 2011 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 Defines an interface whose properties should be immune from
+ * renaming (as it may be implemented by uncompiled client code).
+ **/
+
+google.cf.installer.InteractionDelegate.prototype.getIFrameContainer;
+google.cf.installer.InteractionDelegate.prototype.reset;
+google.cf.installer.InteractionDelegate.prototype.show;
+google.cf.installer.InteractionDelegate.prototype.customizeIFrame;
diff --git a/chrome_frame/cfinstall/src/common/interactiondelegate.js b/chrome_frame/cfinstall/src/common/interactiondelegate.js
new file mode 100644
index 0000000..b9cb8c6
--- /dev/null
+++ b/chrome_frame/cfinstall/src/common/interactiondelegate.js
@@ -0,0 +1,49 @@
+// Copyright (c) 2011 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 Describes an interface clients may implement to customize the
+ * look and feel of the Chrome Frame installation flow on their site.
+ *
+ */
+
+goog.provide('google.cf.installer.InteractionDelegate');
+
+/**
+ * Allows clients to customize the display of the IFrame holding the Chrome
+ * Frame installation flow.
+ * @interface
+ */
+google.cf.installer.InteractionDelegate = function() {};
+
+/**
+ * Returns the element under which the IFrame should be located. Note that the
+ * IFrame must remain in the DOM for the duration of the connection.
+ * Re-parenting the IFrame or any ancestor will cause undefined behaviour.
+ * @return {!HTMLElement} The element that should be the parent of the IFrame.
+ */
+google.cf.installer.InteractionDelegate.prototype.getIFrameContainer =
+ function() {};
+
+/**
+ * Receives a reference to the newly created IFrame. May optionally modify the
+ * element's attributes, style, etc. The InteractionDelegate is not responsible
+ * for inserting the IFrame in the DOM (this will occur later).
+ * @param {!HTMLIFrameElement} iframe The newly created IFrame element.
+ */
+google.cf.installer.InteractionDelegate.prototype.customizeIFrame =
+ function(iframe) {};
+
+/**
+ * Make the IFrame and its decoration (if any) visible. Its dimensions will
+ * already have been adjusted to those of the contained content.
+ */
+google.cf.installer.InteractionDelegate.prototype.show = function() {};
+
+
+/**
+ * Receives notification that the installation flow is complete and that the
+ * IFrame and its decoration (if any) should be hidden and resources freed.
+ */
+google.cf.installer.InteractionDelegate.prototype.reset = function() {};
diff --git a/chrome_frame/cfinstall/src/implementation/crossdomaininstall.js b/chrome_frame/cfinstall/src/implementation/crossdomaininstall.js
new file mode 100755
index 0000000..38a1670
--- /dev/null
+++ b/chrome_frame/cfinstall/src/implementation/crossdomaininstall.js
@@ -0,0 +1,111 @@
+// Copyright (c) 2011 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 Implements the in-line Google Chrome Frame installation flow.
+ * Displays a dialog containing the download page. Upon completion, registers
+ * the Google Chrome Frame components in the current browser process.
+ *
+ **/
+goog.provide('google.cf.installer.CrossDomainInstall');
+
+goog.require('goog.net.xpc.CrossPageChannel');
+goog.require('goog.style');
+goog.require('goog.Uri');
+
+goog.require('google.cf.installer.InteractionDelegate');
+goog.require('google.cf.installer.DialogInteractionDelegate');
+
+/**
+ * @type {Object}
+ **/
+google.cf.installer.CrossDomainInstall = {};
+
+/**
+ * @define {string} Defines the default download page URL.
+ **/
+google.cf.installer.CrossDomainInstall.DEFAULT_DOWNLOAD_PAGE_URL =
+ '//www.google.com/chromeframe/eula.html';
+
+/**
+ * Executes the in-line installation flow.
+ * @param {function()} successHandler Invoked upon installation success. When
+ * invoked, Google Chrome Frame will be active in the current and all
+ * future-launched browser processes.
+ * @param {function()=} opt_failureHandler Invoked upon installation failure or
+ * cancellation.
+ * @param {string=} opt_url An alternative URL for the download page.
+ * @param {google.cf.installer.InteractionDelegate=} opt_interactionDelegate An
+ * alternative UI implementation for the modal dialog.
+ * @param {string=} opt_dummyResourceUri A manually-specified dummy resource URI
+ * that will be used to carry cross-domain responses.
+ */
+google.cf.installer.CrossDomainInstall.execute = function(
+ successHandler, opt_failureHandler, opt_url, opt_interactionDelegate,
+ opt_dummyResourceUri) {
+ var url = new goog.Uri(
+ opt_url ||
+ google.cf.installer.CrossDomainInstall.DEFAULT_DOWNLOAD_PAGE_URL);
+
+ if (!url.hasScheme())
+ url = new goog.Uri(window.location.href).resolve(url);
+
+ var interactionDelegate = opt_interactionDelegate ||
+ new google.cf.installer.DialogInteractionDelegate();
+
+ var cfg = {};
+
+ // TODO(user): Probably need to import some of the link/image url
+ // detection stuff from XDRPC.
+ if (opt_dummyResourceUri) {
+ var dummyUrl = new goog.Uri(opt_dummyResourceUri);
+ if (!dummyUrl.hasScheme())
+ dummyUrl = new goog.Uri(window.location.href).resolve(dummyUrl);
+
+ cfg[goog.net.xpc.CfgFields.LOCAL_POLL_URI] = dummyUrl.toString();
+ }
+
+ cfg[goog.net.xpc.CfgFields.PEER_URI] = url.toString();
+
+ var channel = new goog.net.xpc.CrossPageChannel(cfg);
+ var iframe = channel.createPeerIframe(
+ interactionDelegate.getIFrameContainer(),
+ function(newIFrame) {
+ newIFrame.setAttribute('frameBorder', '0');
+ newIFrame.setAttribute('border', '0');
+ interactionDelegate.customizeIFrame(newIFrame);
+ });
+ channel.registerService('dimensions', function(size) {
+ goog.style.setContentBoxSize(iframe, new goog.math.Size(size['width'],
+ size['height']));
+ interactionDelegate.show();
+ }, true); // true => deserialize messages into objects
+ channel.registerService('result', function(obj) {
+ channel.close();
+ interactionDelegate.reset();
+ var result = obj['result'];
+ if (result)
+ successHandler();
+ else if (opt_failureHandler)
+ opt_failureHandler();
+ }, true); // true => deserialize messages into objects
+ // TODO(user): Perhaps listen to onload and set a timeout for connect.
+ channel.connect();
+};
+
+// In compiled mode, this binary is wrapped in an anonymous function which
+// receives the outer scope as its only parameter. In non-compiled mode, the
+// outer scope is window.
+// Look in the outer scope for the stub, and pass it the implementation.
+try {
+ if (arguments[0]['CF_google_cf_xd_install_stub']) {
+ arguments[0]['CF_google_cf_xd_install_stub'](
+ google.cf.installer.CrossDomainInstall.execute);
+ }
+} catch (e) {
+ if (window['CF_google_cf_xd_install_stub']) {
+ window['CF_google_cf_xd_install_stub'](
+ google.cf.installer.CrossDomainInstall.execute);
+ }
+}
diff --git a/chrome_frame/cfinstall/src/implementation/dialoginteractiondelegate.js b/chrome_frame/cfinstall/src/implementation/dialoginteractiondelegate.js
new file mode 100755
index 0000000..9782dc9
--- /dev/null
+++ b/chrome_frame/cfinstall/src/implementation/dialoginteractiondelegate.js
@@ -0,0 +1,161 @@
+// Copyright (c) 2011 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 Displays the Chrome Frame installation flow in a Closure
+ * dialog component.
+ */
+
+goog.provide('google.cf.installer.DialogInteractionDelegate');
+
+goog.require('goog.math.Size');
+goog.require('goog.style');
+goog.require('goog.ui.Dialog');
+goog.require('goog.userAgent');
+
+goog.require('google.cf.installer.InteractionDelegate');
+
+/**
+ * An implementation of google.cf.installer.InteractionDelegate that decorates
+ * the installation flow using a goog.ui.Dialog .
+ * @constructor
+ * @implements {google.cf.installer.InteractionDelegate}
+ */
+google.cf.installer.DialogInteractionDelegate = function() {
+};
+
+/**
+ * Whether we have already injected the dialog styles into the page.
+ * @type {boolean}
+ * @private
+ **/
+google.cf.installer.DialogInteractionDelegate.injectedCss_ = false;
+
+/**
+ * Injects the dialog styles into the page.
+ * @private
+ **/
+google.cf.installer.DialogInteractionDelegate.injectCss_ = function() {
+ if (google.cf.installer.DialogInteractionDelegate.injectedCss_)
+ return;
+
+ google.cf.installer.DialogInteractionDelegate.injectedCss_ = true;
+
+ goog.style.installStyles(
+ '.xdgcfinstall-dlg {' +
+ 'background: #c1d9ff;' +
+ 'border: 1px solid #3a5774;' +
+ 'color: #000;' +
+ 'padding: 4px;' +
+ 'position: absolute;' +
+ '}' +
+
+ '.xdgcfinstall-dlg-bg {' +
+ 'background: #666;' +
+ 'left: 0;' +
+ 'position: absolute;' +
+ 'top: 0;' +
+ '}' +
+
+ '.xdgcfinstall-dlg-title {' +
+ 'background: #e0edfe;' +
+ 'color: #000;' +
+ 'cursor: pointer;' +
+ 'font-size: 120%;' +
+ 'font-weight: bold;' +
+
+ 'padding: 0px;' +
+ 'height: 17px;' +
+ 'position: relative;' +
+ '_zoom: 1; /* Ensures proper width in IE6 RTL. */' +
+ '}' +
+
+ '.xdgcfinstall-dlg-title-close {' +
+ /* Client apps may override the URL at which they serve the sprite. */
+ 'background: #e0edfe' +
+ 'url(//ssl.gstatic.com/editor/editortoolbar.png)' +
+ 'no-repeat -528px 0;' +
+ 'cursor: default;' +
+ 'font-size: 0%;' +
+ 'height: 15px;' +
+ 'position: absolute;' +
+ 'top: 1px;' +
+ 'right: 1px;' +
+ 'width: 15px;' +
+ 'padding: 0px 0px 0px 0px;' +
+ 'align: right;' +
+ '}' +
+
+ '.xdgcfinstall-dlg-content {' +
+ 'background-color: #fff;' +
+ 'padding: 0px;' +
+ '}'
+ );
+};
+
+/**
+ * The active dialog.
+ * @type {goog.ui.Dialog}
+ * @private
+ */
+google.cf.installer.DialogInteractionDelegate.prototype.dialog_ = null;
+
+/**
+ * @inheritDoc
+ */
+google.cf.installer.DialogInteractionDelegate.prototype.getIFrameContainer =
+ function() {
+ google.cf.installer.DialogInteractionDelegate.injectCss_();
+
+ this.dialog_ = new goog.ui.Dialog('xdgcfinstall-dlg', true);
+ this.dialog_.setButtonSet(null);
+ // TODO(user): The IFrame must be 'visible' or else calculation of its
+ // contents' dimensions is incorrect on IE, yet the following line also
+ // disables interaction with and dims the page contents. It would be best to
+ // only do that when show() is called. Best way is probably to push the mask
+ // elements offscreen.
+ this.dialog_.setVisible(true);
+ goog.style.setPosition(this.dialog_.getDialogElement(), -5000, -5000);
+ return /** @type {!HTMLElement} */(this.dialog_.getContentElement());
+};
+
+/**
+ * @inheritDoc
+ */
+google.cf.installer.DialogInteractionDelegate.prototype.customizeIFrame =
+ function(iframe) {
+};
+
+/**
+ * @inheritDoc
+ */
+google.cf.installer.DialogInteractionDelegate.prototype.show =
+ function() {
+ if (goog.userAgent.IE) {
+ // By default, in IE, the dialog does not respect the width of its contents.
+ // So we set its dimensions here. We need to specifically add some space for
+ // the title bar.
+ var iframeSize = goog.style.getBorderBoxSize(
+ this.dialog_.getContentElement().getElementsByTagName('iframe')[0]);
+ var titleSize = goog.style.getBorderBoxSize(this.dialog_.getTitleElement());
+ goog.style.setContentBoxSize(this.dialog_.getDialogElement(),
+ new goog.math.Size(
+ iframeSize.width,
+ iframeSize.height + titleSize.height));
+ }
+ // Ask the dialog to re-center itself based on the new dimensions.
+ this.dialog_.reposition();
+};
+
+
+/**
+ * @inheritDoc
+ */
+google.cf.installer.DialogInteractionDelegate.prototype.reset = function() {
+ if (this.dialog_) {
+ this.dialog_.setVisible(false);
+ this.dialog_.dispose();
+ this.dialog_ = null;
+ }
+};
diff --git a/chrome_frame/cfinstall/src/miniclosure/base.js b/chrome_frame/cfinstall/src/miniclosure/base.js
new file mode 100644
index 0000000..b64847d
--- /dev/null
+++ b/chrome_frame/cfinstall/src/miniclosure/base.js
@@ -0,0 +1,77 @@
+// Copyright (c) 2011 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 Implements a shim so that the CFInstall scripts can be compiled
+ * with or without Closure. In particular, chromeframe.js is used by the stub,
+ * the implementation, and the download site, so we need to provide an
+ * implementation of goog.provide.
+ **/
+
+var goog = {};
+goog.global = this;
+
+/**
+ * From closure/base.js:goog.exportPath_ .
+ * @param {string} name
+ * @param {Object=} opt_object
+ */
+goog.provide = function(name, opt_object) {
+ var parts = name.split('.');
+ var cur = goog.global;
+
+ // Internet Explorer exhibits strange behavior when throwing errors from
+ // methods externed in this manner. See the testExportSymbolExceptions in
+ // base_test.html for an example.
+ if (!(parts[0] in cur) && cur.execScript)
+ cur.execScript('var ' + parts[0]);
+
+ // Certain browsers cannot parse code in the form for((a in b); c;);
+ // This pattern is produced by the JSCompiler when it collapses the
+ // statement above into the conditional loop below. To prevent this from
+ // happening, use a for-loop and reserve the init logic as below.
+
+ // Parentheses added to eliminate strict JS warning in Firefox.
+ for (var part; parts.length && (part = parts.shift());) {
+ if (!parts.length && opt_object !== undefined) {
+ // last part and we have an object; use it
+ cur[part] = opt_object;
+ } else if (cur[part]) {
+ cur = cur[part];
+ } else {
+ cur = cur[part] = {};
+ }
+ }
+};
+
+// The following line causes the closureBuilder script to recognize this as
+// base.js .
+goog.provide('goog');
+
+/**
+ * From closure/base.js:goog.exportPath_ .
+ * @param {string} name
+ * @param {Object=} opt_object
+ */
+goog.exportSymbol = goog.provide;
+
+/**
+ * NO-OP
+ * @param {string} name
+ */
+goog.require = function(name) {};
+
+/**
+ * A simple form that supports only bound 'this', not arguments.
+ * @param {Function} fn A function to partially apply.
+ * @param {Object|undefined} selfObj Specifies the object which |this| should
+ * point to when the function is run.
+ * @return {!Function} A partially-applied form of the function bind() was
+ * invoked as a method of.
+ */
+goog.bind = function(fn, selfObj) {
+ return function() {
+ return fn.apply(selfObj, arguments);
+ };
+};
diff --git a/chrome_frame/cfinstall/src/miniclosure/style.js b/chrome_frame/cfinstall/src/miniclosure/style.js
new file mode 100644
index 0000000..59905d7
--- /dev/null
+++ b/chrome_frame/cfinstall/src/miniclosure/style.js
@@ -0,0 +1,29 @@
+// Copyright (c) 2011 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.
+
+// A drop-in replacement for one method that we could use from Closure.
+
+goog.provide('goog.style');
+
+/**
+ * Creates a style sheet in the document containing the passed rules.
+ * A simplified version that does not take an optional node parameter.
+ * @param {string} rules
+ */
+goog.style.installStyles = function(rules) {
+ try {
+ var ss = document.createElement('style');
+ ss.setAttribute('type', 'text/css');
+ if (ss.styleSheet) {
+ ss.styleSheet.cssText = rules;
+ } else {
+ ss.appendChild(document.createTextNode(rules));
+ }
+ var h = document.getElementsByTagName('head')[0];
+ var firstChild = h.firstChild;
+ h.insertBefore(ss, firstChild);
+ } catch (e) {
+ // squelch
+ }
+};
diff --git a/chrome_frame/cfinstall/src/stub/cf-activex-externs.js b/chrome_frame/cfinstall/src/stub/cf-activex-externs.js
new file mode 100755
index 0000000..76c6418
--- /dev/null
+++ b/chrome_frame/cfinstall/src/stub/cf-activex-externs.js
@@ -0,0 +1,16 @@
+// Copyright (c) 2011 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 Describes the Chrome Frame ActiveX control.
+ **/
+
+// Defined by chrome_tab.idl
+var ChromeTab;
+/**
+ * @constructor
+ * @extends ActiveXObject
+ */
+ChromeTab.ChromeFrame;
+ChromeTab.ChromeFrame.prototype.registerBhoIfNeeded;
diff --git a/chrome_frame/cfinstall/src/stub/cfinstall.js b/chrome_frame/cfinstall/src/stub/cfinstall.js
new file mode 100644
index 0000000..1bf4e77
--- /dev/null
+++ b/chrome_frame/cfinstall/src/stub/cfinstall.js
@@ -0,0 +1,118 @@
+// Copyright (c) 2011 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 Implements CFInstall.check and isAvailable in a way that is
+ * compatible with previous versions. Also supports a more streamlined
+ * method, 'require'.
+ *
+ **/
+
+goog.provide('google.cf.installer.CFInstall');
+
+goog.require('google.cf.ChromeFrame');
+goog.require('google.cf.installer.InlineDelegate');
+goog.require('google.cf.installer.Installer');
+goog.require('google.cf.installer.OverlayDelegate');
+goog.require('google.cf.installer.Prompt');
+
+/**
+ * Instantiates the CFInstall object. Normally there will be only one, at
+ * Window.CFInstall .
+ * @constructor
+ */
+google.cf.installer.CFInstall = function() {
+ this.prompt_ = new google.cf.installer.Prompt();
+ this.chromeFrame_ = new google.cf.ChromeFrame();
+ this.installer_ = new google.cf.installer.Installer(
+ this.prompt_, this.chromeFrame_);
+ this['setDownloadPageUrl'] =
+ goog.bind(this.prompt_.setDownloadPageUrl, this.prompt_);
+ this['setImplementationUrl'] =
+ goog.bind(this.prompt_.setImplementationUrl, this.prompt_);
+ this['setSameDomainResourceUri'] =
+ goog.bind(this.prompt_.setSameDomainResourceUri, this.prompt_);
+ this['setInteractionDelegate'] =
+ goog.bind(this.prompt_.setInteractionDelegate, this.prompt_);
+ this['require'] = goog.bind(this.installer_.require, this.installer_);
+ this['isAvailable'] =
+ goog.bind(this.chromeFrame_.activate, this.chromeFrame_);
+};
+
+/**
+ * TODO(user): This cookie is not currently set anywhere.
+ * @return {boolean} Whether the user has previously declined Chrome Frame.
+ * @private
+ */
+google.cf.installer.CFInstall.isDeclined_ = function() {
+ return document.cookie.indexOf("disableGCFCheck=1") >=0;
+};
+
+/**
+ * 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'.
+ */
+google.cf.installer.CFInstall.prototype['check'] = function(args) {
+ args = args || {};
+
+ if (!this.chromeFrame_.isPlatformSupported())
+ return;
+
+ if (this.chromeFrame_.activate())
+ return;
+
+ if (args['onmissing'])
+ args['onmissing']();
+
+ if (google.cf.installer.CFInstall.isDeclined_() || args['preventPrompt'])
+ return;
+
+ // NOTE: @slightlyoff, I'm doing away with the window.open option here. Sites
+ // that were using it will now use the popup.
+
+ // In the case of legacy installation parameters, supply a compatible
+ // InteractionDelegate.
+ if (args['mode'] == 'inline' || args['node'] || args['id'] ||
+ args['cssText'] || args['className']) {
+ if (!args['mode'] || args['mode'] == 'inline') {
+ this.prompt_.setInteractionDelegate(
+ new google.cf.installer.InlineDelegate(args));
+ } else {
+ this.prompt_.setInteractionDelegate(
+ new google.cf.installer.OverlayDelegate(args));
+ }
+ }
+
+ if (args['src'])
+ this.prompt_.setDownloadPageUrl(args['src']);
+
+ var onSuccess = function() {
+ if (this.chromeFrame_.activate() && !args['preventInstallDetection']) {
+ if (args['oninstall'])
+ args['oninstall']();
+ window.location.assign(args['destination'] || window.location);
+ }
+ };
+
+ this.prompt_.open(onSuccess, undefined);
+};
+
+// In compiled mode, this binary is wrapped in an anonymous function which
+// receives the outer scope as its only parameter. In non-compiled mode, the
+// outer scope is window.
+
+// Create a single instance of CFInstall and place it in the outer scope
+// (presumably the global window object).
+try {
+ arguments[0]['CFInstall'] = new google.cf.installer.CFInstall();
+} catch (e) {
+ window['CFInstall'] = new google.cf.installer.CFInstall();
+}
diff --git a/chrome_frame/cfinstall/src/stub/chromeframe.js b/chrome_frame/cfinstall/src/stub/chromeframe.js
new file mode 100755
index 0000000..1c00ccd
--- /dev/null
+++ b/chrome_frame/cfinstall/src/stub/chromeframe.js
@@ -0,0 +1,90 @@
+// Copyright (c) 2011 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 Logic for interrogating / manipulating the local Chrome Frame
+ * installation.
+ *
+ **/
+goog.provide('google.cf.ChromeFrame');
+
+/**
+ * Constructs an object for interacting with Chrome Frame through the provided
+ * Window instance.
+ * @constructor
+ * @param {Window=} opt_windowInstance The browser window through which to
+ * interact with Chrome Frame. Defaults to the global window object.
+ **/
+google.cf.ChromeFrame = function(opt_windowInstance) {
+ /**
+ * @private
+ * @const
+ * @type {!Window}
+ **/
+ this.window_ = opt_windowInstance || window;
+};
+
+/**
+ * The name of the Chrome Frame ActiveX control.
+ * @const
+ * @type {string}
+ **/
+google.cf.ChromeFrame.CONTROL_NAME = 'ChromeTab.ChromeFrame';
+
+/**
+ * Determines whether ChromeFrame is supported on the current platform.
+ * @return {boolean} Whether Chrome Frame is supported on the current platform.
+ */
+google.cf.ChromeFrame.prototype.isPlatformSupported = function() {
+ var ua = this.window_.navigator.userAgent;
+ var ieRe = /MSIE (\S+); Windows NT/;
+
+ if (!ieRe.test(ua))
+ return false;
+
+ // We also only support Win2003/XPSP2 or better. See:
+ // http://msdn.microsoft.com/en-us/library/ms537503%28VS.85%29.aspx .
+ // 'SV1' indicates SP2, only bail if not SP2 or Win2K3
+ if (parseFloat(ieRe.exec(ua)[1]) < 6 && ua.indexOf('SV1') < 0)
+ return false;
+
+ return true;
+};
+
+/**
+ * Determines whether Chrome Frame is the currently active renderer.
+ * @return {boolean} Whether Chrome Frame is rendering the current page.
+ */
+google.cf.ChromeFrame.prototype.isActiveRenderer = function () {
+ return this.window_.externalHost ? true : false;
+};
+
+/**
+ * Determines if Google Chrome Frame is activated or locally available for
+ * activation in the current browser instance. In the latter case, will trigger
+ * its activation.
+ * @return {boolean} True if Google Chrome Frame already was active or was
+ * locally available (and now active). False otherwise.
+ */
+google.cf.ChromeFrame.prototype.activate = function() {
+ // Look for CF in the User Agent before trying more expensive checks
+ var ua = this.window_.navigator.userAgent.toLowerCase();
+ if (ua.indexOf('chromeframe') >= 0)
+ return true;
+
+ if (typeof this.window_['ActiveXObject'] != 'undefined') {
+ try {
+ var chromeFrame = /** @type {ChromeTab.ChromeFrame} */(
+ new this.window_.ActiveXObject(google.cf.ChromeFrame.CONTROL_NAME));
+ if (chromeFrame) {
+ // Register the BHO if it hasn't happened already.
+ chromeFrame.registerBhoIfNeeded();
+ return true;
+ }
+ } catch (e) {
+ // Squelch
+ }
+ }
+ return false;
+};
diff --git a/chrome_frame/cfinstall/src/stub/frame.js b/chrome_frame/cfinstall/src/stub/frame.js
new file mode 100644
index 0000000..6d23984
--- /dev/null
+++ b/chrome_frame/cfinstall/src/stub/frame.js
@@ -0,0 +1,46 @@
+// Copyright (c) 2011 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 Implements some utilities for the legacy 'inline' and 'overlay'
+ * UI modes.
+ **/
+
+goog.provide('google.cf.installer.frame');
+
+/**
+ * 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
+ */
+google.cf.installer.frame.setProperties = function(node, args) {
+ var cssText = args['cssText'] || '';
+ node.style.cssText = ' ' + cssText;
+
+ var classText = args['className'] || '';
+ node.className = classText;
+
+ var srcNode = args['node'];
+ if (typeof srcNode == 'string')
+ srcNode = document.getElementById(srcNode);
+ return args['id'] || (srcNode ? srcNode['id'] || '' : '');
+};
+
+/**
+ * Determines the parent node to create the IFrame in, based on the provided
+ * arguments. Note that this should only be called once.
+ * @param {Object} args A map of user-specified properties.
+ */
+google.cf.installer.frame.getParentNode = function(args) {
+ var srcNode = args['node'];
+ if (typeof srcNode == 'string')
+ srcNode = document.getElementById(srcNode);
+ if (srcNode) {
+ var parentNode = srcNode.parentNode;
+ parentNode.removeChild(srcNode);
+ return parentNode;
+ }
+ return document.body;
+}; \ No newline at end of file
diff --git a/chrome_frame/cfinstall/src/stub/inlinedelegate.js b/chrome_frame/cfinstall/src/stub/inlinedelegate.js
new file mode 100644
index 0000000..2489d60
--- /dev/null
+++ b/chrome_frame/cfinstall/src/stub/inlinedelegate.js
@@ -0,0 +1,87 @@
+// Copyright (c) 2011 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 Implements a compatibility layer for older versions of
+ * CFInstall.js .
+ **/
+
+goog.provide('google.cf.installer.InlineDelegate');
+
+goog.require('goog.style');
+
+goog.require('google.cf.installer.InteractionDelegate');
+goog.require('google.cf.installer.frame');
+
+/**
+ * Adds an unadorned iframe into the page, taking arguments to customize it.
+ * @param {Object} args A map of user-specified properties to set
+ * @constructor
+ * @implements {google.cf.installer.InteractionDelegate}
+ */
+google.cf.installer.InlineDelegate = function(args) {
+ this.args_ = args;
+ this.args_.className = 'chromeFrameInstallDefaultStyle ' +
+ (this.args_.className || '');
+};
+
+/**
+ * Indicates whether the overlay CSS has already been injected.
+ * @type {boolean}
+ * @private
+ */
+google.cf.installer.InlineDelegate.styleInjected_ = false;
+
+/**
+ * Generates the CSS for the overlay.
+ * @private
+ */
+google.cf.installer.InlineDelegate.injectCss_ = function() {
+ if (google.cf.installer.InlineDelegate.styleInjected_)
+ return;
+
+ goog.style.installStyles('.chromeFrameInstallDefaultStyle {' +
+ 'width: 800px;' +
+ 'height: 600px;' +
+ 'position: absolute;' +
+ 'left: 50%;' +
+ 'top: 50%;' +
+ 'margin-left: -400px;' +
+ 'margin-top: -300px;' +
+ '}');
+ google.cf.installer.InlineDelegate.styleInjected_ = true;
+};
+
+/**
+ * @inheritDoc
+ */
+google.cf.installer.InlineDelegate.prototype.getIFrameContainer = function() {
+ // TODO(user): This will append to the end of the container, whereas
+ // prior behaviour was beginning...
+ google.cf.installer.InlineDelegate.injectCss_();
+ return google.cf.installer.frame.getParentNode(this.args_);
+};
+
+/**
+ * @inheritDoc
+ */
+google.cf.installer.InlineDelegate.prototype.customizeIFrame =
+ function(iframe) {
+ google.cf.installer.frame.setProperties(iframe, this.args_);
+};
+
+/**
+ * @inheritDoc
+ */
+google.cf.installer.InlineDelegate.prototype.show = function() {
+ // TODO(user): Should start it out hidden and reveal/resize here.
+};
+
+/**
+ * @inheritDoc
+ */
+google.cf.installer.InlineDelegate.prototype.reset =
+ function() {
+ // TODO(user): Should hide it here.
+};
diff --git a/chrome_frame/cfinstall/src/stub/installer.js b/chrome_frame/cfinstall/src/stub/installer.js
new file mode 100644
index 0000000..5416ade
--- /dev/null
+++ b/chrome_frame/cfinstall/src/stub/installer.js
@@ -0,0 +1,43 @@
+// Copyright (c) 2011 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
+ **/
+
+goog.provide('google.cf.installer.Installer');
+
+goog.require('google.cf.ChromeFrame');
+goog.require('google.cf.installer.Prompt');
+
+/**
+ * @constructor
+ */
+google.cf.installer.Installer = function(prompt, chromeFrame) {
+ this.prompt_ = prompt;
+ this.chromeFrame_ = chromeFrame;
+};
+
+google.cf.installer.Installer.prototype.require =
+ function(opt_onInstall, opt_onFailure) {
+ if (this.chromeFrame_.isActiveRenderer())
+ return;
+
+ if (!this.chromeFrame_.isPlatformSupported()) {
+ if (opt_onFailure)
+ opt_onFailure();
+ return;
+ }
+
+ var successHandler = opt_onInstall || function() {
+ window.location.assign(window.location.href);
+ };
+
+ if (this.chromeFrame_.activate()) {
+ successHandler();
+ return;
+ }
+
+ this.prompt_.open(successHandler, opt_onFailure);
+};
diff --git a/chrome_frame/cfinstall/src/stub/overlaydelegate.js b/chrome_frame/cfinstall/src/stub/overlaydelegate.js
new file mode 100644
index 0000000..bb87b6f
--- /dev/null
+++ b/chrome_frame/cfinstall/src/stub/overlaydelegate.js
@@ -0,0 +1,156 @@
+// Copyright (c) 2011 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 Implements a compatibility layer for older versions of
+ * CFInstall.js .
+ **/
+
+goog.provide('google.cf.installer.OverlayDelegate');
+
+goog.require('google.cf.installer.InteractionDelegate');
+goog.require('google.cf.installer.frame');
+
+/**
+ * Constructs an InteractionDelegate compatible with previous versions of
+ * CFInstall.js .
+ * @constructor
+ * @implements {google.cf.installer.InteractionDelegate}
+ */
+google.cf.installer.OverlayDelegate = function(args) {
+ this.args_ = args;
+};
+
+/**
+ * Indicates whether the overlay CSS has already been injected.
+ * @type {boolean}
+ * @private
+ */
+google.cf.installer.OverlayDelegate.styleInjected_ = false;
+
+/**
+ * Generates the CSS for the overlay.
+ * @private
+ */
+google.cf.installer.OverlayDelegate.injectCss_ = function() {
+ if (google.cf.installer.OverlayDelegate.styleInjected_)
+ return;
+ goog.style.installStyles('.chromeFrameOverlayContent {' +
+ 'position: absolute;' +
+ 'margin-left: -400px;' +
+ 'margin-top: -300px;' +
+ 'left: 50%;' +
+ 'top: 50%;' +
+ 'border: 1px solid #93B4D9;' +
+ 'background-color: white;' +
+ 'z-index: 2001;' +
+ '}' +
+ '.chromeFrameOverlayContent iframe {' +
+ 'width: 800px;' +
+ 'height: 600px;' +
+ 'border: none;' +
+ '}' +
+ '.chromeFrameOverlayCloseBar {' +
+ 'height: 1em;' +
+ 'text-align: right;' +
+ 'background-color: #CADEF4;' +
+ '}' +
+ '.chromeFrameOverlayUnderlay {' +
+ 'position: absolute;' +
+ 'width: 100%;' +
+ 'height: 100%;' +
+ 'background-color: white;' +
+ 'opacity: 0.5;' +
+ '-moz-opacity: 0.5;' +
+ '-webkit-opacity: 0.5;' +
+ '-ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";' +
+ 'filter: alpha(opacity=50);' +
+ 'z-index: 2000;' +
+ '}');
+ google.cf.installer.OverlayDelegate.styleInjected_ = true;
+};
+
+/**
+ * Generates the HTML for the overlay.
+ * @private
+ */
+google.cf.installer.OverlayDelegate.injectHtml_ = function() {
+ google.cf.installer.OverlayDelegate.injectCss_();
+ if (document.getElementById('chromeFrameOverlayContent')) {
+ return; // Was previously created. Bail.
+ }
+
+ var n = document.createElement('span');
+ n.innerHTML = '<div class="chromeFrameOverlayUnderlay"></div>' +
+ '<table class="chromeFrameOverlayContent"' +
+ 'id="chromeFrameOverlayContent"' +
+ 'cellpadding="0" cellspacing="0">' +
+ '<tr class="chromeFrameOverlayCloseBar">' +
+ '<td>' +
+ // TODO(user): i18n
+ '<button id="chromeFrameCloseButton">close</button>' +
+ '</td>' +
+ '</tr>' +
+ '<tr>' +
+ '<td id="chromeFrameIframeHolder"></td>' +
+ '</tr>' +
+ '</table>';
+
+ var b = document.body;
+ // Insert underlay nodes into the document in the right order.
+ while (n.firstChild) {
+ b.insertBefore(n.lastChild, b.firstChild);
+ }
+};
+
+/**
+ * @inheritDoc
+ */
+google.cf.installer.OverlayDelegate.prototype.getIFrameContainer =
+ function() {
+ google.cf.installer.OverlayDelegate.injectHtml_();
+ document.getElementById('chromeFrameCloseButton').onclick =
+ goog.bind(this.reset, this);
+ return /** @type {!HTMLElement} */(
+ document.getElementById('chromeFrameIframeHolder'));
+};
+
+/**
+ * @inheritDoc
+ */
+google.cf.installer.OverlayDelegate.prototype.customizeIFrame =
+ function(iframe) {
+ google.cf.installer.frame.setProperties(iframe, this.args_);
+};
+
+/**
+ * @inheritDoc
+ */
+google.cf.installer.OverlayDelegate.prototype.show = function() {
+ // Should start it out hidden and reveal/resize here.
+};
+
+/**
+ * @inheritDoc
+ */
+google.cf.installer.OverlayDelegate.prototype.reset = function() {
+ // IE has a limit to the # of <style> tags allowed, so we avoid
+ // tempting the fates.
+ if (google.cf.installer.OverlayDelegate.hideInjected_)
+ return;
+
+ goog.style.installStyles(
+ '.chromeFrameOverlayContent { display: none; } ' +
+ '.chromeFrameOverlayUnderlay { display: none; }');
+ document.getElementById('chromeFrameIframeHolder').removeChild(
+ document.getElementById('chromeFrameIframeHolder').firstChild);
+
+ document.getElementById('chromeFrameCloseButton').onclick = null;
+
+// TODO(user): put this in somewhere.
+// // Hide the dialog for a year (or until cookies are deleted).
+// var age = 365 * 24 * 60 * 60 * 1000;
+// document.cookie = "disableGCFCheck=1;path=/;max-age="+age;
+ google.cf.installer.OverlayDelegate.hideInjected_ = true;
+};
diff --git a/chrome_frame/cfinstall/src/stub/prompt.js b/chrome_frame/cfinstall/src/stub/prompt.js
new file mode 100644
index 0000000..bf5ccee
--- /dev/null
+++ b/chrome_frame/cfinstall/src/stub/prompt.js
@@ -0,0 +1,210 @@
+// Copyright (c) 2011 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 Implements an in-site integration of the Chrome Frame
+ * installation flow by loading its implementation on demand.
+ **/
+
+goog.provide('google.cf.installer.Prompt');
+
+goog.require('google.cf.installer.InteractionDelegate');
+
+/**
+ * Constructs a prompt flow that loads its implementation from an external
+ * Javascript file.
+ * @constructor
+ * @param {Window=} opt_windowInstance The window in which to load the external
+ * script. Defaults to the global window object.
+ */
+google.cf.installer.Prompt = function(opt_windowInstance) {
+ this.window_ = opt_windowInstance || window;
+};
+
+/**
+ * An optional adapter to customize the display of the installation flow.
+ * @type {!google.cf.installer.InteractionDelegate|undefined}
+ * @private
+ */
+google.cf.installer.Prompt.prototype.customInteractionDelegate_ = undefined;
+
+/**
+ * An optional URL to a resource in the same domain as the calling site that
+ * will be used to transport installation results back to the client.
+ */
+google.cf.installer.Prompt.prototype.
+ manuallySpecifiedSameDomainResourceUri_ = undefined;
+
+/**
+ * Customizes the display of the prompt via the given adapter.
+ * @param {!google.cf.installer.InteractionDelegate} interactionDelegate The
+ * adapter.
+ */
+google.cf.installer.Prompt.prototype.setInteractionDelegate =
+ function(interactionDelegate) {
+ this.customInteractionDelegate_ = interactionDelegate;
+};
+
+/**
+ * Specifies a resource in the same domain as the calling site that will be used
+ * to carry installation results across domain boundaries.
+ * @param {string} uri The resource URI to use.
+ */
+google.cf.installer.Prompt.prototype.setSameDomainResourceUri = function(uri) {
+ this.manuallySpecifiedSameDomainResourceUri_ = uri;
+};
+
+/**
+ * Holds the loaded installation flow execution method. See
+ * CrossDomainInstall.execute (crossdomaininstall.js).
+ * @type {?function(function(), function()=, string=,
+ * google.cf.installer.InteractionDelegate=, string=)}
+ * @private
+ **/
+google.cf.installer.Prompt.prototype.installProc_ = null;
+
+/**
+ * @define {string} Defines the default implementation location.
+ **/
+google.cf.installer.Prompt.DEFAULT_IMPLEMENTATION_URL =
+ '//ajax.googleapis.com/ajax/libs/chrome-frame/2/CFInstall.impl.min.js';
+
+/**
+ * Defines the URL from which the full prompting logic will be retrieved.
+ * @type {string}
+ * @private
+ **/
+google.cf.installer.Prompt.prototype.implementationUrl_ =
+ google.cf.installer.Prompt.DEFAULT_IMPLEMENTATION_URL;
+
+/**
+ * Defines a custom URL for the Chrome Frame download page.
+ * @type {string|undefined}
+ * @private
+ */
+google.cf.installer.Prompt.prototype.downloadPageUrl_ = undefined;
+
+/**
+ * Overrides the default URL for loading the implementation.
+ * @param {string} url The custom URL.
+ */
+google.cf.installer.Prompt.prototype.setImplementationUrl = function(url) {
+ this.implementationUrl_ = url;
+};
+
+/**
+ * Overrides the default URL for the download page.
+ * @param {string} url The custom URL.
+ */
+google.cf.installer.Prompt.prototype.setDownloadPageUrl = function(url) {
+ this.downloadPageUrl_ = url;
+};
+
+/**
+ * Initiates loading of the full implementation if not already initiated.
+ * @param {function()=} opt_loadCompleteHandler A callback that will be notified
+ * when the loading of the script has completed, possibly unsuccessfully.
+ **/
+google.cf.installer.Prompt.prototype.loadInstallProc_ =
+ function(opt_loadCompleteHandler) {
+ var scriptParent = this.window_.document.getElementsByTagName('head')[0] ||
+ this.window_.document.documentElement;
+ var scriptEl = this.window_.document.createElement('script');
+ scriptEl.src = this.implementationUrl_;
+ scriptEl.type = 'text/javascript';
+
+ if (opt_loadCompleteHandler) {
+ var loadHandler = goog.bind(function() {
+ scriptEl.onreadystatechange = null;
+ scriptEl.onerror = null;
+ scriptEl.onload = null;
+ loadHandler = function(){};
+ opt_loadCompleteHandler();
+ }, this);
+
+ scriptEl.onload = loadHandler;
+ scriptEl.onerror = loadHandler;
+ scriptEl.onreadystatechange = function() {
+ if (scriptEl.readyState == 'loaded')
+ loadHandler();
+ };
+ }
+
+ scriptParent.appendChild(scriptEl);
+};
+
+/**
+ * Invokes the installation procedure with our configured parameters and
+ * the provided callbacks.
+ * @param {function()} successHandler The method to invoke upon installation
+ * success.
+ * @param {function()} opt_failureHandler The method to invoke upon installation
+ * failure.
+ */
+google.cf.installer.Prompt.prototype.invokeProc_ =
+ function(successHandler, opt_failureHandler) {
+ this.installProc_(successHandler,
+ opt_failureHandler,
+ this.downloadPageUrl_,
+ this.customInteractionDelegate_,
+ this.manuallySpecifiedSameDomainResourceUri_);
+}
+
+/**
+ * Receives a handle to the flow implementation method and invokes it.
+ * @param {function(function(), function()=, string=,
+ * google.cf.installer.InteractionDelegate=, string=)}
+ * installProc The install execution method. See
+ * CrossDomainInstall.execute().
+ * @param {function()} successHandler The method to invoke upon installation
+ * success.
+ * @param {function()} opt_failureHandler The method to invoke upon installation
+ * failure.
+ */
+google.cf.installer.Prompt.prototype.onProcLoaded_ =
+ function(installProc, successHandler, opt_failureHandler) {
+ this.window_['CF_google_cf_xd_install_stub'] = undefined;
+ this.installProc_ = installProc;
+ this.invokeProc_(successHandler, opt_failureHandler);
+};
+
+/**
+ * Loads and executes the in-line Google Chrome Frame installation flow.
+ * Will typically execute asynchronously (as the flow behaviour is not yet
+ * loaded).
+ *
+ * @param {function()} successHandler A function to invoke once Google
+ * Chrome Frame is successfully installed. Overrides the default
+ * behaviour, which is to reload the current page.
+ * @param {function()=} opt_failureHandler A function to invoke if the
+ * installation fails. The default behaviour is to do nothing.
+ */
+google.cf.installer.Prompt.prototype.open = function(successHandler,
+ opt_failureHandler) {
+ if (this.installProc_) {
+ this.invokeProc_(successHandler, opt_failureHandler);
+ return;
+ }
+
+ if (this.window_['CF_google_cf_xd_install_stub']) {
+ if (opt_failureHandler)
+ opt_failureHandler();
+ return;
+ }
+
+ this.window_['CF_google_cf_xd_install_stub'] = goog.bind(
+ function(installProc) {
+ this.onProcLoaded_(installProc, successHandler, opt_failureHandler);
+ }, this);
+
+ var loadCompleteHandler = undefined;
+ if (opt_failureHandler) {
+ loadCompleteHandler = goog.bind(function() {
+ if (!this.installProc_)
+ opt_failureHandler();
+ }, this);
+ }
+
+ this.loadInstallProc_(loadCompleteHandler);
+};