Commit 4120bcf3 authored by sergeyu@chromium.org's avatar sergeyu@chromium.org

Download the host components when user tries to enable Me2Me host.

Now when NPAPI plugin is not present the host setup wizard detects
when the host is not installed and asks the user to install it.

BUG=339626

Review URL: https://codereview.chromium.org/132793007

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@248604 0039d316-1c4b-4281-b951-d872f2087c98
parent ca20ea8f
......@@ -15,6 +15,10 @@ remoting.HostController = function() {
/** @type {HTMLElement} @private */
var container = document.getElementById('daemon-plugin-container');
container.appendChild(plugin);
if (plugin.hasOwnProperty('REQUESTED_ACCESS_CODE')) {
container.removeChild(plugin);
return null;
}
return plugin;
};
......@@ -472,5 +476,13 @@ remoting.HostController.prototype.clearPairedClients = function(
this.hostDispatcher_.clearPairedClients(onDone, onError);
};
/**
* Returns true if the NPAPI plugin is being used.
* @return {boolean}
*/
remoting.HostController.prototype.usingNpapiPlugin = function() {
return this.hostDispatcher_.usingNpapiPlugin();
}
/** @type {remoting.HostController} */
remoting.hostController = null;
......@@ -28,9 +28,6 @@ var remoting = remoting || {};
* unsupported.
*/
remoting.HostDispatcher = function(createPluginCallback) {
/** @type {remoting.HostDispatcher} */
var that = this;
/** @type {remoting.HostNativeMessaging} @private */
this.nativeMessagingHost_ = new remoting.HostNativeMessaging();
......@@ -43,23 +40,44 @@ remoting.HostDispatcher = function(createPluginCallback) {
/** @type {Array.<function()>} */
this.pendingRequests_ = [];
this.createPluginCallback_ = createPluginCallback;
this.tryToInitialize_();
}
/** @enum {number} */
remoting.HostDispatcher.State = {
UNKNOWN: 0,
NATIVE_MESSAGING: 1,
NPAPI: 2,
NOT_INSTALLED: 3
};
remoting.HostDispatcher.prototype.tryToInitialize_ = function() {
/** @type {remoting.HostDispatcher} */
var that = this;
if (this.state_ != remoting.HostDispatcher.State.UNKNOWN)
return;
function sendPendingRequests() {
for (var i = 0; i < that.pendingRequests_.length; i++) {
that.pendingRequests_[i]();
var pendingRequests = that.pendingRequests_;
that.pendingRequests_ = [];
for (var i = 0; i < pendingRequests.length; i++) {
pendingRequests[i]();
}
that.pendingRequests_ = null;
}
function onNativeMessagingInit() {
console.log('Native Messaging supported.');
that.state_ = remoting.HostDispatcher.State.NATIVE_MESSAGING;
sendPendingRequests();
}
function onNativeMessagingFailed(error) {
console.log('Native Messaging unsupported, falling back to NPAPI.');
that.npapiHost_ = createPluginCallback();
that.state_ = remoting.HostDispatcher.State.NPAPI;
that.npapiHost_ = that.createPluginCallback_();
that.state_ = that.npapiHost_ ? remoting.HostDispatcher.State.NPAPI
: remoting.HostDispatcher.State.NOT_INSTALLED;
sendPendingRequests();
}
......@@ -67,13 +85,6 @@ remoting.HostDispatcher = function(createPluginCallback) {
onNativeMessagingFailed);
};
/** @enum {number} */
remoting.HostDispatcher.State = {
UNKNOWN: 0,
NATIVE_MESSAGING: 1,
NPAPI: 2
};
/**
* @param {remoting.HostController.Feature} feature The feature to test for.
* @param {function(boolean):void} onDone
......@@ -98,6 +109,9 @@ remoting.HostDispatcher.prototype.hasFeature = function(
}
onDone(supportedFeatures.indexOf(feature) >= 0);
break;
case remoting.HostDispatcher.State.NOT_INSTALLED:
onDone(false);
break;
}
};
......@@ -122,6 +136,9 @@ remoting.HostDispatcher.prototype.getHostName = function(onDone, onError) {
onError(remoting.Error.MISSING_PLUGIN);
}
break;
case remoting.HostDispatcher.State.NOT_INSTALLED:
onError(remoting.Error.MISSING_PLUGIN);
break;
}
};
......@@ -149,6 +166,9 @@ remoting.HostDispatcher.prototype.getPinHash =
onError(remoting.Error.MISSING_PLUGIN);
}
break;
case remoting.HostDispatcher.State.NOT_INSTALLED:
onError(remoting.Error.MISSING_PLUGIN);
break;
}
};
......@@ -173,6 +193,9 @@ remoting.HostDispatcher.prototype.generateKeyPair = function(onDone, onError) {
onError(remoting.Error.MISSING_PLUGIN);
}
break;
case remoting.HostDispatcher.State.NOT_INSTALLED:
onError(remoting.Error.MISSING_PLUGIN);
break;
}
};
......@@ -199,6 +222,9 @@ remoting.HostDispatcher.prototype.updateDaemonConfig =
onError(remoting.Error.MISSING_PLUGIN);
}
break;
case remoting.HostDispatcher.State.NOT_INSTALLED:
onError(remoting.Error.MISSING_PLUGIN);
break;
}
};
......@@ -238,6 +264,9 @@ remoting.HostDispatcher.prototype.getDaemonConfig = function(onDone, onError) {
onError(remoting.Error.MISSING_PLUGIN);
}
break;
case remoting.HostDispatcher.State.NOT_INSTALLED:
onDone({});
break;
}
};
......@@ -262,6 +291,9 @@ remoting.HostDispatcher.prototype.getDaemonVersion = function(onDone, onError) {
onError(remoting.Error.MISSING_PLUGIN);
}
break;
case remoting.HostDispatcher.State.NOT_INSTALLED:
onError(remoting.Error.MISSING_PLUGIN);
break;
}
};
......@@ -287,6 +319,9 @@ remoting.HostDispatcher.prototype.getUsageStatsConsent =
onError(remoting.Error.MISSING_PLUGIN);
}
break;
case remoting.HostDispatcher.State.NOT_INSTALLED:
onError(remoting.Error.MISSING_PLUGIN);
break;
}
};
......@@ -314,6 +349,9 @@ remoting.HostDispatcher.prototype.startDaemon =
onError(remoting.Error.MISSING_PLUGIN);
}
break;
case remoting.HostDispatcher.State.NOT_INSTALLED:
onError(remoting.Error.MISSING_PLUGIN);
break;
}
};
......@@ -337,6 +375,9 @@ remoting.HostDispatcher.prototype.stopDaemon = function(onDone, onError) {
onError(remoting.Error.MISSING_PLUGIN);
}
break;
case remoting.HostDispatcher.State.NOT_INSTALLED:
onError(remoting.Error.MISSING_PLUGIN);
break;
}
};
......@@ -346,10 +387,27 @@ remoting.HostDispatcher.prototype.stopDaemon = function(onDone, onError) {
* @return {void}
*/
remoting.HostDispatcher.prototype.getDaemonState = function(onDone, onError) {
// If the host was in not-initialized state try initializing it again in case
// it was installed.
if (this.state_ == remoting.HostDispatcher.State.NOT_INSTALLED) {
this.state_ = remoting.HostDispatcher.State.UNKNOWN;
this.tryToInitialize_();
}
this.getDaemonStateInternal_(onDone, onError);
}
/**
* @param {function(remoting.HostController.State):void} onDone
* @param {function(remoting.Error):void} onError
* @return {void}
*/
remoting.HostDispatcher.prototype.getDaemonStateInternal_ =
function(onDone, onError) {
switch (this.state_) {
case remoting.HostDispatcher.State.UNKNOWN:
this.pendingRequests_.push(
this.getDaemonState.bind(this, onDone, onError));
this.getDaemonStateInternal_.bind(this, onDone, onError));
break;
case remoting.HostDispatcher.State.NATIVE_MESSAGING:
this.nativeMessagingHost_.getDaemonState(onDone, onError);
......@@ -364,6 +422,9 @@ remoting.HostDispatcher.prototype.getDaemonState = function(onDone, onError) {
onDone(state);
}
break;
case remoting.HostDispatcher.State.NOT_INSTALLED:
onDone(remoting.HostController.State.NOT_INSTALLED);
break;
}
};
......@@ -404,6 +465,9 @@ remoting.HostDispatcher.prototype.getPairedClients = function(onDone, onError) {
onError(remoting.Error.MISSING_PLUGIN);
}
break;
case remoting.HostDispatcher.State.NOT_INSTALLED:
onError(remoting.Error.MISSING_PLUGIN);
break;
}
};
......@@ -449,6 +513,9 @@ remoting.HostDispatcher.prototype.clearPairedClients =
onError(remoting.Error.MISSING_PLUGIN);
}
break;
case remoting.HostDispatcher.State.NOT_INSTALLED:
onError(remoting.Error.MISSING_PLUGIN);
break;
}
};
......@@ -477,6 +544,9 @@ remoting.HostDispatcher.prototype.deletePairedClient =
onError(remoting.Error.MISSING_PLUGIN);
}
break;
case remoting.HostDispatcher.State.NOT_INSTALLED:
onError(remoting.Error.MISSING_PLUGIN);
break;
}
};
......@@ -500,6 +570,9 @@ remoting.HostDispatcher.prototype.getHostClientId =
// doesn't have access to the API keys baked into the installed host.
onError(remoting.Error.UNEXPECTED);
break;
case remoting.HostDispatcher.State.NOT_INSTALLED:
onError(remoting.Error.MISSING_PLUGIN);
break;
}
};
......@@ -526,5 +599,16 @@ remoting.HostDispatcher.prototype.getCredentialsFromAuthCode =
// doesn't have access to the API keys baked into the installed host.
onError(remoting.Error.UNEXPECTED);
break;
case remoting.HostDispatcher.State.NOT_INSTALLED:
onError(remoting.Error.MISSING_PLUGIN);
break;
}
};
/**
* Returns true if the NPAPI plugin is being used.
* @return {boolean}
*/
remoting.HostDispatcher.prototype.usingNpapiPlugin = function() {
return this.state_ == remoting.HostDispatcher.State.NPAPI;
}
......@@ -80,7 +80,9 @@ remoting.HostList = function(table, noHosts, errorMsg, errorButton,
* @type {remoting.HostController.State}
* @private
*/
this.localHostState_ = remoting.HostController.State.NOT_IMPLEMENTED;
this.localHostState_ = remoting.isMe2MeSupported()
? remoting.HostController.State.NOT_INSTALLED
: remoting.HostController.State.NOT_IMPLEMENTED;
/**
* @type {number}
* @private
......
......@@ -365,11 +365,13 @@ remoting.HostNativeMessaging.prototype.onDisconnect_ = function() {
console.error('Native Message port disconnected');
// Notify the error-handlers of any requests that are still outstanding.
for (var id in this.pendingReplies_) {
this.pendingReplies_[/** @type {number} */(id)].onError(
var pendingReplies = this.pendingReplies_;
this.pendingReplies_ = {};
for (var id in pendingReplies) {
pendingReplies[/** @type {number} */(id)].onError(
remoting.Error.UNEXPECTED);
}
this.pendingReplies_ = {};
}
/**
......
......@@ -27,7 +27,7 @@ remoting.HostSetupFlow.State = {
// Dialog states.
ASK_PIN: 1,
// Used on Mac OS X to prompt the user to manually install a .dmg package.
// Prompts the user to install the host package.
INSTALL_HOST: 2,
// Processing states.
......@@ -223,6 +223,7 @@ remoting.HostSetupDialog.prototype.showForStartWithToken_ =
this.hostController_.getConsent(onGetConsent, onError);
var flow = [
remoting.HostSetupFlow.State.INSTALL_HOST,
remoting.HostSetupFlow.State.ASK_PIN,
remoting.HostSetupFlow.State.STARTING_HOST,
remoting.HostSetupFlow.State.HOST_STARTED];
......@@ -231,8 +232,12 @@ remoting.HostSetupDialog.prototype.showForStartWithToken_ =
state != remoting.HostController.State.NOT_INSTALLED &&
state != remoting.HostController.State.INSTALLING;
if (navigator.platform.indexOf('Mac') != -1 && !installed) {
flow.unshift(remoting.HostSetupFlow.State.INSTALL_HOST);
// Skip the installation step when the host is already installed or when using
// NPAPI plugin on Windows (because on Windows the plugin takes care of
// installation).
if (installed || (navigator.platform == 'Win32' &&
this.hostController_.usingNpapiPlugin())) {
flow.shift();
}
this.startNewFlow_(flow);
......@@ -325,8 +330,7 @@ remoting.HostSetupDialog.prototype.updateState_ = function() {
remoting.setMode(remoting.AppMode.HOST_SETUP_ASK_PIN);
} else if (state == remoting.HostSetupFlow.State.INSTALL_HOST) {
remoting.setMode(remoting.AppMode.HOST_SETUP_INSTALL);
window.location =
'https://dl.google.com/chrome-remote-desktop/chromeremotedesktop.dmg';
this.installHost_();
} else if (state == remoting.HostSetupFlow.State.STARTING_HOST) {
showProcessingMessage(/*i18n-content*/'HOST_SETUP_STARTING');
this.startHost_();
......@@ -356,6 +360,36 @@ remoting.HostSetupDialog.prototype.updateState_ = function() {
}
};
/**
* Installs Host component.
*/
remoting.HostSetupDialog.prototype.installHost_ = function() {
var hostPackageUrl = '';
switch (navigator.platform) {
case 'Win32':
hostPackageUrl = 'http://dl.google.com/dl/edgedl/chrome-remote-desktop/chromeremotedesktophost.msi';
break;
case 'MacIntel':
hostPackageUrl = 'https://dl.google.com/chrome-remote-desktop/chromeremotedesktop.dmg';
break;
case 'Linux x86_64':
hostPackageUrl = 'https://dl.google.com/linux/direct/chrome-remote-desktop_current_amd64.deb';
break;
case 'Linux i386':
hostPackageUrl = 'https://dl.google.com/linux/direct/chrome-remote-desktop_current_i386.deb';
break;
default:
// We never expect to get in this state. Host controls should not be shown
// on unsupported platform.
this.flow_.switchToErrorState(remoting.Error.UNEXPECTED);
this.updateState_();
return;
}
// Start downloading the package.
window.location = hostPackageUrl;
}
/**
* Registers and starts the host.
*/
......
......@@ -150,6 +150,26 @@ function isIT2MeSupported_() {
return !remoting.runningOnChromeOS();
}
// TODO(sergeyu): We want to show Me2Me host controls only on some Linux
// distributions that we know work properly with the chromoting host. Implement
// dome detection mechanism and apply it here.
/** @type {boolean} */
remoting.supportedLinuxDistibutionDetected_ = false;
/**
* @return {boolean}
*/
remoting.isMe2MeSupported = function isMe2MeSupported() {
/** @type {string} */
var platform = navigator.platform;
// Currently Me2Me is supported on Windows, OSX and some versions of Linux.
return platform == 'Win32' || platform == 'MacIntel' ||
((platform == 'Linux x86_64' || platform == 'Linux i386') &&
remoting.supportedLinuxDistibutionDetected_ &&
!remoting.runningOnChromeOS());
}
/**
* Display the user's email address and allow access to the rest of the app,
* including parsing URL parameters.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment