Added daemon process NPAPI.

This provides a framework that we can implement per-platform to allow the
Me2Me daemon to installed, started and stopped by the web-app.

I've gone with a polling-based API for now, as it simplifies some of
the logic. We can revisit this if necessary to make it more sophisticated.

BUG=None
TEST=None until we have some implementations.


Review URL: http://codereview.chromium.org/9316078

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@120723 0039d316-1c4b-4281-b951-d872f2087c98
parent 95835366
// Copyright (c) 2012 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.
#ifndef REMOTING_HOST_DAEMON_CONTROLLER_H_
#define REMOTING_HOST_DAEMON_CONTROLLER_H_
#include <string>
namespace remoting {
class DaemonController {
public:
enum State {
// Placeholder state for platforms on which the daemon process is not
// implemented. The web-app will not show the corresponding UI. This value
// will eventually be deprecated or removed.
STATE_NOT_IMPLEMENTED = -1,
// The daemon process is not installed. This is functionally equivalent
// to STATE_STOPPED, but the start method is expected to be significantly
// slower, and might involve user interaction. It might be appropriate to
// indicate this in the UI.
STATE_NOT_INSTALLED = 0,
// The daemon process is installed but not running. Call Start to start it.
STATE_STOPPED = 1,
// The daemon process is running. Call Start again to change the PIN or
// Stop to stop it.
STATE_STARTED = 2,
// The previous Start operation failed. This is functionally equivalent
// to STATE_STOPPED, but the UI should report an error in this state.
// This state should not persist across restarts of the NPAPI process.
STATE_START_FAILED = 3,
// The state cannot be determined. This could indicate that the plugin
// has not been provided with sufficient information, for example, the
// user for which to query state on a multi-user system.
STATE_UNKNOWN = 4
};
virtual ~DaemonController() {}
// Return the "installed/running" state of the daemon process.
virtual State GetState() = 0;
// Set the PIN for accessing this host, which should be expressed as a
// UTF8-encoded string. It is permitted to call SetPin when the daemon
// is already running. Returns true if successful, or false if the PIN
// does not satisfy complexity requirements.
//
// TODO(jamiewalch): More state-setting methods needed here. Sufficient
// state must be set prior to calling any other DaemonController method;
// this should be documented for each method.
virtual bool SetPin(const std::string& pin) = 0;
// Start the daemon process. Since this may require that the daemon be
// downloaded and installed, this may take a long time--poll GetState
// until the state is STATE_STARTED or STATE_START_FAILED. Start fails
// synchronously and returns false if sufficient state has not been set,
// including a valid PIN.
virtual bool Start() = 0;
// Stop the daemon process. It is permitted to call Stop while the daemon
// process is being installed, in which case the installation should be
// aborted if possible; if not then it is sufficient to ensure that the
// daemon process is not started automatically upon successful installation.
// Returns false if sufficient state has not been set; Stop is not permitted
// to fail for any other reason.
virtual bool Stop() = 0;
static DaemonController* Create();
};
} // namespace remoting
#endif // REMOTING_HOST_DAEMON_CONTROLLER_H_
// Copyright (c) 2012 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.
#include "remoting/host/plugin/daemon_controller.h"
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
namespace remoting {
namespace {
class DaemonControllerLinux : public remoting::DaemonController {
public:
DaemonControllerLinux();
virtual State GetState() OVERRIDE;
virtual bool SetPin(const std::string& pin) OVERRIDE;
virtual bool Start() OVERRIDE;
virtual bool Stop() OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(DaemonControllerLinux);
};
DaemonControllerLinux::DaemonControllerLinux() {
}
remoting::DaemonController::State DaemonControllerLinux::GetState() {
return remoting::DaemonController::STATE_NOT_IMPLEMENTED;
}
bool DaemonControllerLinux::SetPin(const std::string& pin) {
NOTIMPLEMENTED();
return false;
}
bool DaemonControllerLinux::Start() {
NOTIMPLEMENTED();
return false;
}
bool DaemonControllerLinux::Stop() {
NOTIMPLEMENTED();
return false;
}
} // namespace
DaemonController* remoting::DaemonController::Create() {
return new DaemonControllerLinux();
}
} // namespace remoting
// Copyright (c) 2012 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.
#include "remoting/host/plugin/daemon_controller.h"
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
namespace remoting {
namespace {
class DaemonControllerMac : public remoting::DaemonController {
public:
DaemonControllerMac();
virtual State GetState() OVERRIDE;
virtual bool SetPin(const std::string& pin) OVERRIDE;
virtual bool Start() OVERRIDE;
virtual bool Stop() OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(DaemonControllerMac);
};
DaemonControllerMac::DaemonControllerMac() {
}
remoting::DaemonController::State DaemonControllerMac::GetState() {
return remoting::DaemonController::STATE_NOT_IMPLEMENTED;
}
bool DaemonControllerMac::SetPin(const std::string& pin) {
NOTIMPLEMENTED();
return false;
}
bool DaemonControllerMac::Start() {
NOTIMPLEMENTED();
return false;
}
bool DaemonControllerMac::Stop() {
NOTIMPLEMENTED();
return false;
}
} // namespace
DaemonController* remoting::DaemonController::Create() {
return new DaemonControllerMac();
}
} // namespace remoting
// Copyright (c) 2012 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.
#include "remoting/host/plugin/daemon_controller.h"
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
namespace remoting {
namespace {
class DaemonControllerWin : public remoting::DaemonController {
public:
DaemonControllerWin();
virtual State GetState() OVERRIDE;
virtual bool SetPin(const std::string& pin) OVERRIDE;
virtual bool Start() OVERRIDE;
virtual bool Stop() OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(DaemonControllerWin);
};
DaemonControllerWin::DaemonControllerWin() {
}
remoting::DaemonController::State DaemonControllerWin::GetState() {
return remoting::DaemonController::STATE_NOT_IMPLEMENTED;
}
bool DaemonControllerWin::SetPin(const std::string& pin) {
NOTIMPLEMENTED();
return false;
}
bool DaemonControllerWin::Start() {
NOTIMPLEMENTED();
return false;
}
bool DaemonControllerWin::Stop() {
NOTIMPLEMENTED();
return false;
}
} // namespace
DaemonController* remoting::DaemonController::Create() {
return new DaemonControllerWin();
}
} // namespace remoting
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "remoting/host/plugin/host_script_object.h" #include "remoting/host/plugin/host_script_object.h"
#include "remoting/host/plugin/daemon_controller.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/message_loop.h" #include "base/message_loop.h"
...@@ -25,37 +26,12 @@ ...@@ -25,37 +26,12 @@
namespace remoting { namespace remoting {
// Supported Javascript interface:
// readonly attribute string accessCode;
// readonly attribute int accessCodeLifetime;
// readonly attribute string client;
// readonly attribute int state;
//
// state: {
// DISCONNECTED,
// STARTING,
// REQUESTED_ACCESS_CODE,
// RECEIVED_ACCESS_CODE,
// CONNECTED,
// DISCONNECTING,
// ERROR,
// }
//
// attribute Function void logDebugInfo(string);
// attribute Function void onNatTraversalPolicyChanged(boolean);
// attribute Function void onStateChanged(state);
//
// // The |auth_service_with_token| parameter should be in the format
// // "auth_service:auth_token". An example would be "oauth2:1/2a3912vd".
// void connect(string uid, string auth_service_with_token);
// void disconnect();
// void localize(string (*localize_func)(string,...));
namespace { namespace {
const char* kAttrNameAccessCode = "accessCode"; const char* kAttrNameAccessCode = "accessCode";
const char* kAttrNameAccessCodeLifetime = "accessCodeLifetime"; const char* kAttrNameAccessCodeLifetime = "accessCodeLifetime";
const char* kAttrNameClient = "client"; const char* kAttrNameClient = "client";
const char* kAttrNameDaemonState = "daemonState";
const char* kAttrNameState = "state"; const char* kAttrNameState = "state";
const char* kAttrNameLogDebugInfo = "logDebugInfo"; const char* kAttrNameLogDebugInfo = "logDebugInfo";
const char* kAttrNameOnNatTraversalPolicyChanged = const char* kAttrNameOnNatTraversalPolicyChanged =
...@@ -64,6 +40,9 @@ const char* kAttrNameOnStateChanged = "onStateChanged"; ...@@ -64,6 +40,9 @@ const char* kAttrNameOnStateChanged = "onStateChanged";
const char* kFuncNameConnect = "connect"; const char* kFuncNameConnect = "connect";
const char* kFuncNameDisconnect = "disconnect"; const char* kFuncNameDisconnect = "disconnect";
const char* kFuncNameLocalize = "localize"; const char* kFuncNameLocalize = "localize";
const char* kFuncNameSetDaemonPin = "setDaemonPin";
const char* kFuncNameStartDaemon = "startDaemon";
const char* kFuncNameStopDaemon = "stopDaemon";
// States. // States.
const char* kAttrNameDisconnected = "DISCONNECTED"; const char* kAttrNameDisconnected = "DISCONNECTED";
...@@ -90,6 +69,7 @@ HostNPScriptObject::HostNPScriptObject( ...@@ -90,6 +69,7 @@ HostNPScriptObject::HostNPScriptObject(
new PluginMessageLoopProxy(plugin_thread_delegate)), new PluginMessageLoopProxy(plugin_thread_delegate)),
host_context_(plugin_message_loop_proxy_), host_context_(plugin_message_loop_proxy_),
failed_login_attempts_(0), failed_login_attempts_(0),
daemon_controller_(DaemonController::Create()),
disconnected_event_(true, false), disconnected_event_(true, false),
am_currently_logging_(false), am_currently_logging_(false),
nat_traversal_enabled_(false), nat_traversal_enabled_(false),
...@@ -147,7 +127,10 @@ bool HostNPScriptObject::HasMethod(const std::string& method_name) { ...@@ -147,7 +127,10 @@ bool HostNPScriptObject::HasMethod(const std::string& method_name) {
CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_); CHECK_EQ(base::PlatformThread::CurrentId(), np_thread_id_);
return (method_name == kFuncNameConnect || return (method_name == kFuncNameConnect ||
method_name == kFuncNameDisconnect || method_name == kFuncNameDisconnect ||
method_name == kFuncNameLocalize); method_name == kFuncNameLocalize ||
method_name == kFuncNameSetDaemonPin ||
method_name == kFuncNameStartDaemon ||
method_name == kFuncNameStopDaemon);
} }
bool HostNPScriptObject::InvokeDefault(const NPVariant* args, bool HostNPScriptObject::InvokeDefault(const NPVariant* args,
...@@ -171,6 +154,12 @@ bool HostNPScriptObject::Invoke(const std::string& method_name, ...@@ -171,6 +154,12 @@ bool HostNPScriptObject::Invoke(const std::string& method_name,
return Disconnect(args, argCount, result); return Disconnect(args, argCount, result);
} else if (method_name == kFuncNameLocalize) { } else if (method_name == kFuncNameLocalize) {
return Localize(args, argCount, result); return Localize(args, argCount, result);
} else if (method_name == kFuncNameSetDaemonPin) {
return SetDaemonPin(args, argCount, result);
} else if (method_name == kFuncNameStartDaemon) {
return StartDaemon(args, argCount, result);
} else if (method_name == kFuncNameStopDaemon) {
return StopDaemon(args, argCount, result);
} else { } else {
SetException("Invoke: unknown method " + method_name); SetException("Invoke: unknown method " + method_name);
return false; return false;
...@@ -183,6 +172,7 @@ bool HostNPScriptObject::HasProperty(const std::string& property_name) { ...@@ -183,6 +172,7 @@ bool HostNPScriptObject::HasProperty(const std::string& property_name) {
return (property_name == kAttrNameAccessCode || return (property_name == kAttrNameAccessCode ||
property_name == kAttrNameAccessCodeLifetime || property_name == kAttrNameAccessCodeLifetime ||
property_name == kAttrNameClient || property_name == kAttrNameClient ||
property_name == kAttrNameDaemonState ||
property_name == kAttrNameState || property_name == kAttrNameState ||
property_name == kAttrNameLogDebugInfo || property_name == kAttrNameLogDebugInfo ||
property_name == kAttrNameOnNatTraversalPolicyChanged || property_name == kAttrNameOnNatTraversalPolicyChanged ||
...@@ -228,6 +218,9 @@ bool HostNPScriptObject::GetProperty(const std::string& property_name, ...@@ -228,6 +218,9 @@ bool HostNPScriptObject::GetProperty(const std::string& property_name,
} else if (property_name == kAttrNameClient) { } else if (property_name == kAttrNameClient) {
*result = NPVariantFromString(client_username_); *result = NPVariantFromString(client_username_);
return true; return true;
} else if (property_name == kAttrNameDaemonState) {
INT32_TO_NPVARIANT(daemon_controller_->GetState(), *result);
return true;
} else if (property_name == kAttrNameDisconnected) { } else if (property_name == kAttrNameDisconnected) {
INT32_TO_NPVARIANT(kDisconnected, *result); INT32_TO_NPVARIANT(kDisconnected, *result);
return true; return true;
...@@ -320,16 +313,19 @@ bool HostNPScriptObject::Enumerate(std::vector<std::string>* values) { ...@@ -320,16 +313,19 @@ bool HostNPScriptObject::Enumerate(std::vector<std::string>* values) {
kAttrNameState, kAttrNameState,
kAttrNameLogDebugInfo, kAttrNameLogDebugInfo,
kAttrNameOnStateChanged, kAttrNameOnStateChanged,
kFuncNameConnect,
kFuncNameDisconnect,
kFuncNameLocalize,
kAttrNameDisconnected, kAttrNameDisconnected,
kAttrNameStarting, kAttrNameStarting,
kAttrNameRequestedAccessCode, kAttrNameRequestedAccessCode,
kAttrNameReceivedAccessCode, kAttrNameReceivedAccessCode,
kAttrNameConnected, kAttrNameConnected,
kAttrNameDisconnecting, kAttrNameDisconnecting,
kAttrNameError kAttrNameError,
kFuncNameConnect,
kFuncNameDisconnect,
kFuncNameLocalize,
kFuncNameSetDaemonPin,
kFuncNameStartDaemon,
kFuncNameStopDaemon
}; };
for (size_t i = 0; i < arraysize(entries); ++i) { for (size_t i = 0; i < arraysize(entries); ++i) {
values->push_back(entries[i]); values->push_back(entries[i]);
...@@ -566,6 +562,48 @@ bool HostNPScriptObject::Localize(const NPVariant* args, ...@@ -566,6 +562,48 @@ bool HostNPScriptObject::Localize(const NPVariant* args,
} }
} }
bool HostNPScriptObject::SetDaemonPin(const NPVariant* args,
uint32_t arg_count,
NPVariant* result) {
if (arg_count != 1) {
SetException("startDaemon: bad number of arguments");
return false;
}
if (NPVARIANT_IS_STRING(args[0])) {
bool set_pin_result =
daemon_controller_->SetPin(StringFromNPVariant(args[0]));
BOOLEAN_TO_NPVARIANT(set_pin_result, *result);
return true;
} else {
SetException("startDaemon: unexpected type for argument 1");
return false;
}
}
bool HostNPScriptObject::StartDaemon(const NPVariant* args,
uint32_t arg_count,
NPVariant* result) {
if (arg_count != 0) {
SetException("startDaemon: bad number of arguments");
return false;
}
bool start_result = daemon_controller_->Start();
BOOLEAN_TO_NPVARIANT(start_result, *result);
return true;
}
bool HostNPScriptObject::StopDaemon(const NPVariant* args,
uint32_t arg_count,
NPVariant* result) {
if (arg_count != 0) {
SetException("startDaemon: bad number of arguments");
return false;
}
bool stop_result = daemon_controller_->Stop();
BOOLEAN_TO_NPVARIANT(stop_result, *result);
return true;
}
void HostNPScriptObject::DisconnectInternal() { void HostNPScriptObject::DisconnectInternal() {
if (!host_context_.network_message_loop()->BelongsToCurrentThread()) { if (!host_context_.network_message_loop()->BelongsToCurrentThread()) {
host_context_.network_message_loop()->PostTask( host_context_.network_message_loop()->PostTask(
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
namespace remoting { namespace remoting {
class ChromotingHost; class ChromotingHost;
class DaemonController;
class DesktopEnvironment; class DesktopEnvironment;
class It2MeHostUserInterface; class It2MeHostUserInterface;
class MutableHostConfig; class MutableHostConfig;
...@@ -106,6 +107,21 @@ class HostNPScriptObject : public HostStatusObserver { ...@@ -106,6 +107,21 @@ class HostNPScriptObject : public HostStatusObserver {
// No result. // No result.
bool Localize(const NPVariant* args, uint32_t argCount, NPVariant* result); bool Localize(const NPVariant* args, uint32_t argCount, NPVariant* result);
// Set the PIN for Me2Me. Args are:
// string pin
// Returns true if the PIN was updated successfully.
bool SetDaemonPin(const NPVariant* args, uint32_t argCount,
NPVariant* result);
// Start the daemon process or change the PIN if it is running. No args.
// Returns true if the download/start mechanism was initiated successfully
// (poll daemonState to wait for completion) or false if an error occurred.
bool StartDaemon(const NPVariant* args, uint32_t argCount, NPVariant* result);
// Start the daemon process or change the PIN if it is running. No arguments.
// Returns true if the daemon was stopped successfully or false on error.
bool StopDaemon(const NPVariant* args, uint32_t argCount, NPVariant* result);
// Updates state of the host. Can be called only on the main thread. // Updates state of the host. Can be called only on the main thread.
void SetState(State state); void SetState(State state);
...@@ -192,6 +208,8 @@ class HostNPScriptObject : public HostStatusObserver { ...@@ -192,6 +208,8 @@ class HostNPScriptObject : public HostStatusObserver {
UiStrings ui_strings_; UiStrings ui_strings_;
base::Lock ui_strings_lock_; base::Lock ui_strings_lock_;
scoped_ptr<DaemonController> daemon_controller_;
base::WaitableEvent disconnected_event_; base::WaitableEvent disconnected_event_;
// True if we're in the middle of handling a log message. // True if we're in the middle of handling a log message.
......
...@@ -286,6 +286,10 @@ ...@@ -286,6 +286,10 @@
'sources': [ 'sources': [
'host/it2me_host_user_interface.cc', 'host/it2me_host_user_interface.cc',
'host/it2me_host_user_interface.h', 'host/it2me_host_user_interface.h',
'host/plugin/daemon_controller.h',
'host/plugin/daemon_controller_linux.cc',
'host/plugin/daemon_controller_mac.cc',
'host/plugin/daemon_controller_win.cc',
'host/plugin/host_log_handler.cc', 'host/plugin/host_log_handler.cc',
'host/plugin/host_log_handler.h', 'host/plugin/host_log_handler.h',
'host/plugin/host_plugin.cc', 'host/plugin/host_plugin.cc',
......
// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
...@@ -25,6 +25,16 @@ remoting.HostPlugin.prototype.disconnect = function() {}; ...@@ -25,6 +25,16 @@ remoting.HostPlugin.prototype.disconnect = function() {};
* @return {void} Nothing. */ * @return {void} Nothing. */
remoting.HostPlugin.prototype.localize = function(callback) {}; remoting.HostPlugin.prototype.localize = function(callback) {};
/** @param {string} pin The new PIN.
* @return {boolean} True if the PIN was changed successfully. */
remoting.HostPlugin.prototype.setDaemonPin = function(pin) {};
/** @return {boolean} True if successful (poll daemonState for completion). */
remoting.HostPlugin.prototype.startDaemon = function() {};
/** @return {void} Nothing. */
remoting.HostPlugin.prototype.stopDaemon = function() {};
/** @type {number} */ remoting.HostPlugin.prototype.state; /** @type {number} */ remoting.HostPlugin.prototype.state;
/** @type {number} */ remoting.HostPlugin.prototype.STARTING; /** @type {number} */ remoting.HostPlugin.prototype.STARTING;
...@@ -40,5 +50,8 @@ remoting.HostPlugin.prototype.localize = function(callback) {}; ...@@ -40,5 +50,8 @@ remoting.HostPlugin.prototype.localize = function(callback) {};
/** @type {string} */ remoting.HostPlugin.prototype.client; /** @type {string} */ remoting.HostPlugin.prototype.client;
/** @type {number} The install/running state of the daemon process. */
remoting.HostPlugin.prototype.daemonState;
/** @type {function(boolean):void} */ /** @type {function(boolean):void} */
remoting.HostPlugin.prototype.onNatTraversalPolicyChanged; remoting.HostPlugin.prototype.onNatTraversalPolicyChanged;
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