summaryrefslogtreecommitdiffstats
path: root/remoting
diff options
context:
space:
mode:
authoralexeypa@chromium.org <alexeypa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-01 10:15:09 +0000
committeralexeypa@chromium.org <alexeypa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-01 10:15:09 +0000
commit0b205e16eeaa51a32b544687e08ef356d500245a (patch)
tree93ae9bf8cd5b0ec91e41c8398b314ab95ade6a7f /remoting
parent61e77c687ad8601cd64164d3191425400f7bc72c (diff)
downloadchromium_src-0b205e16eeaa51a32b544687e08ef356d500245a.zip
chromium_src-0b205e16eeaa51a32b544687e08ef356d500245a.tar.gz
chromium_src-0b205e16eeaa51a32b544687e08ef356d500245a.tar.bz2
Introducing an out-of-process COM class hosting RdpClient.
RdpClient takes dependency on mstscax.dll that pulls a lot of code to the process. This CL allows RdpClient objects to be hosted in a separate process running at medium integrity level under LocalService account. BUG=137696 Review URL: https://chromiumcodereview.appspot.com/12330178 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@185515 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting')
-rw-r--r--remoting/host/host_main.cc4
-rw-r--r--remoting/host/host_main.h1
-rw-r--r--remoting/host/installer/win/chromoting.wxs103
-rw-r--r--remoting/host/installer/win/parameters.json1
-rw-r--r--remoting/host/setup/daemon_controller_win.cc2
-rw-r--r--remoting/host/win/chromoting_lib_idl.templ57
-rw-r--r--remoting/host/win/chromoting_module.cc70
-rw-r--r--remoting/host/win/chromoting_module.h2
-rw-r--r--remoting/host/win/elevated_controller.h10
-rw-r--r--remoting/host/win/rdp_client.cc17
-rw-r--r--remoting/host/win/rdp_client.h2
-rw-r--r--remoting/host/win/rdp_client_unittest.cc7
-rw-r--r--remoting/host/win/rdp_desktop_session.cc56
-rw-r--r--remoting/host/win/rdp_desktop_session.h76
-rw-r--r--remoting/remoting.gyp14
15 files changed, 391 insertions, 31 deletions
diff --git a/remoting/host/host_main.cc b/remoting/host/host_main.cc
index 96b2752..1687758 100644
--- a/remoting/host/host_main.cc
+++ b/remoting/host/host_main.cc
@@ -42,6 +42,7 @@ int DesktopProcessMain();
#if defined(OS_WIN)
int ElevatedControllerMain();
+int RdpDesktopSessionMain();
#endif // defined(OS_WIN)
const char kElevateSwitchName[] = "elevate";
@@ -56,6 +57,7 @@ const char kProcessTypeDesktop[] = "desktop";
#if defined(OS_WIN)
const char kProcessTypeController[] = "controller";
+const char kProcessTypeRdpDesktopSession[] = "rdp_desktop_session";
#endif // defined(OS_WIN)
namespace {
@@ -146,6 +148,8 @@ MainRoutineFn SelectMainRoutine(const std::string& process_type) {
#if defined(OS_WIN)
if (process_type == kProcessTypeController) {
main_routine = &ElevatedControllerMain;
+ } else if (process_type == kProcessTypeRdpDesktopSession) {
+ main_routine = &RdpDesktopSessionMain;
}
#endif // defined(OS_WIN)
diff --git a/remoting/host/host_main.h b/remoting/host/host_main.h
index 5dbdd35..2b56734 100644
--- a/remoting/host/host_main.h
+++ b/remoting/host/host_main.h
@@ -25,6 +25,7 @@ extern const char kProcessTypeDesktop[];
#if defined(OS_WIN)
extern const char kProcessTypeController[];
+extern const char kProcessTypeRdpDesktopSession[];
#endif // defined(OS_WIN)
// The common entry point exported from remoting_core.dll. It uses
diff --git a/remoting/host/installer/win/chromoting.wxs b/remoting/host/installer/win/chromoting.wxs
index 0ef21fd..a88b4a40 100644
--- a/remoting/host/installer/win/chromoting.wxs
+++ b/remoting/host/installer/win/chromoting.wxs
@@ -28,29 +28,51 @@
<?define ChromotingTypelib = "{b6396c45-b0cc-456b-9f49-f12964ee6df4}" ?>
+ <!-- AppIDs used by the COM components. -->
<?define ControllerAppid = "{4ff35d5e-d226-4550-9248-03e7779e67de}" ?>
+ <?define RdpAppid = "{52e6fd1a-f16e-49c0-aacb-5436a915448b}" ?>
+
<?define ControllerClass = "ElevatedController Class" ?>
<?define ControllerProgid =
"ChromotingElevatedController.ElevatedController" ?>
<!--
- The long hex value below is a security descriptor that allows SYSTEM,
- built-in administrators and interactive users to call methods of a COM
- object (COM_RIGHTS_EXECUTE and COM_RIGHTS_EXECUTE_LOCAL). The security
- descriptor was generated from SDDL definition using the PowerShell script
- below:
-
- $sddl = "O:BAG:BAD:(A;;0x3;;;IU)(A;;0x3;;;SY)(A;;0x3;;;BA)"
- $i = ([wmiclass]"Win32_SecurityDescriptorHelper").SDDLToBinarySD($sddl).BinarySD
- -join ($i | foreach {$_.ToString("X2")})
+ The long hex values below are security descriptors generated from SDDL
+ definition using the PowerShell script below:
+
+ $sddl = "<SDDL definition goes here>"
+ $i = ([wmiclass]"Win32_SecurityDescriptorHelper").SDDLToBinarySD($sddl).BinarySD
+ -join ($i | foreach {$_.ToString("X2")})
+ -->
+
+ <!--
+ A security descriptor that allows SYSTEM, built-in administrators and
+ interactive users COM_RIGHTS_EXECUTE and COM_RIGHTS_EXECUTE_LOCAL rights.
+ The SDDL definition:
+
+ $sddl = "O:BAG:BAD:(A;;0x3;;;IU)(A;;0x3;;;SY)(A;;0x3;;;BA)"
-->
<?define ControllerSd = "010004805C0000006C00000000000000140000000200480003000000000014000300000001010000000000050400000000001400030000000101000000000005120000000000180003000000010200000000000520000000200200000102000000000005200000002002000001020000000000052000000020020000" ?>
+ <!--
+ A security descriptor that gives SYSTEM, built-in administrators and
+ LocalSystem accounts COM_RIGHTS_EXECUTE, COM_RIGHTS_EXECUTE_LOCAL, and
+ COM_RIGHTS_ACTIVATE_LOCAL rights. It specifies a mandatory label that
+ specifies "no execute up" policy for medium integrity level.
+
+ $sddl = "O:BAG:BAD:(A;;0xb;;;SY)(A;;0xb;;;BA)(A;;0xb;;;LS)S:(ML;;NX;;;ME)"
+ -->
+ <?define RdpSd = "010014807800000088000000140000003000000002001C000100000011001400040000000101000000000010002000000200480003000000000014000B000000010100000000000512000000000018000B00000001020000000000052000000020020000000014000B0000000101000000000005130000000102000000000005200000002002000001020000000000052000000020020000" ?>
+
<!-- Verify that all required parameters are defined. -->
<?ifndef ControllerClsid ?>
<?error ControllerClsid must be defined ?>
<?endif?>
+ <?ifndef RdpDesktopSessionClsid ?>
+ <?error RdpDesktopSessionClsid must be defined ?>
+ <?endif?>
+
<?ifndef Version ?>
<?error Version must be defined ?>
<?endif?>
@@ -238,6 +260,21 @@
Type="binary"
Value="$(var.ControllerSd)"/>
</RegistryKey>
+
+ <RegistryKey Key="$(var.RdpAppid)" Action="create">
+ <RegistryValue Type="string"
+ Value="ChromotingRdpDesktopSession"/>
+ <RegistryValue Name="AccessPermission"
+ Type="binary"
+ Value="$(var.RdpSd)"/>
+ <RegistryValue Name="LaunchPermission"
+ Type="binary"
+ Value="$(var.RdpSd)"/>
+ <RegistryValue Name="RunAs"
+ Type="string"
+ Value="NT AUTHORITY\LocalService"/>
+ </RegistryKey>
+
</RegistryKey>
<RegistryKey Key="$(var.ControllerProgid)" Action="create">
@@ -308,9 +345,42 @@
Value="@[binaries]$(var.CoreBinary),-104"/>
</RegistryKey>
</RegistryKey>
+ <RegistryKey Key="$(var.RdpDesktopSessionClsid)" Action="create">
+ <RegistryValue Type="string"
+ Value="RdpDesktopSession Class"/>
+
+ <RegistryValue Type="string"
+ Name="AppID"
+ Value="$(var.RdpAppid)"/>
+
+ <RegistryKey Key="LocalServer32" Action="create">
+ <RegistryValue Type="string"
+ Value="[binaries]$(var.HostBinary) --type=rdp_desktop_session"/>
+ </RegistryKey>
+
+ <RegistryKey Key="TypeLib" Action="create">
+ <RegistryValue Type="string"
+ Value="$(var.ChromotingTypelib)"/>
+ </RegistryKey>
+ </RegistryKey>
</RegistryKey>
<RegistryKey Key="Interface">
+ <!-- IRdpDesktopSession interface -->
+ <RegistryKey Key="{126c22bc-34ef-4cfb-83ef-9b8ada3391e8}"
+ Action="create">
+ <RegistryKey Key="ProxyStubClsid32" Action="create">
+ <RegistryValue Type="string"
+ Value="{00020424-0000-0000-C000-000000000046}"/>
+ </RegistryKey>
+
+ <RegistryKey Key="TypeLib" Action="create">
+ <RegistryValue Type="string"
+ Value="$(var.ChromotingTypelib)"/>
+ </RegistryKey>
+ </RegistryKey>
+
+ <!-- IDaemonControl2 interface -->
<RegistryKey Key="{655bd819-c08c-4b04-80c2-f160739ff6ef}"
Action="create">
<RegistryKey Key="ProxyStubClsid32" Action="create">
@@ -324,6 +394,21 @@
</RegistryKey>
</RegistryKey>
+ <!-- IRdpDesktopSessionEventHandler interface -->
+ <RegistryKey Key="{987bca97-9d40-42fc-a00d-e6a701261af5}"
+ Action="create">
+ <RegistryKey Key="ProxyStubClsid32" Action="create">
+ <RegistryValue Type="string"
+ Value="{00020424-0000-0000-C000-000000000046}"/>
+ </RegistryKey>
+
+ <RegistryKey Key="TypeLib" Action="create">
+ <RegistryValue Type="string"
+ Value="$(var.ChromotingTypelib)"/>
+ </RegistryKey>
+ </RegistryKey>
+
+ <!-- IDaemonControl interface -->
<RegistryKey Key="{e051a481-6345-4ba1-bdb1-cf7929955268}"
Action="create">
<RegistryKey Key="ProxyStubClsid32" Action="create">
diff --git a/remoting/host/installer/win/parameters.json b/remoting/host/installer/win/parameters.json
index 324dc7e..e044343 100644
--- a/remoting/host/installer/win/parameters.json
+++ b/remoting/host/installer/win/parameters.json
@@ -3,6 +3,7 @@
"Branding": "@@BRANDING@@",
"ControllerClsid": "@@DAEMON_CONTROLLER_CLSID@@",
"OfficialBuild": "@@OFFICIAL_BUILD@@",
+ "RdpDesktopSessionClsid": "@@RDP_DESKTOP_SESSION_CLSID@@",
"RemotingMultiProcess" : "@@REMOTING_MULTI_PROCESS@@",
"Version": "@@VERSION@@"
},
diff --git a/remoting/host/setup/daemon_controller_win.cc b/remoting/host/setup/daemon_controller_win.cc
index 497fd5a..dfcc373 100644
--- a/remoting/host/setup/daemon_controller_win.cc
+++ b/remoting/host/setup/daemon_controller_win.cc
@@ -26,7 +26,7 @@
#include "base/win/windows_version.h"
#include "remoting/base/scoped_sc_handle_win.h"
#include "remoting/host/branding.h"
-// MIDL-generated declarations and definitions.
+// chromoting_lib.h contains MIDL-generated declarations.
#include "remoting/host/chromoting_lib.h"
#include "remoting/host/setup/daemon_installer_win.h"
#include "remoting/host/usage_stats_consent.h"
diff --git a/remoting/host/win/chromoting_lib_idl.templ b/remoting/host/win/chromoting_lib_idl.templ
index f2f7f31..c5b496c 100644
--- a/remoting/host/win/chromoting_lib_idl.templ
+++ b/remoting/host/win/chromoting_lib_idl.templ
@@ -13,7 +13,7 @@ import "ocidl.idl";
helpstring("IDaemonControl Interface"),
pointer_default(unique)
]
-interface IDaemonControl: IDispatch {
+interface IDaemonControl : IDispatch {
[ id(1), helpstring("Returns a filtered copy of the daemon's configuration. "
"Only 'host_id' and 'xmpp_login' values are returned, "
"because any other values may contain security-sensitive "
@@ -53,7 +53,7 @@ interface IDaemonControl: IDispatch {
helpstring("IDaemonControl2 Interface"),
pointer_default(unique)
]
-interface IDaemonControl2: IDaemonControl {
+interface IDaemonControl2 : IDaemonControl {
[ id(8), helpstring("Retrieves the user's consent to collect crash dumps "
"and gather usage statistics.") ]
HRESULT GetUsageStatsConsent([out] BOOL* allowed,
@@ -65,6 +65,51 @@ interface IDaemonControl2: IDaemonControl {
};
[
+ object,
+ uuid(987bca97-9d40-42fc-a00d-e6a701261af5),
+ dual,
+ nonextensible,
+ helpstring("IRdpDesktopSessionEventHandler Interface"),
+ pointer_default(unique)
+]
+interface IRdpDesktopSessionEventHandler : IDispatch {
+ [ id(1), helpstring("Notifies that an RDP connection has been established "
+ "successfully. The client's address and port are "
+ " returned in |client_endpoint| as |SOCKADDR_STORAGE| "
+ "structure. When this method is called multiple times, "
+ "the most recent |client_endpoint| supersedes all "
+ "previous ones.") ]
+ HRESULT OnRdpConnected([in, size_is(length)] byte* client_endpoint,
+ [in] long length);
+
+ [ id(2), helpstring("Notifies the delegate that the RDP connection has been "
+ "closed.") ]
+ HRESULT OnRdpClosed();
+};
+
+[
+ object,
+ uuid(126c22bc-34ef-4cfb-83ef-9b8ada3391e8),
+ dual,
+ nonextensible,
+ helpstring("IRdpDesktopSession Interface"),
+ pointer_default(unique)
+]
+interface IRdpDesktopSession : IDispatch {
+ [ id(1), helpstring("Initiates a loopback RDP connection to spawn a new "
+ "Windows session. |width| and |height| specify the "
+ "initial screen resolution.") ]
+ HRESULT Connect([in] long width, [in] long height,
+ [in] IRdpDesktopSessionEventHandler* event_handler);
+
+ [ id(2), helpstring("Shuts down the connection created by Connect().") ]
+ HRESULT Disconnect();
+
+ [ id(3), helpstring("Changes the screen resolution.") ]
+ HRESULT ChangeResolution([in] long width, [in] long height);
+};
+
+[
uuid(b6396c45-b0cc-456b-9f49-f12964ee6df4),
version(1.0),
helpstring("Chromoting 1.0 Type Library")
@@ -79,4 +124,12 @@ library ChromotingLib {
coclass ElevatedController {
[default] interface IDaemonControl2;
};
+
+ [
+ uuid(@RDP_DESKTOP_SESSION_CLSID@),
+ helpstring("RdpDesktopSession Class")
+ ]
+ coclass RdpDesktopSession {
+ [default] interface IRdpDesktopSession;
+ };
};
diff --git a/remoting/host/win/chromoting_module.cc b/remoting/host/win/chromoting_module.cc
index a9f62b1..6be0a50 100644
--- a/remoting/host/win/chromoting_module.cc
+++ b/remoting/host/win/chromoting_module.cc
@@ -8,9 +8,13 @@
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/run_loop.h"
+#include "base/win/scoped_handle.h"
+#include "base/win/windows_version.h"
#include "remoting/base/auto_thread_task_runner.h"
+#include "remoting/base/typed_buffer.h"
#include "remoting/host/host_exit_codes.h"
#include "remoting/host/win/elevated_controller.h"
+#include "remoting/host/win/rdp_desktop_session.h"
namespace remoting {
@@ -20,6 +24,55 @@ namespace {
base::LazyInstance<scoped_refptr<AutoThreadTaskRunner> > g_module_task_runner =
LAZY_INSTANCE_INITIALIZER;
+// Lowers the process integrity level such that it does not exceed |max_level|.
+// |max_level| is expected to be one of SECURITY_MANDATORY_XXX constants.
+bool LowerProcessIntegrityLevel(DWORD max_level) {
+ base::win::ScopedHandle token;
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_WRITE,
+ token.Receive())) {
+ PLOG(ERROR) << "OpenProcessToken() failed";
+ return false;
+ }
+
+ TypedBuffer<TOKEN_MANDATORY_LABEL> mandatory_label;
+ DWORD length = 0;
+
+ // Get the size of the buffer needed to hold the mandatory label.
+ BOOL result = GetTokenInformation(token, TokenIntegrityLevel,
+ mandatory_label.get(), length, &length);
+ if (!result && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+ // Allocate a buffer that is large enough.
+ TypedBuffer<TOKEN_MANDATORY_LABEL> buffer(length);
+ mandatory_label.Swap(buffer);
+
+ // Get the the mandatory label.
+ result = GetTokenInformation(token, TokenIntegrityLevel,
+ mandatory_label.get(), length, &length);
+ }
+ if (!result) {
+ PLOG(ERROR) << "Failed to get the mandatory label";
+ return false;
+ }
+
+ // Read the current integrity level.
+ DWORD sub_authority_count =
+ *GetSidSubAuthorityCount(mandatory_label->Label.Sid);
+ DWORD* current_level = GetSidSubAuthority(mandatory_label->Label.Sid,
+ sub_authority_count - 1);
+
+ // Set the integrity level to |max_level| if needed.
+ if (*current_level > max_level) {
+ *current_level = max_level;
+ if (!SetTokenInformation(token, TokenIntegrityLevel, mandatory_label.get(),
+ length)) {
+ PLOG(ERROR) << "Failed to set the mandatory label";
+ return false;
+ }
+ }
+
+ return true;
+}
+
} // namespace
ChromotingModule::ChromotingModule(
@@ -137,4 +190,21 @@ int ElevatedControllerMain() {
return module.Run() ? kSuccessExitCode : kInitializationFailed;
}
+// RdpClient entry point.
+int RdpDesktopSessionMain() {
+ // Lower the integrity level to medium, which is the lowest level at which
+ // the RDP ActiveX control can run.
+ if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
+ if (!LowerProcessIntegrityLevel(SECURITY_MANDATORY_MEDIUM_RID))
+ return kInitializationFailed;
+ }
+
+ ATL::_ATL_OBJMAP_ENTRY rdp_client_entry[] = {
+ OBJECT_ENTRY(__uuidof(RdpDesktopSession), RdpDesktopSession)
+ };
+
+ ChromotingModule module(rdp_client_entry, rdp_client_entry + 1);
+ return module.Run() ? kSuccessExitCode : kInitializationFailed;
+}
+
} // namespace remoting
diff --git a/remoting/host/win/chromoting_module.h b/remoting/host/win/chromoting_module.h
index 4a1bd2be..2c7f1aa 100644
--- a/remoting/host/win/chromoting_module.h
+++ b/remoting/host/win/chromoting_module.h
@@ -13,7 +13,7 @@
#include "base/memory/ref_counted.h"
#include "base/win/scoped_com_initializer.h"
-// MIDL-generated declarations.
+// chromoting_lib.h contains MIDL-generated declarations.
#include "remoting/host/chromoting_lib.h"
namespace base {
diff --git a/remoting/host/win/elevated_controller.h b/remoting/host/win/elevated_controller.h
index 3901bc1..23e5e31 100644
--- a/remoting/host/win/elevated_controller.h
+++ b/remoting/host/win/elevated_controller.h
@@ -11,21 +11,21 @@
#include "remoting/base/scoped_sc_handle_win.h"
-// MIDL-generated declarations.
+// chromoting_lib.h contains MIDL-generated declarations.
#include "remoting/host/chromoting_lib.h"
namespace remoting {
-class ATL_NO_VTABLE __declspec(uuid(DAEMON_CONTROLLER_CLSID)) ElevatedController
+class __declspec(uuid(DAEMON_CONTROLLER_CLSID)) ElevatedController
: public ATL::CComObjectRootEx<ATL::CComSingleThreadModel>,
public ATL::CComCoClass<ElevatedController,
&__uuidof(ElevatedController)>,
public ATL::IDispatchImpl<IDaemonControl2, &IID_IDaemonControl2,
&LIBID_ChromotingLib, 1, 0> {
public:
- // Declare the class factory that does not lock the ATL module. This is the
- // same DECLARE_CLASSFACTORY() with the exception that ATL::CComObjectNoLock
- // is used unconditionally.
+ // Declare a class factory which must not lock the ATL module. This is the
+ // same as DECLARE_CLASSFACTORY() with the exception that
+ // ATL::CComObjectNoLock is used unconditionally.
//
// By default ATL generates locking class factories (by wrapping them in
// ATL::CComObjectCached) for classes hosted in a DLL. This class is compiled
diff --git a/remoting/host/win/rdp_client.cc b/remoting/host/win/rdp_client.cc
index 2f1a134..9c1fb37 100644
--- a/remoting/host/win/rdp_client.cc
+++ b/remoting/host/win/rdp_client.cc
@@ -22,10 +22,6 @@ namespace remoting {
namespace {
-// Default width and hight of the RDP client window.
-const long kDefaultWidth = 1024;
-const long kDefaultHeight = 768;
-
// The range of addresses RdpClient may use to distinguish client connections:
// 127.0.0.2 - 127.255.255.254. 127.0.0.1 is explicitly blocked by the RDP
// ActiveX control.
@@ -49,7 +45,7 @@ class RdpClient::Core
RdpClient::EventHandler* event_handler);
// Initiates a loopback RDP connection.
- void Connect();
+ void Connect(const SkISize& screen_size);
// Initiates a graceful shutdown of the RDP connection.
void Disconnect();
@@ -113,11 +109,12 @@ class RdpClient::Core
RdpClient::RdpClient(
scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
+ const SkISize& screen_size,
EventHandler* event_handler) {
DCHECK(caller_task_runner->BelongsToCurrentThread());
core_ = new Core(caller_task_runner, ui_task_runner, event_handler);
- core_->Connect();
+ core_->Connect(screen_size);
}
RdpClient::~RdpClient() {
@@ -136,9 +133,10 @@ RdpClient::Core::Core(
get_extended_tcp_table_(NULL) {
}
-void RdpClient::Core::Connect() {
+void RdpClient::Core::Connect(const SkISize& screen_size) {
if (!ui_task_runner_->BelongsToCurrentThread()) {
- ui_task_runner_->PostTask(FROM_HERE, base::Bind(&Core::Connect, this));
+ ui_task_runner_->PostTask(FROM_HERE,
+ base::Bind(&Core::Connect, this, screen_size));
return;
}
@@ -170,8 +168,7 @@ void RdpClient::Core::Connect() {
// Create the ActiveX control window.
rdp_client_window_.reset(new RdpClientWindow(server_endpoint_, this));
- if (!rdp_client_window_->Connect(SkISize::Make(kDefaultWidth,
- kDefaultHeight))) {
+ if (!rdp_client_window_->Connect(screen_size)) {
rdp_client_window_.reset();
// Notify the caller that connection attempt failed.
diff --git a/remoting/host/win/rdp_client.h b/remoting/host/win/rdp_client.h
index 4987397..07a0238 100644
--- a/remoting/host/win/rdp_client.h
+++ b/remoting/host/win/rdp_client.h
@@ -9,6 +9,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/threading/non_thread_safe.h"
+#include "third_party/skia/include/core/SkSize.h"
namespace base {
class SingleThreadTaskRunner;
@@ -38,6 +39,7 @@ class RdpClient : public base::NonThreadSafe {
RdpClient(
scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
+ const SkISize& screen_size,
EventHandler* event_handler);
virtual ~RdpClient();
diff --git a/remoting/host/win/rdp_client_unittest.cc b/remoting/host/win/rdp_client_unittest.cc
index 38f59cd..f906829 100644
--- a/remoting/host/win/rdp_client_unittest.cc
+++ b/remoting/host/win/rdp_client_unittest.cc
@@ -25,6 +25,10 @@ namespace remoting {
namespace {
+// Default width and hight of the RDP client window.
+const long kDefaultWidth = 1024;
+const long kDefaultHeight = 768;
+
class MockRdpClientEventHandler : public RdpClient::EventHandler {
public:
MockRdpClientEventHandler() {}
@@ -134,7 +138,8 @@ TEST_F(RdpClientTest, Basic) {
.WillOnce(InvokeWithoutArgs(this, &RdpClientTest::CloseRdpClient));
rdp_client_.reset(new RdpClient(task_runner_, task_runner_,
- &event_handler_));
+ SkISize::Make(kDefaultWidth, kDefaultHeight),
+ &event_handler_));
task_runner_ = NULL;
run_loop_.Run();
diff --git a/remoting/host/win/rdp_desktop_session.cc b/remoting/host/win/rdp_desktop_session.cc
new file mode 100644
index 0000000..c555874
--- /dev/null
+++ b/remoting/host/win/rdp_desktop_session.cc
@@ -0,0 +1,56 @@
+// Copyright (c) 2013 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/win/rdp_desktop_session.h"
+
+#include <winsock2.h>
+
+#include "net/base/ip_endpoint.h"
+#include "net/base/net_util.h"
+#include "remoting/base/auto_thread_task_runner.h"
+#include "remoting/host/win/chromoting_module.h"
+
+namespace remoting {
+
+RdpDesktopSession::RdpDesktopSession() {
+}
+
+STDMETHODIMP RdpDesktopSession::Connect(
+ long width,
+ long height,
+ IRdpDesktopSessionEventHandler* event_handler) {
+ event_handler_ = event_handler;
+
+ scoped_refptr<AutoThreadTaskRunner> task_runner =
+ ChromotingModule::task_runner();
+ DCHECK(task_runner->BelongsToCurrentThread());
+
+ client_.reset(new RdpClient(task_runner, task_runner,
+ SkISize::Make(width, height), this));
+ return S_OK;
+}
+
+STDMETHODIMP RdpDesktopSession::Disconnect() {
+ client_.reset();
+ event_handler_ = NULL;
+ return S_OK;
+}
+
+STDMETHODIMP RdpDesktopSession::ChangeResolution(long width, long height) {
+ return E_NOTIMPL;
+}
+
+void RdpDesktopSession::OnRdpConnected(const net::IPEndPoint& client_endpoint) {
+ net::SockaddrStorage sockaddr;
+ CHECK(client_endpoint.ToSockAddr(sockaddr.addr, &sockaddr.addr_len));
+
+ event_handler_->OnRdpConnected(reinterpret_cast<byte*>(sockaddr.addr),
+ sockaddr.addr_len);
+}
+
+void RdpDesktopSession::OnRdpClosed() {
+ event_handler_->OnRdpClosed();
+}
+
+} // namespace remoting
diff --git a/remoting/host/win/rdp_desktop_session.h b/remoting/host/win/rdp_desktop_session.h
new file mode 100644
index 0000000..6ab2087
--- /dev/null
+++ b/remoting/host/win/rdp_desktop_session.h
@@ -0,0 +1,76 @@
+// Copyright (c) 2013 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_WIN_RDP_DESKTOP_SESSION_H_
+#define REMOTING_HOST_WIN_RDP_DESKTOP_SESSION_H_
+
+#include <atlbase.h>
+#include <atlcom.h>
+#include <atlctl.h>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/win/scoped_comptr.h"
+// chromoting_lib.h contains MIDL-generated declarations.
+#include "remoting/host/chromoting_lib.h"
+#include "remoting/host/win/rdp_client.h"
+
+namespace net {
+class IPEndPoint;
+} // namespace net
+
+namespace remoting {
+
+// Implements IRdpDesktopSession interface providing a way to host RdpClient
+// objects in a COM component.
+class __declspec(uuid(RDP_DESKTOP_SESSION_CLSID)) RdpDesktopSession
+ : public ATL::CComObjectRootEx<ATL::CComSingleThreadModel>,
+ public ATL::CComCoClass<RdpDesktopSession, &__uuidof(RdpDesktopSession)>,
+ public ATL::IDispatchImpl<IRdpDesktopSession, &IID_IRdpDesktopSession,
+ &LIBID_ChromotingLib, 1, 0>,
+ public RdpClient::EventHandler {
+ public:
+ // Declare a class factory which must not lock the ATL module. This is the
+ // same as DECLARE_CLASSFACTORY() with the exception that
+ // ATL::CComObjectNoLock is used unconditionally.
+ //
+ // By default ATL generates locking class factories (by wrapping them in
+ // ATL::CComObjectCached) for classes hosted in a DLL. This class is compiled
+ // into a DLL but it is registered as an out-of-process class, so its class
+ // factory should not use locking.
+ typedef ATL::CComCreator<ATL::CComObjectNoLock<ATL::CComClassFactory> >
+ _ClassFactoryCreatorClass;
+
+ RdpDesktopSession();
+
+ // IRdpDesktopSession implementation.
+ STDMETHOD(Connect)(long width, long height,
+ IRdpDesktopSessionEventHandler* event_handler);
+ STDMETHOD(Disconnect)();
+ STDMETHOD(ChangeResolution)(long width, long height);
+
+ DECLARE_NO_REGISTRY()
+
+ private:
+ // RdpClient::EventHandler interface.
+ virtual void OnRdpConnected(const net::IPEndPoint& client_endpoint) OVERRIDE;
+ virtual void OnRdpClosed() OVERRIDE;
+
+ BEGIN_COM_MAP(RdpDesktopSession)
+ COM_INTERFACE_ENTRY(IRdpDesktopSession)
+ COM_INTERFACE_ENTRY(IDispatch)
+ END_COM_MAP()
+
+ // Implements loading and instantiation of the RDP ActiveX client.
+ scoped_ptr<RdpClient> client_;
+
+ // Holds a reference to the caller's EventHandler, through which notifications
+ // are dispatched. Released in Disconnect(), to prevent further notifications.
+ base::win::ScopedComPtr<IRdpDesktopSessionEventHandler> event_handler_;
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+};
+
+} // namespace remoting
+
+#endif // REMOTING_HOST_WIN_RDP_DESKTOP_SESSION_H_
diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp
index 7a73e44..0c2472d 100644
--- a/remoting/remoting.gyp
+++ b/remoting/remoting.gyp
@@ -89,10 +89,15 @@
'host_plugin_prefix': '',
}],
['OS=="win"', {
- # Use auto-generated CLSID to make sure that the newly installed COM
+ # Use auto-generated CLSIDs to make sure that the newly installed COM
# classes will be used during/after upgrade even if there are old
# instances running already.
- 'daemon_controller_clsid': '<!(python tools/uuidgen.py)',
+ # The parameter passed to uuidgen.py is ignored, but needed to make sure
+ # that the script will be invoked separately for each CLSID. Otherwise
+ # GYP will reuse the value returned by the first invocation of
+ # the script.
+ 'daemon_controller_clsid': '<!(python tools/uuidgen.py 1)',
+ 'rdp_desktop_session_clsid': '<!(python tools/uuidgen.py 2)',
}],
],
'remoting_webapp_locale_files': [
@@ -1157,6 +1162,7 @@
'python',
'<(version_py_path)',
'-e', "DAEMON_CONTROLLER_CLSID='<(daemon_controller_clsid)'",
+ '-e', "RDP_DESKTOP_SESSION_CLSID='<(rdp_desktop_session_clsid)'",
'<(RULE_INPUT_PATH)',
'<@(_outputs)',
],
@@ -1304,6 +1310,7 @@
'_ATL_NO_AUTOMATIC_NAMESPACE',
'_ATL_NO_EXCEPTIONS',
'DAEMON_CONTROLLER_CLSID="{<(daemon_controller_clsid)}"',
+ 'RDP_DESKTOP_SESSION_CLSID="{<(rdp_desktop_session_clsid)}"',
'HOST_IMPLEMENTATION',
'ISOLATION_AWARE_ENABLED=1',
'STRICT',
@@ -1371,6 +1378,8 @@
'host/win/host_service.h',
'host/win/omaha.cc',
'host/win/omaha.h',
+ 'host/win/rdp_desktop_session.cc',
+ 'host/win/rdp_desktop_session.h',
'host/win/unprivileged_process_delegate.cc',
'host/win/unprivileged_process_delegate.h',
'host/win/worker_process_launcher.cc',
@@ -1723,6 +1732,7 @@
'defs': [
'BRANDING=<(branding)',
'DAEMON_CONTROLLER_CLSID={<(daemon_controller_clsid)}',
+ 'RDP_DESKTOP_SESSION_CLSID={<(rdp_desktop_session_clsid)}',
'REMOTING_MULTI_PROCESS=<(remoting_multi_process)',
'VERSION=<(version_full)',
],