1// Copyright 2013 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 <vector>
6
7#include "base/command_line.h"
8#include "base/files/file_path.h"
9#include "base/message_loop/message_loop.h"
10#include "base/run_loop.h"
11#include "base/stl_util.h"
12#include "chrome/browser/browser_process.h"
13#include "chrome/browser/extensions/extension_service.h"
14#include "chrome/browser/extensions/test_extension_system.h"
15#include "chrome/browser/media_galleries/media_file_system_registry.h"
16#include "chrome/browser/media_galleries/media_galleries_test_util.h"
17#include "chrome/test/base/chrome_render_view_host_test_harness.h"
18#include "chrome/test/base/testing_browser_process.h"
19#include "chrome/test/base/testing_profile.h"
20#include "components/storage_monitor/storage_info.h"
21#include "components/storage_monitor/storage_monitor.h"
22#include "components/storage_monitor/test_portable_device_watcher_win.h"
23#include "components/storage_monitor/test_storage_monitor.h"
24#include "components/storage_monitor/test_storage_monitor_win.h"
25#include "components/storage_monitor/test_volume_mount_watcher_win.h"
26#include "content/public/browser/render_view_host.h"
27#include "content/public/browser/web_contents.h"
28#include "extensions/browser/extension_system.h"
29#include "testing/gtest/include/gtest/gtest.h"
30
31using storage_monitor::PortableDeviceWatcherWin;
32using storage_monitor::StorageInfo;
33using storage_monitor::StorageMonitor;
34using storage_monitor::TestPortableDeviceWatcherWin;
35using storage_monitor::TestStorageMonitor;
36using storage_monitor::TestStorageMonitorWin;
37using storage_monitor::TestVolumeMountWatcherWin;
38
39namespace {
40
41typedef std::map<MediaGalleryPrefId, MediaFileSystemInfo> FSInfoMap;
42
43void GetGalleryInfoCallback(
44    FSInfoMap* results,
45    const std::vector<MediaFileSystemInfo>& file_systems) {
46  for (size_t i = 0; i < file_systems.size(); ++i) {
47    ASSERT_FALSE(ContainsKey(*results, file_systems[i].pref_id));
48    (*results)[file_systems[i].pref_id] = file_systems[i];
49  }
50}
51
52}  // namespace
53
54class MTPDeviceDelegateImplWinTest : public ChromeRenderViewHostTestHarness {
55 protected:
56  void SetUp() OVERRIDE;
57  void TearDown() OVERRIDE;
58
59  void ProcessAttach(const std::string& id,
60                     const base::string16& name,
61                     const base::FilePath::StringType& location);
62  std::string AttachDevice(StorageInfo::Type type,
63                           const std::string& unique_id,
64                           const base::FilePath& location);
65  void CheckGalleryInfo(const MediaFileSystemInfo& info,
66                        const base::string16& name,
67                        const base::FilePath& path,
68                        bool removable,
69                        bool media_device);
70
71  // Pointer to the storage monitor. Owned by TestingBrowserProcess.
72  TestStorageMonitorWin* monitor_;
73  scoped_refptr<extensions::Extension> extension_;
74
75  EnsureMediaDirectoriesExists media_directories_;
76};
77
78void MTPDeviceDelegateImplWinTest::SetUp() {
79  ChromeRenderViewHostTestHarness::SetUp();
80
81  TestStorageMonitor::Destroy();
82  TestPortableDeviceWatcherWin* portable_device_watcher =
83      new TestPortableDeviceWatcherWin;
84  TestVolumeMountWatcherWin* mount_watcher = new TestVolumeMountWatcherWin;
85  portable_device_watcher->set_use_dummy_mtp_storage_info(true);
86  scoped_ptr<TestStorageMonitorWin> monitor(
87      new TestStorageMonitorWin(mount_watcher, portable_device_watcher));
88  TestingBrowserProcess* browser_process = TestingBrowserProcess::GetGlobal();
89  DCHECK(browser_process);
90  monitor_ = monitor.get();
91  StorageMonitor::SetStorageMonitorForTesting(monitor.PassAs<StorageMonitor>());
92
93  base::RunLoop runloop;
94  browser_process->media_file_system_registry()->GetPreferences(profile())->
95      EnsureInitialized(runloop.QuitClosure());
96  runloop.Run();
97
98  extensions::TestExtensionSystem* extension_system(
99      static_cast<extensions::TestExtensionSystem*>(
100          extensions::ExtensionSystem::Get(profile())));
101  extension_system->CreateExtensionService(
102      CommandLine::ForCurrentProcess(), base::FilePath(), false);
103
104  std::vector<std::string> all_permissions;
105  all_permissions.push_back("allAutoDetected");
106  all_permissions.push_back("read");
107  extension_ = AddMediaGalleriesApp("all", all_permissions, profile());
108}
109
110void MTPDeviceDelegateImplWinTest::TearDown() {
111  // Windows storage monitor must be destroyed on the same thread
112  // as construction.
113  TestStorageMonitor::Destroy();
114
115  ChromeRenderViewHostTestHarness::TearDown();
116}
117
118void MTPDeviceDelegateImplWinTest::ProcessAttach(
119    const std::string& id,
120    const base::string16& label,
121    const base::FilePath::StringType& location) {
122  StorageInfo info(id, location, label, base::string16(), base::string16(), 0);
123  monitor_->receiver()->ProcessAttach(info);
124}
125
126std::string MTPDeviceDelegateImplWinTest::AttachDevice(
127    StorageInfo::Type type,
128    const std::string& unique_id,
129    const base::FilePath& location) {
130  std::string device_id = StorageInfo::MakeDeviceId(type, unique_id);
131  DCHECK(StorageInfo::IsRemovableDevice(device_id));
132  base::string16 label = location.LossyDisplayName();
133  ProcessAttach(device_id, label, location.value());
134  base::RunLoop().RunUntilIdle();
135  return device_id;
136}
137
138void MTPDeviceDelegateImplWinTest::CheckGalleryInfo(
139    const MediaFileSystemInfo& info,
140    const base::string16& name,
141    const base::FilePath& path,
142    bool removable,
143    bool media_device) {
144  EXPECT_EQ(name, info.name);
145  EXPECT_EQ(path, info.path);
146  EXPECT_EQ(removable, info.removable);
147  EXPECT_EQ(media_device, info.media_device);
148  EXPECT_NE(0UL, info.pref_id);
149
150  if (removable)
151    EXPECT_NE(0UL, info.transient_device_id.size());
152  else
153    EXPECT_EQ(0UL, info.transient_device_id.size());
154}
155
156TEST_F(MTPDeviceDelegateImplWinTest, GalleryNameMTP) {
157  base::FilePath location(
158      PortableDeviceWatcherWin::GetStoragePathFromStorageId(
159          TestPortableDeviceWatcherWin::kStorageUniqueIdA));
160  AttachDevice(StorageInfo::MTP_OR_PTP, "mtp_fake_id", location);
161
162  content::RenderViewHost* rvh = web_contents()->GetRenderViewHost();
163  FSInfoMap results;
164  MediaFileSystemRegistry* registry =
165      g_browser_process->media_file_system_registry();
166  registry->GetMediaFileSystemsForExtension(
167      rvh, extension_.get(),
168      base::Bind(&GetGalleryInfoCallback, base::Unretained(&results)));
169  base::RunLoop().RunUntilIdle();
170
171  ASSERT_EQ(media_directories_.num_galleries() + 1, results.size());
172  bool checked = false;
173  for (FSInfoMap::iterator i = results.begin(); i != results.end(); ++i) {
174    MediaFileSystemInfo info = i->second;
175    if (info.path == location) {
176      CheckGalleryInfo(info, location.LossyDisplayName(), location, true, true);
177      checked = true;
178      break;
179    }
180  }
181  EXPECT_TRUE(checked);
182}
183