Home | History | Annotate | Download | only in host
      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/logging.h"
     11 #include "base/single_thread_task_runner.h"
     12 #include "remoting/host/client_session_control.h"
     13 
     14 namespace remoting {
     15 
     16 class 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 
     30 CurtainModeLinux::CurtainModeLinux() {
     31 }
     32 
     33 bool 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 
     46 bool 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         LOG(INFO) << "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         LOG(INFO) << "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         LOG(INFO) << "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         LOG(INFO) << "Non Xvfb keyboard found: " << device_info->name;
     90       }
     91     } else {
     92       found_other_devices = true;
     93       LOG(INFO) << "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
    102 scoped_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