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 18namespace chromeos { 19 20namespace { 21 22// Sysfs directory containing V4L devices. 23const char kV4LSubsystemDir[] = "/sys/class/video4linux/"; 24// Name of the udev property with V4L capabilities. 25const char kV4LCapabilities[] = "ID_V4L_CAPABILITIES"; 26// Delimiter character for udev V4L capabilities. 27const char kV4LCapabilitiesDelim = ':'; 28// V4L capability that denotes a capture-enabled device. 29const char kV4LCaptureCapability[] = "capture"; 30 31} // namespace 32 33using content::BrowserThread; 34 35// static 36CameraDetector::CameraPresence CameraDetector::camera_presence_ = 37 CameraDetector::kCameraPresenceUnknown; 38 39// static 40bool CameraDetector::presence_check_in_progress_ = false; 41 42// static 43void 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 58void 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 67bool 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