1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "remoting/host/curtain_mode.h" 6 7#include <X11/extensions/XInput.h> 8 9#include "base/callback.h" 10#include "base/single_thread_task_runner.h" 11#include "remoting/base/logging.h" 12#include "remoting/host/client_session_control.h" 13 14namespace remoting { 15 16class CurtainModeLinux : public CurtainMode { 17 public: 18 CurtainModeLinux(); 19 20 // Overriden from CurtainMode. 21 virtual bool Activate() OVERRIDE; 22 23 private: 24 // Returns true if the host is running under an Xvfb session. 25 bool IsXvfbSession(); 26 27 DISALLOW_COPY_AND_ASSIGN(CurtainModeLinux); 28}; 29 30CurtainModeLinux::CurtainModeLinux() { 31} 32 33bool CurtainModeLinux::Activate() { 34 // We can't curtain the session in run-time in Linux. 35 // Either the session is running on Xvfb (i.e. always curtained), or it is 36 // attached to the physical console (i.e. impossible to curtain). 37 bool activated = IsXvfbSession(); 38 if (!activated) { 39 LOG(ERROR) << "Curtain-mode is not supported when running on non-Xvfb " 40 "X server"; 41 } 42 43 return activated; 44} 45 46bool CurtainModeLinux::IsXvfbSession() { 47 // Try to identify an Xvfb session. There's no way to query what X server we 48 // are running under, so we check for the Xvfb input devices. 49 // TODO(rmsousa): Find a similar way to determine that the *output* is secure. 50 Display* display = XOpenDisplay(NULL); 51 int opcode, event, error; 52 if (!XQueryExtension(display, "XInputExtension", &opcode, &event, &error)) { 53 // If XInput is not available, assume it is not an Xvfb session. 54 LOG(ERROR) << "X Input extension not available: " << error; 55 XCloseDisplay(display); 56 return false; 57 } 58 int num_devices; 59 XDeviceInfo* devices; 60 bool found_xvfb_mouse = false; 61 bool found_xvfb_keyboard = false; 62 bool found_other_devices = false; 63 devices = XListInputDevices(display, &num_devices); 64 for (int i = 0; i < num_devices; i++) { 65 XDeviceInfo* device_info = &devices[i]; 66 if (device_info->use == IsXExtensionPointer) { 67 if (strcmp(device_info->name, "Xvfb mouse") == 0) { 68 found_xvfb_mouse = true; 69 } else if (strcmp(device_info->name, "Virtual core XTEST pointer") != 0) { 70 found_other_devices = true; 71 HOST_LOG << "Non Xvfb mouse found: " << device_info->name; 72 } 73 } else if (device_info->use == IsXExtensionKeyboard) { 74 if (strcmp(device_info->name, "Xvfb keyboard") == 0) { 75 found_xvfb_keyboard = true; 76 } else if (strcmp(device_info->name, 77 "Virtual core XTEST keyboard") != 0) { 78 found_other_devices = true; 79 HOST_LOG << "Non Xvfb keyboard found: " << device_info->name; 80 } 81 } else if (device_info->use == IsXPointer) { 82 if (strcmp(device_info->name, "Virtual core pointer") != 0) { 83 found_other_devices = true; 84 HOST_LOG << "Non Xvfb mouse found: " << device_info->name; 85 } 86 } else if (device_info->use == IsXKeyboard) { 87 if (strcmp(device_info->name, "Virtual core keyboard") != 0) { 88 found_other_devices = true; 89 HOST_LOG << "Non Xvfb keyboard found: " << device_info->name; 90 } 91 } else { 92 found_other_devices = true; 93 HOST_LOG << "Non Xvfb device found: " << device_info->name; 94 } 95 } 96 XFreeDeviceList(devices); 97 XCloseDisplay(display); 98 return found_xvfb_mouse && found_xvfb_keyboard && !found_other_devices; 99} 100 101// static 102scoped_ptr<CurtainMode> CurtainMode::Create( 103 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, 104 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, 105 base::WeakPtr<ClientSessionControl> client_session_control) { 106 return scoped_ptr<CurtainMode>(new CurtainModeLinux()); 107} 108 109} // namespace remoting 110