Home | History | Annotate | Download | only in browser
      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 // libudev is used for monitoring device changes.
      6 
      7 #include "content/browser/device_monitor_linux.h"
      8 
      9 #include <libudev.h>
     10 
     11 #include <string>
     12 
     13 #include "base/system_monitor/system_monitor.h"
     14 #include "content/browser/udev_linux.h"
     15 #include "content/public/browser/browser_thread.h"
     16 
     17 namespace {
     18 
     19 struct SubsystemMap {
     20   base::SystemMonitor::DeviceType device_type;
     21   const char* subsystem;
     22   const char* devtype;
     23 };
     24 
     25 const char kAudioSubsystem[] = "sound";
     26 const char kVideoSubsystem[] = "video4linux";
     27 
     28 // Add more subsystems here for monitoring.
     29 const SubsystemMap kSubsystemMap[] = {
     30   { base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE, kAudioSubsystem, NULL },
     31   { base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE, kVideoSubsystem, NULL },
     32 };
     33 
     34 }  // namespace
     35 
     36 namespace content {
     37 
     38 DeviceMonitorLinux::DeviceMonitorLinux() {
     39   DCHECK(BrowserThread::IsMessageLoopValid(BrowserThread::IO));
     40   BrowserThread::PostTask(BrowserThread::IO,
     41       FROM_HERE,
     42       base::Bind(&DeviceMonitorLinux::Initialize, base::Unretained(this)));
     43 }
     44 
     45 DeviceMonitorLinux::~DeviceMonitorLinux() {
     46 }
     47 
     48 void DeviceMonitorLinux::Initialize() {
     49   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
     50 
     51   // We want to be notified of IO message loop destruction to delete |udev_|.
     52   base::MessageLoop::current()->AddDestructionObserver(this);
     53 
     54   std::vector<UdevLinux::UdevMonitorFilter> filters;
     55   for (size_t i = 0; i < arraysize(kSubsystemMap); ++i) {
     56     filters.push_back(UdevLinux::UdevMonitorFilter(
     57         kSubsystemMap[i].subsystem, kSubsystemMap[i].devtype));
     58   }
     59   udev_.reset(new UdevLinux(filters,
     60       base::Bind(&DeviceMonitorLinux::OnDevicesChanged,
     61                  base::Unretained(this))));
     62 }
     63 
     64 void DeviceMonitorLinux::WillDestroyCurrentMessageLoop() {
     65   // Called on IO thread.
     66   udev_.reset();
     67 }
     68 
     69 void DeviceMonitorLinux::OnDevicesChanged(udev_device* device) {
     70   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
     71   DCHECK(device);
     72 
     73   base::SystemMonitor::DeviceType device_type =
     74       base::SystemMonitor::DEVTYPE_UNKNOWN;
     75   std::string subsystem(udev_device_get_subsystem(device));
     76   for (size_t i = 0; i < arraysize(kSubsystemMap); ++i) {
     77     if (subsystem == kSubsystemMap[i].subsystem) {
     78       device_type = kSubsystemMap[i].device_type;
     79       break;
     80     }
     81   }
     82   DCHECK_NE(device_type, base::SystemMonitor::DEVTYPE_UNKNOWN);
     83 
     84   base::SystemMonitor::Get()->ProcessDevicesChanged(device_type);
     85 }
     86 
     87 }  // namespace content
     88