Curtain mode implementation for Mac OS X.

This implements the basic curtain-mode functionality:
* Switch out the active session on connection (if necessary--it doesn't do this if the session is at the login screen or already switched out)
* Close all connections if the session becomes active again (for example, if someone logs into it at the console).

It doesn't solve the problem of launchd starting a new instance of the server when we switch out. There will be a follow-up CL to address that.

BUG=110111


Review URL: https://chromiumcodereview.appspot.com/10823215

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@150746 0039d316-1c4b-4281-b951-d872f2087c98
parent db83b39e
// 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/curtain_mode_mac.h"
#include <ApplicationServices/ApplicationServices.h>
#include <Security/Security.h>
#include "base/logging.h"
#include "base/mac/scoped_cftyperef.h"
namespace {
const char* kCGSessionPath =
"/System/Library/CoreServices/Menu Extras/User.menu/Contents/Resources/"
"CGSession";
}
namespace remoting {
CurtainMode::CurtainMode() : event_handler_(NULL) {
}
CurtainMode::~CurtainMode() {
if (event_handler_) {
RemoveEventHandler(event_handler_);
}
}
bool CurtainMode::Init(const base::Closure& on_session_activate) {
DCHECK(on_session_activate_.is_null());
on_session_activate_ = on_session_activate;
EventTypeSpec event;
event.eventClass = kEventClassSystem;
event.eventKind = kEventSystemUserSessionActivated;
OSStatus result = InstallApplicationEventHandler(
NewEventHandlerUPP(SessionActivateHandler), 1, &event, this,
&event_handler_);
return result == noErr;
}
void CurtainMode::OnClientAuthenticated(const std::string& jid) {
// If the current session is attached to the console and is not showing
// the logon screen then switch it out to ensure privacy.
base::mac::ScopedCFTypeRef<CFDictionaryRef> session(
CGSessionCopyCurrentDictionary());
const void* on_console = CFDictionaryGetValue(session,
kCGSessionOnConsoleKey);
const void* logged_in = CFDictionaryGetValue(session, kCGSessionLoginDoneKey);
if (logged_in == kCFBooleanTrue && on_console == kCFBooleanTrue) {
pid_t child = fork();
if (child == 0) {
execl(kCGSessionPath, kCGSessionPath, "-suspend", NULL);
_exit(1);
} else if (child > 0) {
int status = 0;
waitpid(child, &status, 0);
}
}
}
OSStatus CurtainMode::SessionActivateHandler(EventHandlerCallRef handler,
EventRef event,
void* user_data) {
CurtainMode* self = static_cast<CurtainMode*>(user_data);
self->OnSessionActivate();
return noErr;
}
void CurtainMode::OnSessionActivate() {
if (!on_session_activate_.is_null()) {
on_session_activate_.Run();
}
}
} // 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.
#ifndef REMOTING_HOST_CURTAIN_MODE_MAC_H_
#define REMOTING_HOST_CURTAIN_MODE_MAC_H_
#include <Carbon/Carbon.h>
#include <string>
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "remoting/host/host_status_observer.h"
namespace remoting {
class CurtainMode : public HostStatusObserver {
public:
CurtainMode();
virtual ~CurtainMode();
// Set the callback to be invoked when the switched-out remote session is
// switched back to the console. Typically, remote connections should be
// closed in this event to make sure that only one connection (console or
// remote) exists to a session at any time to ensure privacy. Note that
// only the session's owner (or someone who knows the owner's password)
// can attach it to the console, so this is safe.
bool Init(const base::Closure& on_session_activate);
// Overridden from HostStatusObserver
virtual void OnClientAuthenticated(const std::string& jid) OVERRIDE;
private:
static OSStatus SessionActivateHandler(EventHandlerCallRef handler,
EventRef event,
void* user_data);
void OnSessionActivate();
base::Closure on_session_activate_;
EventHandlerRef event_handler_;
};
}
#endif
......@@ -51,6 +51,7 @@
#if defined(OS_MACOSX)
#include "base/mac/scoped_nsautorelease_pool.h"
#include "remoting/host/curtain_mode_mac.h"
#include "remoting/host/sighup_listener_mac.h"
#endif
// N.B. OS_WIN is defined by including src/base headers.
......@@ -446,6 +447,12 @@ class HostProcess
base::Unretained(this)));
#endif
#if defined(OS_MACOSX)
curtain_.Init(base::Bind(&HostProcess::OnDisconnectRequested,
base::Unretained(this)));
host_->AddStatusObserver(&curtain_);
#endif
host_->Start();
CreateAuthenticatorFactory();
......@@ -558,6 +565,10 @@ class HostProcess
scoped_refptr<ChromotingHost> host_;
int exit_code_;
#if defined(OS_MACOSX)
remoting::CurtainMode curtain_;
#endif
};
} // namespace remoting
......
......@@ -1468,6 +1468,8 @@
'host/remoting_me2me_host.cc',
'host/usage_stats_consent.h',
'host/usage_stats_consent_win.cc',
'host/curtain_mode_mac.h',
'host/curtain_mode_mac.cc',
],
'conditions': [
['OS=="mac"', {
......
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