| // 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(BrowserThread::CurrentlyOn(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(BrowserThread::CurrentlyOn(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<std::string> caps; |
| base::SplitString(v4l_capabilities, kV4LCapabilitiesDelim, &caps); |
| if (find(caps.begin(), caps.end(), kV4LCaptureCapability) != caps.end()) { |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| |
| } // namespace chromeos |