// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/chromeos/camera_detector.h" #include "base/bind.h" #include "base/files/file_enumerator.h" #include "base/files/file_util.h" #include "base/location.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/task_runner_util.h" #include "base/threading/sequenced_worker_pool.h" #include "components/storage_monitor/udev_util_linux.h" #include "content/public/browser/browser_thread.h" namespace chromeos { namespace { // Sysfs directory containing V4L devices. const char kV4LSubsystemDir[] = "/sys/class/video4linux/"; // Name of the udev property with V4L capabilities. const char kV4LCapabilities[] = "ID_V4L_CAPABILITIES"; // Delimiter character for udev V4L capabilities. const char kV4LCapabilitiesDelim = ':'; // V4L capability that denotes a capture-enabled device. const char kV4LCaptureCapability[] = "capture"; } // namespace using content::BrowserThread; // static CameraDetector::CameraPresence CameraDetector::camera_presence_ = CameraDetector::kCameraPresenceUnknown; // static bool CameraDetector::presence_check_in_progress_ = false; // static void CameraDetector::StartPresenceCheck(const base::Closure& callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (presence_check_in_progress_) return; DVLOG(1) << "Starting camera presence check"; presence_check_in_progress_ = true; base::PostTaskAndReplyWithResult( BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior( base::SequencedWorkerPool::SKIP_ON_SHUTDOWN).get(), FROM_HERE, base::Bind(&CameraDetector::CheckPresence), base::Bind(&CameraDetector::OnPresenceCheckDone, callback)); } // static void CameraDetector::OnPresenceCheckDone(const base::Closure& callback, bool present) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); camera_presence_ = present ? kCameraPresent : kCameraAbsent; presence_check_in_progress_ = false; callback.Run(); } // static bool CameraDetector::CheckPresence() { // We do a quick check using udev database because opening each /dev/videoX // device may trigger costly device initialization. base::FileEnumerator file_enum( base::FilePath(kV4LSubsystemDir), false /* not recursive */, base::FileEnumerator::FILES | base::FileEnumerator::SHOW_SYM_LINKS); for (base::FilePath path = file_enum.Next(); !path.empty(); path = file_enum.Next()) { std::string v4l_capabilities; if (storage_monitor::GetUdevDevicePropertyValueByPath( path, kV4LCapabilities, &v4l_capabilities)) { std::vector caps; base::SplitString(v4l_capabilities, kV4LCapabilitiesDelim, &caps); if (find(caps.begin(), caps.end(), kV4LCaptureCapability) != caps.end()) { return true; } } } return false; } } // namespace chromeos