// 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); };