Home | History | Annotate | Download | only in webapp
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 /**
      6  * @fileoverview
      7  *
      8  * HostInstaller allows the caller to download the host binary and monitor the
      9  * install progress of the host by pinging the host periodically via native
     10  * messaging.
     11  *
     12  * To download the host and wait for install:
     13  *   var hostInstaller = new remoting.HostInstaller();
     14  *   hostInstaller.downloadAndWaitForInstall().then(function() {
     15  *      // Install has completed.
     16  *   }, function(){
     17  *      // Download has failed.
     18  *   })
     19  *
     20  * To stop listening to the install progress:
     21  *   hostInstaller.cancel();
     22  */
     23 
     24 'use strict';
     25 
     26 /** @suppress {duplicate} */
     27 var remoting = remoting || {};
     28 
     29 /**
     30  * @constructor
     31  */
     32 remoting.HostInstaller = function() {
     33   /**
     34    * @type {Promise}
     35    * @private
     36    */
     37   this.downloadAndWaitForInstallPromise_ = null;
     38 
     39   /**
     40    * @type {?number}
     41    * @private
     42    */
     43   this.checkInstallIntervalId_ = null;
     44 };
     45 
     46 /**
     47  * @return {Promise}  The promise will resolve to a boolean value indicating
     48  *     whether the host is installed or not.
     49  */
     50 remoting.HostInstaller.prototype.isInstalled = function() {
     51   // Always do a fresh check as we don't get notified when the host is
     52   // uninstalled.
     53 
     54   /** @param {function(*=):void} resolve */
     55   return new Promise(function(resolve) {
     56     // TODO(kelvinp): Use different native messaging ports for the Me2me host
     57     // vs It2MeHost.
     58     /** @type {chrome.runtime.Port} */
     59     var port =
     60         chrome.runtime.connectNative('com.google.chrome.remote_assistance');
     61 
     62     function onMessage() {
     63       port.onDisconnect.removeListener(onDisconnected);
     64       port.onMessage.removeListener(onMessage);
     65       port.disconnect();
     66       resolve(true);
     67     }
     68 
     69     function onDisconnected() {
     70       port.onDisconnect.removeListener(onDisconnected);
     71       port.onMessage.removeListener(onMessage);
     72       resolve(false);
     73     }
     74 
     75     port.onDisconnect.addListener(onDisconnected);
     76     port.onMessage.addListener(onMessage);
     77     port.postMessage({type: 'hello'});
     78   });
     79 };
     80 
     81 /**
     82  * @throws {Error}  Throws if there is no matching host binary for the current
     83  *     platform.
     84  */
     85 remoting.HostInstaller.prototype.download = function() {
     86   /** @type {Object.<string,string>} */
     87   var hostDownloadUrls = {
     88     'Win32' : 'http://dl.google.com/dl/edgedl/chrome-remote-desktop/' +
     89         'chromeremotedesktophost.msi',
     90     'Win64' : 'http://dl.google.com/dl/edgedl/chrome-remote-desktop/' +
     91         'chromeremotedesktophost.msi',
     92     'MacIntel' : 'https://dl.google.com/chrome-remote-desktop/' +
     93         'chromeremotedesktop.dmg',
     94     'Linux x86_64' : 'https://dl.google.com/linux/direct/' +
     95         'chrome-remote-desktop_current_amd64.deb',
     96     'Linux i386' : 'https://dl.google.com/linux/direct/' +
     97         'chrome-remote-desktop_current_i386.deb'
     98   };
     99 
    100   var hostPackageUrl = hostDownloadUrls[navigator.platform];
    101   if (hostPackageUrl === undefined) {
    102     throw new Error(remoting.Error.CANCELLED);
    103   }
    104 
    105   // Start downloading the package.
    106   if (base.isAppsV2()) {
    107     // TODO(jamiewalch): Use chrome.downloads when it is available to
    108     // apps v2 (http://crbug.com/174046)
    109     window.open(hostPackageUrl);
    110   } else {
    111     window.location = hostPackageUrl;
    112   }
    113 };
    114 
    115 /** @return {Promise} */
    116 remoting.HostInstaller.prototype.downloadAndWaitForInstall = function() {
    117   /** @type {remoting.HostInstaller} */
    118   var that = this;
    119   /**
    120    * @type {number}
    121    * @const
    122    */
    123   var CHECK_INSTALL_INTERVAL_IN_MILLISECONDS = 1000;
    124 
    125   /** @param {boolean} installed */
    126   return this.isInstalled().then(function(installed){
    127     if (installed) {
    128       return Promise.resolve(true);
    129     }
    130 
    131     if (that.downloadAndWaitForInstallPromise_ === null) {
    132       that.downloadAndWaitForInstallPromise_ = new Promise(
    133         /** @param {Function} resolve */
    134         function(resolve){
    135           that.download();
    136           that.checkInstallIntervalId_ = window.setInterval(function() {
    137             /** @param {boolean} installed */
    138             that.isInstalled().then(function(installed) {
    139               if (installed) {
    140                 that.cancel();
    141                 resolve();
    142               }
    143             });
    144           }, CHECK_INSTALL_INTERVAL_IN_MILLISECONDS);
    145       });
    146     }
    147     return that.downloadAndWaitForInstallPromise_;
    148   });
    149 };
    150 
    151 /**
    152  * Stops waiting for the host to be installed.
    153  * For example
    154  *   var promise = hostInstaller.downloadAndWaitForInstall();
    155  *   hostInstaller.cancel(); // This will prevent |promise| from fulfilling.
    156  */
    157 remoting.HostInstaller.prototype.cancel = function() {
    158   if (this.checkInstallIntervalId_ !== null) {
    159     window.clearInterval(this.checkInstallIntervalId_);
    160     this.checkInstallIntervalId_ = null;
    161   }
    162   this.downloadAndWaitForInstallPromise_ = null;
    163 };
    164