summaryrefslogtreecommitdiffstats
path: root/remoting/host/win
diff options
context:
space:
mode:
authoralexeypa@chromium.org <alexeypa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-02 02:39:04 +0000
committeralexeypa@chromium.org <alexeypa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-02 02:39:04 +0000
commitae82efcf08991eee3c8be508e2182655ba0abbca (patch)
tree2ae4547bc6db9728359d0de73c35234b93ce1c11 /remoting/host/win
parentc90475e80e5dbbb1c82c60c3de4e0db71b188936 (diff)
downloadchromium_src-ae82efcf08991eee3c8be508e2182655ba0abbca.zip
chromium_src-ae82efcf08991eee3c8be508e2182655ba0abbca.tar.gz
chromium_src-ae82efcf08991eee3c8be508e2182655ba0abbca.tar.bz2
[Chromoting] Create per-session job objects to control processes launched in a session.
Processes from different sessions cannot be attached to the same job object even in the case when their lifetimes do not overlap. The CL causes |WtsSessionProcessLauncher| to create a new job object every time it is switched to a new session. This CL also makes sure that the host process will be completely shutdown before trying to re-launch it is a different session to avoid the race with the session attach notification. BUG=149098,153005 Review URL: https://chromiumcodereview.appspot.com/11029004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@159623 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/host/win')
-rw-r--r--remoting/host/win/wts_session_process_launcher.cc95
-rw-r--r--remoting/host/win/wts_session_process_launcher.h11
2 files changed, 62 insertions, 44 deletions
diff --git a/remoting/host/win/wts_session_process_launcher.cc b/remoting/host/win/wts_session_process_launcher.cc
index 2073f60..9b991fa 100644
--- a/remoting/host/win/wts_session_process_launcher.cc
+++ b/remoting/host/win/wts_session_process_launcher.cc
@@ -74,9 +74,6 @@ class WtsSessionProcessLauncherImpl
// Returns the exit code of the worker process.
virtual DWORD GetExitCode() = 0;
- // Sets the token to be used to launch the worker process.
- virtual void ResetUserToken(ScopedHandle* user_token) = 0;
-
// Stops the object asynchronously.
virtual void Stop() = 0;
@@ -93,6 +90,7 @@ namespace {
class SingleProcessLauncher : public WtsSessionProcessLauncherImpl {
public:
SingleProcessLauncher(
+ uint32 session_id,
const FilePath& binary_path,
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner);
@@ -104,7 +102,6 @@ class SingleProcessLauncher : public WtsSessionProcessLauncherImpl {
// WtsSessionProcessLauncherImpl implementation.
virtual DWORD GetExitCode() OVERRIDE;
- virtual void ResetUserToken(ScopedHandle* user_token) OVERRIDE;
virtual void Stop() OVERRIDE;
private:
@@ -134,6 +131,7 @@ class ElevatedProcessLauncher : public WtsSessionProcessLauncherImpl,
public base::MessagePumpForIO::IOHandler {
public:
ElevatedProcessLauncher(
+ uint32 session_id,
const FilePath& binary_path,
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
@@ -151,7 +149,6 @@ class ElevatedProcessLauncher : public WtsSessionProcessLauncherImpl,
// WtsSessionProcessLauncherImpl implementation.
virtual DWORD GetExitCode() OVERRIDE;
- virtual void ResetUserToken(ScopedHandle* user_token) OVERRIDE;
virtual void Stop() OVERRIDE;
private:
@@ -197,10 +194,12 @@ class ElevatedProcessLauncher : public WtsSessionProcessLauncherImpl,
};
SingleProcessLauncher::SingleProcessLauncher(
+ uint32 session_id,
const FilePath& binary_path,
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner)
: binary_path_(binary_path),
main_task_runner_(main_task_runner) {
+ CHECK(CreateSessionToken(session_id, &user_token_));
}
bool SingleProcessLauncher::DoLaunchProcess(
@@ -272,17 +271,12 @@ DWORD SingleProcessLauncher::GetExitCode() {
return exit_code;
}
-void SingleProcessLauncher::ResetUserToken(ScopedHandle* user_token) {
- DCHECK(main_task_runner_->BelongsToCurrentThread());
-
- user_token_ = user_token->Pass();
-}
-
void SingleProcessLauncher::Stop() {
DCHECK(main_task_runner_->BelongsToCurrentThread());
}
ElevatedProcessLauncher::ElevatedProcessLauncher(
+ uint32 session_id,
const FilePath& binary_path,
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
@@ -292,6 +286,8 @@ ElevatedProcessLauncher::ElevatedProcessLauncher(
process_exit_event_.Set(CreateEvent(NULL, TRUE, FALSE, NULL));
CHECK(process_exit_event_.IsValid());
+ CHECK(CreateSessionToken(session_id, &user_token_));
+
// To receive job object notifications the job object is registered with
// the completion port represented by |io_task_runner|. The registration has
// to be done on the I/O thread because MessageLoopForIO::RegisterJobObject()
@@ -411,13 +407,6 @@ DWORD ElevatedProcessLauncher::GetExitCode() {
return exit_code;
}
-void ElevatedProcessLauncher::ResetUserToken(
- ScopedHandle* user_token) {
- DCHECK(main_task_runner_->BelongsToCurrentThread());
-
- user_token_ = user_token->Pass();
-}
-
void ElevatedProcessLauncher::Stop() {
DCHECK(main_task_runner_->BelongsToCurrentThread());
@@ -543,25 +532,7 @@ WtsSessionProcessLauncher::WtsSessionProcessLauncher(
Stop();
return;
}
- FilePath host_binary = dir_path.Append(kMe2meHostBinaryName);
-
- // The workaround we use to launch a process in a not yet logged in session
- // (see CreateRemoteSessionProcess()) on Windows XP/2K3 does not let us to
- // assign the started process to a job. However on Vista+ we have to start
- // the host via a helper process. The helper process calls ShellExecute() that
- // does not work across the session boundary but it required to launch
- // a binary specifying uiAccess='true' in its manifest.
- //
- // Below we choose which implementation of |WorkerProcessLauncher::Delegate|
- // to use. A single process is launched on XP (since uiAccess='true' does not
- // have effect any way). Vista+ utilizes a helper process and assign it to
- // a job object to control it.
- if (base::win::GetVersion() == base::win::VERSION_XP) {
- impl_ = new SingleProcessLauncher(host_binary, main_message_loop);
- } else {
- impl_ = new ElevatedProcessLauncher(host_binary, main_message_loop,
- ipc_message_loop);
- }
+ host_binary_ = dir_path.Append(kMe2meHostBinaryName);
}
WtsSessionProcessLauncher::~WtsSessionProcessLauncher() {
@@ -598,10 +569,34 @@ void WtsSessionProcessLauncher::OnSessionAttached(uint32 session_id) {
attached_ = true;
- // Create a session token and launch the host.
- ScopedHandle user_token;
- if (CreateSessionToken(session_id, &user_token)) {
- impl_->ResetUserToken(&user_token);
+ // Reset the backoff timeout every time the session is switched.
+ launch_backoff_ = base::TimeDelta();
+
+ // The workaround we use to launch a process in a not yet logged in session
+ // (see CreateRemoteSessionProcess()) on Windows XP/2K3 does not let us to
+ // assign the started process to a job. However on Vista+ we have to start
+ // the host via a helper process. The helper process calls ShellExecute() that
+ // does not work across the session boundary but it required to launch
+ // a binary specifying uiAccess='true' in its manifest.
+ //
+ // Below we choose which implementation of |WorkerProcessLauncher::Delegate|
+ // to use. A single process is launched on XP (since uiAccess='true' does not
+ // have effect any way). Vista+ utilizes a helper process and assign it to
+ // a job object to control it.
+ if (new_impl_.get()) {
+ new_impl_->Stop();
+ new_impl_ = NULL;
+ }
+ if (base::win::GetVersion() == base::win::VERSION_XP) {
+ new_impl_ = new SingleProcessLauncher(session_id, host_binary_,
+ main_message_loop_);
+ } else {
+ new_impl_ = new ElevatedProcessLauncher(session_id, host_binary_,
+ main_message_loop_,
+ ipc_message_loop_);
+ }
+
+ if (launcher_.get() == NULL) {
LaunchProcess();
}
}
@@ -631,7 +626,11 @@ void WtsSessionProcessLauncher::DoStop() {
return;
}
- // Tear down the core asynchromously.
+ // Tear down implementation objects asynchromously.
+ if (new_impl_.get()) {
+ new_impl_->Stop();
+ new_impl_ = NULL;
+ }
if (impl_.get()) {
impl_->Stop();
impl_ = NULL;
@@ -646,6 +645,18 @@ void WtsSessionProcessLauncher::LaunchProcess() {
DCHECK(launcher_.get() == NULL);
DCHECK(!timer_.IsRunning());
+ // Switch to a new implementation object if needed.
+ if (new_impl_.get() != NULL) {
+ if (impl_.get() != NULL) {
+ impl_->Stop();
+ impl_ = NULL;
+ }
+
+ impl_.swap(new_impl_);
+ }
+
+ DCHECK(impl_.get() != NULL);
+
launch_time_ = base::Time::Now();
launcher_.reset(new WorkerProcessLauncher(
impl_.get(), this,
diff --git a/remoting/host/win/wts_session_process_launcher.h b/remoting/host/win/wts_session_process_launcher.h
index 040a4f3..e9a8e54 100644
--- a/remoting/host/win/wts_session_process_launcher.h
+++ b/remoting/host/win/wts_session_process_launcher.h
@@ -74,10 +74,17 @@ class WtsSessionProcessLauncher
// |true| if this object is currently attached to the console session.
bool attached_;
- // The specific code knowing how to launch and control a child process
- // implemented by |WtsSessionProcessLauncherImpl|.
+ // Path to the host binary to launch.
+ FilePath host_binary_;
+
+ // OS version dependent WorkerProcessLauncher::Delegate implementation
+ // instance for the currently-running child process.
scoped_refptr<WtsSessionProcessLauncherImpl> impl_;
+ // WorkerProcessLauncher::Delegate implementation that will be used to launch
+ // the new child process after a session switch.
+ scoped_refptr<WtsSessionProcessLauncherImpl> new_impl_;
+
// Time of the last launch attempt.
base::Time launch_time_;