Home | History | Annotate | Download | only in chromeos
      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 "chrome/browser/chromeos/camera_detector.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/files/file_enumerator.h"
      9 #include "base/files/file_util.h"
     10 #include "base/location.h"
     11 #include "base/strings/string_split.h"
     12 #include "base/strings/string_util.h"
     13 #include "base/task_runner_util.h"
     14 #include "base/threading/sequenced_worker_pool.h"
     15 #include "components/storage_monitor/udev_util_linux.h"
     16 #include "content/public/browser/browser_thread.h"
     17 
     18 namespace chromeos {
     19 
     20 namespace {
     21 
     22 // Sysfs directory containing V4L devices.
     23 const char kV4LSubsystemDir[] = "/sys/class/video4linux/";
     24 // Name of the udev property with V4L capabilities.
     25 const char kV4LCapabilities[] = "ID_V4L_CAPABILITIES";
     26 // Delimiter character for udev V4L capabilities.
     27 const char kV4LCapabilitiesDelim = ':';
     28 // V4L capability that denotes a capture-enabled device.
     29 const char kV4LCaptureCapability[] = "capture";
     30 
     31 }  // namespace
     32 
     33 using content::BrowserThread;
     34 
     35 // static
     36 CameraDetector::CameraPresence CameraDetector::camera_presence_ =
     37     CameraDetector::kCameraPresenceUnknown;
     38 
     39 // static
     40 bool CameraDetector::presence_check_in_progress_ = false;
     41 
     42 // static
     43 void CameraDetector::StartPresenceCheck(const base::Closure& callback) {
     44   DCHECK(BrowserThread::CurrentlyOn(content::BrowserThread::UI));
     45   if (presence_check_in_progress_)
     46     return;
     47   DVLOG(1) << "Starting camera presence check";
     48   presence_check_in_progress_ = true;
     49   base::PostTaskAndReplyWithResult(
     50       BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
     51           base::SequencedWorkerPool::SKIP_ON_SHUTDOWN).get(),
     52       FROM_HERE,
     53       base::Bind(&CameraDetector::CheckPresence),
     54       base::Bind(&CameraDetector::OnPresenceCheckDone, callback));
     55 }
     56 
     57 // static
     58 void CameraDetector::OnPresenceCheckDone(const base::Closure& callback,
     59                                          bool present) {
     60   DCHECK(BrowserThread::CurrentlyOn(content::BrowserThread::UI));
     61   camera_presence_ = present ? kCameraPresent : kCameraAbsent;
     62   presence_check_in_progress_ = false;
     63   callback.Run();
     64 }
     65 
     66 // static
     67 bool CameraDetector::CheckPresence() {
     68   // We do a quick check using udev database because opening each /dev/videoX
     69   // device may trigger costly device initialization.
     70   base::FileEnumerator file_enum(
     71       base::FilePath(kV4LSubsystemDir), false /* not recursive */,
     72       base::FileEnumerator::FILES | base::FileEnumerator::SHOW_SYM_LINKS);
     73   for (base::FilePath path = file_enum.Next(); !path.empty();
     74        path = file_enum.Next()) {
     75     std::string v4l_capabilities;
     76     if (storage_monitor::GetUdevDevicePropertyValueByPath(
     77             path, kV4LCapabilities, &v4l_capabilities)) {
     78       std::vector<std::string> caps;
     79       base::SplitString(v4l_capabilities, kV4LCapabilitiesDelim, &caps);
     80       if (find(caps.begin(), caps.end(), kV4LCaptureCapability) != caps.end()) {
     81         return true;
     82       }
     83     }
     84   }
     85   return false;
     86 }
     87 
     88 }  // namespace chromeos
     89