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/file_util.h" 9 #include "base/files/file_enumerator.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 "chrome/browser/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 (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