Add SystemMonitor::GetAttachedMediaDevices().

BUG=none
TEST=included
Review URL: https://chromiumcodereview.appspot.com/10332190

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@138148 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/base/system_monitor/system_monitor.cc b/base/system_monitor/system_monitor.cc
index afca3fc..fa25f71 100644
--- a/base/system_monitor/system_monitor.cc
+++ b/base/system_monitor/system_monitor.cc
@@ -4,6 +4,8 @@
 
 #include "base/system_monitor/system_monitor.h"
 
+#include <utility>
+
 #include "base/file_path.h"
 #include "base/logging.h"
 #include "base/message_loop.h"
@@ -87,13 +89,28 @@
 void SystemMonitor::ProcessMediaDeviceAttached(const DeviceIdType& id,
                                                const std::string& name,
                                                const FilePath& path) {
+  media_device_map_.insert(std::make_pair(id, MakeTuple(id, name, path)));
   NotifyMediaDeviceAttached(id, name, path);
 }
 
 void SystemMonitor::ProcessMediaDeviceDetached(const DeviceIdType& id) {
+  MediaDeviceMap::iterator it = media_device_map_.find(id);
+  if (it != media_device_map_.end())
+    media_device_map_.erase(it);
   NotifyMediaDeviceDetached(id);
 }
 
+std::vector<SystemMonitor::MediaDeviceInfo>*
+SystemMonitor::GetAttachedMediaDevices() const {
+  std::vector<MediaDeviceInfo>* results = new std::vector<MediaDeviceInfo>;
+  for (MediaDeviceMap::const_iterator it = media_device_map_.begin();
+       it != media_device_map_.end();
+       ++it) {
+    results->push_back(it->second);
+  }
+  return results;
+}
+
 void SystemMonitor::AddPowerObserver(PowerObserver* obs) {
   power_observer_list_->AddObserver(obs);
 }
diff --git a/base/system_monitor/system_monitor.h b/base/system_monitor/system_monitor.h
index e0decc92..d88ef09 100644
--- a/base/system_monitor/system_monitor.h
+++ b/base/system_monitor/system_monitor.h
@@ -9,10 +9,12 @@
 #include <map>
 #include <string>
 #include <utility>
+#include <vector>
 
 #include "base/base_export.h"
 #include "base/basictypes.h"
 #include "base/threading/thread_checker.h"
+#include "base/tuple.h"
 #include "build/build_config.h"
 
 // Windows HiRes timers drain the battery faster so we need to know the battery
@@ -57,6 +59,8 @@
   };
 
   typedef unsigned int DeviceIdType;
+  // (Media device id, Media device name, Media device path)
+  typedef Tuple3<DeviceIdType, std::string, FilePath> MediaDeviceInfo;
 
   // Create SystemMonitor. Only one SystemMonitor instance per application
   // is allowed.
@@ -155,6 +159,9 @@
                                   const FilePath& path);
   void ProcessMediaDeviceDetached(const DeviceIdType& id);
 
+  // Returns information for attached media devices.
+  std::vector<MediaDeviceInfo>* GetAttachedMediaDevices() const;
+
   // Enters or leaves a period of time with a given |requirement|. If the
   // operation has multiple requirements, make sure to use a unique |reason| for
   // each one. Reusing the same |reason| is OK as far as the |requirement| is
@@ -172,6 +179,8 @@
   size_t GetPowerRequirementsCountForTest() const;
 
  private:
+  typedef std::map<base::SystemMonitor::DeviceIdType,
+                   MediaDeviceInfo> MediaDeviceMap;
 #if defined(OS_MACOSX)
   void PlatformInit();
   void PlatformDestroy();
@@ -211,6 +220,8 @@
   base::OneShotTimer<SystemMonitor> delayed_battery_check_;
 #endif
 
+  MediaDeviceMap media_device_map_;
+
   DISALLOW_COPY_AND_ASSIGN(SystemMonitor);
 };
 
diff --git a/base/system_monitor/system_monitor_unittest.cc b/base/system_monitor/system_monitor_unittest.cc
index 4475dcb..d568799 100644
--- a/base/system_monitor/system_monitor_unittest.cc
+++ b/base/system_monitor/system_monitor_unittest.cc
@@ -2,9 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/file_path.h"
-#include "base/test/mock_devices_changed_observer.h"
 #include "base/system_monitor/system_monitor.h"
+
+#include "base/file_path.h"
+#include "base/message_loop.h"
+#include "base/test/mock_devices_changed_observer.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -137,6 +139,75 @@
   loop.RunAllPending();
 }
 
+TEST(SystemMonitor, GetAttachedMediaDevicesEmpty) {
+  // Initialize a message loop for this to run on.
+  MessageLoop loop;
+
+#if defined(OS_MACOSX)
+  SystemMonitor::AllocateSystemIOPorts();
+#endif
+
+  SystemMonitor system_monitor;
+
+  scoped_ptr<std::vector<SystemMonitor::MediaDeviceInfo> > devices;
+  devices.reset(system_monitor.GetAttachedMediaDevices());
+  EXPECT_EQ(0U, devices->size());
+}
+
+TEST(SystemMonitor, GetAttachedMediaDevicesAttachDetach) {
+  // Initialize a message loop for this to run on.
+  MessageLoop loop;
+
+#if defined(OS_MACOSX)
+  SystemMonitor::AllocateSystemIOPorts();
+#endif
+
+  SystemMonitor system_monitor;
+
+  const SystemMonitor::DeviceIdType kDeviceId1 = 42;
+  const char kDeviceName1[] = "test";
+  const FilePath kDevicePath1(FILE_PATH_LITERAL("/testfoo"));
+  system_monitor.ProcessMediaDeviceAttached(kDeviceId1,
+                                            kDeviceName1,
+                                            kDevicePath1);
+  loop.RunAllPending();
+  scoped_ptr<std::vector<SystemMonitor::MediaDeviceInfo> > devices;
+  devices.reset(system_monitor.GetAttachedMediaDevices());
+  ASSERT_EQ(1U, devices->size());
+  EXPECT_EQ(kDeviceId1, (*devices)[0].a);
+  EXPECT_EQ(kDeviceName1, (*devices)[0].b);
+  EXPECT_EQ(kDevicePath1, (*devices)[0].c);
+
+  const SystemMonitor::DeviceIdType kDeviceId2 = 44;
+  const char kDeviceName2[] = "test2";
+  const FilePath kDevicePath2(FILE_PATH_LITERAL("/testbar"));
+  system_monitor.ProcessMediaDeviceAttached(kDeviceId2,
+                                            kDeviceName2,
+                                            kDevicePath2);
+  loop.RunAllPending();
+  devices.reset(system_monitor.GetAttachedMediaDevices());
+  ASSERT_EQ(2U, devices->size());
+  EXPECT_EQ(kDeviceId1, (*devices)[0].a);
+  EXPECT_EQ(kDeviceName1, (*devices)[0].b);
+  EXPECT_EQ(kDevicePath1, (*devices)[0].c);
+  EXPECT_EQ(kDeviceId2, (*devices)[1].a);
+  EXPECT_EQ(kDeviceName2, (*devices)[1].b);
+  EXPECT_EQ(kDevicePath2, (*devices)[1].c);
+
+  system_monitor.ProcessMediaDeviceDetached(kDeviceId1);
+  loop.RunAllPending();
+  devices.reset(system_monitor.GetAttachedMediaDevices());
+  ASSERT_EQ(1U, devices->size());
+  EXPECT_EQ(kDeviceId2, (*devices)[0].a);
+  EXPECT_EQ(kDeviceName2, (*devices)[0].b);
+  EXPECT_EQ(kDevicePath2, (*devices)[0].c);
+
+  system_monitor.ProcessMediaDeviceDetached(kDeviceId2);
+  loop.RunAllPending();
+  devices.reset(system_monitor.GetAttachedMediaDevices());
+  EXPECT_EQ(0U, devices->size());
+}
+
 TEST(SystemMonitor, PowerRequirements) {
 #if defined(OS_WIN)
   MessageLoop loop;