1 // Copyright 2014 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 "base/bind.h" 6 #include "base/command_line.h" 7 #include "base/files/file_path.h" 8 #include "base/run_loop.h" 9 #include "base/strings/string16.h" 10 #include "base/strings/string_util.h" 11 #include "base/strings/utf_string_conversions.h" 12 #include "chrome/browser/extensions/test_extension_system.h" 13 #include "chrome/browser/media_galleries/media_galleries_dialog_controller_test_util.h" 14 #include "chrome/browser/media_galleries/media_galleries_permission_controller.h" 15 #include "chrome/browser/media_galleries/media_galleries_preferences.h" 16 #include "chrome/browser/media_galleries/media_galleries_test_util.h" 17 #include "chrome/test/base/testing_profile.h" 18 #include "components/storage_monitor/storage_info.h" 19 #include "components/storage_monitor/test_storage_monitor.h" 20 #include "content/public/test/test_browser_thread_bundle.h" 21 #include "extensions/common/permissions/media_galleries_permission.h" 22 #include "testing/gtest/include/gtest/gtest.h" 23 24 #if defined(OS_CHROMEOS) 25 #include "chrome/browser/chromeos/login/users/scoped_test_user_manager.h" 26 #include "chrome/browser/chromeos/settings/cros_settings.h" 27 #include "chrome/browser/chromeos/settings/device_settings_service.h" 28 #endif 29 30 using storage_monitor::StorageInfo; 31 using storage_monitor::TestStorageMonitor; 32 33 namespace { 34 35 std::string GalleryName(const MediaGalleryPrefInfo& gallery) { 36 base::string16 name = gallery.GetGalleryDisplayName(); 37 return base::UTF16ToASCII(name); 38 } 39 40 } // namespace 41 42 class MediaGalleriesPermissionControllerTest : public ::testing::Test { 43 public: 44 MediaGalleriesPermissionControllerTest() 45 : dialog_(NULL), 46 dialog_update_count_at_destruction_(0), 47 controller_(NULL), 48 profile_(new TestingProfile()), 49 weak_factory_(this) { 50 } 51 52 virtual ~MediaGalleriesPermissionControllerTest() { 53 EXPECT_FALSE(controller_); 54 EXPECT_FALSE(dialog_); 55 } 56 57 virtual void SetUp() OVERRIDE { 58 ASSERT_TRUE(TestStorageMonitor::CreateAndInstall()); 59 60 extensions::TestExtensionSystem* extension_system( 61 static_cast<extensions::TestExtensionSystem*>( 62 extensions::ExtensionSystem::Get(profile_.get()))); 63 extension_system->CreateExtensionService( 64 CommandLine::ForCurrentProcess(), base::FilePath(), false); 65 66 gallery_prefs_.reset(new MediaGalleriesPreferences(profile_.get())); 67 base::RunLoop loop; 68 gallery_prefs_->EnsureInitialized(loop.QuitClosure()); 69 loop.Run(); 70 71 std::vector<std::string> read_permissions; 72 read_permissions.push_back( 73 extensions::MediaGalleriesPermission::kReadPermission); 74 extension_ = AddMediaGalleriesApp("read", read_permissions, profile_.get()); 75 } 76 77 virtual void TearDown() OVERRIDE { 78 TestStorageMonitor::Destroy(); 79 } 80 81 void StartDialog() { 82 ASSERT_FALSE(controller_); 83 controller_ = new MediaGalleriesPermissionController( 84 *extension_.get(), 85 gallery_prefs_.get(), 86 base::Bind(&MediaGalleriesPermissionControllerTest::CreateMockDialog, 87 base::Unretained(this)), 88 base::Bind( 89 &MediaGalleriesPermissionControllerTest::OnControllerDone, 90 base::Unretained(this))); 91 } 92 93 MediaGalleriesPermissionController* controller() { 94 return controller_; 95 } 96 97 MockMediaGalleriesDialog* dialog() { 98 return dialog_; 99 } 100 101 int dialog_update_count_at_destruction() { 102 EXPECT_FALSE(dialog_); 103 return dialog_update_count_at_destruction_; 104 } 105 106 extensions::Extension* extension() { 107 return extension_.get(); 108 } 109 110 MediaGalleriesPreferences* gallery_prefs() { 111 return gallery_prefs_.get(); 112 } 113 114 GalleryDialogId GetDialogIdFromPrefId(MediaGalleryPrefId pref_id); 115 116 void TestForgottenType(MediaGalleryPrefInfo::Type type, 117 bool forget_preserves_pref_id); 118 119 protected: 120 EnsureMediaDirectoriesExists mock_gallery_locations_; 121 122 private: 123 MediaGalleriesDialog* CreateMockDialog( 124 MediaGalleriesDialogController* controller) { 125 EXPECT_FALSE(dialog_); 126 dialog_update_count_at_destruction_ = 0; 127 dialog_ = new MockMediaGalleriesDialog(base::Bind( 128 &MediaGalleriesPermissionControllerTest::OnDialogDestroyed, 129 weak_factory_.GetWeakPtr())); 130 return dialog_; 131 } 132 133 void OnDialogDestroyed(int update_count) { 134 EXPECT_TRUE(dialog_); 135 dialog_update_count_at_destruction_ = update_count; 136 dialog_ = NULL; 137 } 138 139 void OnControllerDone() { 140 controller_ = NULL; 141 } 142 143 // Needed for extension service & friends to work. 144 content::TestBrowserThreadBundle thread_bundle_; 145 146 // The dialog is owned by the controller, but this pointer should only be 147 // valid while the dialog is live within the controller. 148 MockMediaGalleriesDialog* dialog_; 149 int dialog_update_count_at_destruction_; 150 151 // The controller owns itself. 152 MediaGalleriesPermissionController* controller_; 153 154 scoped_refptr<extensions::Extension> extension_; 155 156 #if defined OS_CHROMEOS 157 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_; 158 chromeos::ScopedTestCrosSettings test_cros_settings_; 159 chromeos::ScopedTestUserManager test_user_manager_; 160 #endif 161 162 TestStorageMonitor monitor_; 163 scoped_ptr<TestingProfile> profile_; 164 scoped_ptr<MediaGalleriesPreferences> gallery_prefs_; 165 166 base::WeakPtrFactory<MediaGalleriesPermissionControllerTest> 167 weak_factory_; 168 169 DISALLOW_COPY_AND_ASSIGN(MediaGalleriesPermissionControllerTest); 170 }; 171 172 GalleryDialogId 173 MediaGalleriesPermissionControllerTest::GetDialogIdFromPrefId( 174 MediaGalleryPrefId pref_id) { 175 return controller_->GetDialogId(pref_id); 176 } 177 178 void MediaGalleriesPermissionControllerTest::TestForgottenType( 179 MediaGalleryPrefInfo::Type type, bool forget_preserves_pref_id) { 180 EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size()); 181 182 MediaGalleryPrefId forgotten1 = gallery_prefs()->AddGalleryByPath( 183 MakeMediaGalleriesTestingPath("forgotten1"), type); 184 MediaGalleryPrefId forgotten2 = gallery_prefs()->AddGalleryByPath( 185 MakeMediaGalleriesTestingPath("forgotten2"), type); 186 // Show dialog and accept to verify 2 entries 187 StartDialog(); 188 EXPECT_EQ(0U, controller()->GetSectionEntries(0).size()); 189 EXPECT_EQ(mock_gallery_locations_.num_galleries() + 2U, 190 controller()->GetSectionEntries(1).size()); 191 controller()->DidToggleEntry(GetDialogIdFromPrefId(forgotten1), true); 192 controller()->DidToggleEntry(GetDialogIdFromPrefId(forgotten2), true); 193 controller()->DialogFinished(true); 194 EXPECT_EQ(2U, gallery_prefs()->GalleriesForExtension(*extension()).size()); 195 196 // Forget one and cancel to see that it's still there. 197 StartDialog(); 198 EXPECT_EQ(2U, controller()->GetSectionEntries(0).size()); 199 controller()->DidForgetEntry(GetDialogIdFromPrefId(forgotten1)); 200 EXPECT_EQ(1U, controller()->GetSectionEntries(0).size()); 201 controller()->DialogFinished(false); 202 EXPECT_EQ(2U, gallery_prefs()->GalleriesForExtension(*extension()).size()); 203 204 // Forget one and confirm to see that it's gone. 205 StartDialog(); 206 EXPECT_EQ(2U, controller()->GetSectionEntries(0).size()); 207 controller()->DidForgetEntry(GetDialogIdFromPrefId(forgotten1)); 208 EXPECT_EQ(1U, controller()->GetSectionEntries(0).size()); 209 controller()->DialogFinished(true); 210 EXPECT_EQ(1U, gallery_prefs()->GalleriesForExtension(*extension()).size()); 211 212 // Add back and test whether the same pref id is preserved. 213 StartDialog(); 214 controller()->FileSelected( 215 MakeMediaGalleriesTestingPath("forgotten1"), 0, NULL); 216 controller()->DialogFinished(true); 217 EXPECT_EQ(2U, gallery_prefs()->GalleriesForExtension(*extension()).size()); 218 MediaGalleryPrefInfo retrieved_info; 219 EXPECT_TRUE(gallery_prefs()->LookUpGalleryByPath( 220 MakeMediaGalleriesTestingPath("forgotten1"), &retrieved_info)); 221 EXPECT_EQ(forget_preserves_pref_id, retrieved_info.pref_id == forgotten1); 222 223 // Add a new one and forget it & see that it's gone. 224 MediaGalleryPrefId forgotten3 = gallery_prefs()->AddGalleryByPath( 225 MakeMediaGalleriesTestingPath("forgotten3"), type); 226 StartDialog(); 227 EXPECT_EQ(2U, controller()->GetSectionEntries(0).size()); 228 EXPECT_EQ(mock_gallery_locations_.num_galleries() + 1U, 229 controller()->GetSectionEntries(1).size()); 230 controller()->DidToggleEntry(GetDialogIdFromPrefId(forgotten3), true); 231 controller()->DidForgetEntry(GetDialogIdFromPrefId(forgotten3)); 232 EXPECT_EQ(2U, controller()->GetSectionEntries(0).size()); 233 EXPECT_EQ(static_cast<unsigned long>(mock_gallery_locations_.num_galleries()), 234 controller()->GetSectionEntries(1).size()); 235 controller()->DialogFinished(true); 236 EXPECT_EQ(2U, gallery_prefs()->GalleriesForExtension(*extension()).size()); 237 } 238 239 TEST_F(MediaGalleriesPermissionControllerTest, TestForgottenUserAdded) { 240 TestForgottenType(MediaGalleryPrefInfo::kUserAdded, 241 false /* forget_preserves_pref_id */); 242 } 243 244 TEST_F(MediaGalleriesPermissionControllerTest, TestForgottenAutoDetected) { 245 TestForgottenType(MediaGalleryPrefInfo::kAutoDetected, 246 true /* forget_preserves_pref_id */); 247 } 248 249 TEST_F(MediaGalleriesPermissionControllerTest, TestForgottenScanResult) { 250 TestForgottenType(MediaGalleryPrefInfo::kScanResult, 251 true /* forget_preserves_pref_id */); 252 } 253 254 TEST_F(MediaGalleriesPermissionControllerTest, TestNameGeneration) { 255 MediaGalleryPrefInfo gallery; 256 gallery.pref_id = 1; 257 gallery.device_id = StorageInfo::MakeDeviceId( 258 StorageInfo::FIXED_MASS_STORAGE, "/path/to/gallery"); 259 gallery.type = MediaGalleryPrefInfo::kAutoDetected; 260 std::string galleryName("/path/to/gallery"); 261 #if defined(OS_CHROMEOS) 262 galleryName = "gallery"; 263 #endif 264 EXPECT_EQ(galleryName, GalleryName(gallery)); 265 266 gallery.display_name = base::ASCIIToUTF16("override"); 267 EXPECT_EQ("override", GalleryName(gallery)); 268 269 gallery.display_name = base::string16(); 270 gallery.volume_label = base::ASCIIToUTF16("label"); 271 EXPECT_EQ(galleryName, GalleryName(gallery)); 272 273 gallery.path = base::FilePath(FILE_PATH_LITERAL("sub/gallery2")); 274 galleryName = "/path/to/gallery/sub/gallery2"; 275 #if defined(OS_CHROMEOS) 276 galleryName = "gallery2"; 277 #endif 278 #if defined(OS_WIN) 279 galleryName = base::FilePath(FILE_PATH_LITERAL("/path/to/gallery")) 280 .Append(gallery.path).MaybeAsASCII(); 281 #endif 282 EXPECT_EQ(galleryName, GalleryName(gallery)); 283 284 gallery.path = base::FilePath(); 285 gallery.device_id = StorageInfo::MakeDeviceId( 286 StorageInfo::REMOVABLE_MASS_STORAGE_WITH_DCIM, 287 "/path/to/dcim"); 288 gallery.display_name = base::ASCIIToUTF16("override"); 289 EXPECT_EQ("override", GalleryName(gallery)); 290 291 gallery.volume_label = base::ASCIIToUTF16("volume"); 292 gallery.vendor_name = base::ASCIIToUTF16("vendor"); 293 gallery.model_name = base::ASCIIToUTF16("model"); 294 EXPECT_EQ("override", GalleryName(gallery)); 295 296 gallery.display_name = base::string16(); 297 EXPECT_EQ("volume", GalleryName(gallery)); 298 299 gallery.volume_label = base::string16(); 300 EXPECT_EQ("vendor, model", GalleryName(gallery)); 301 302 gallery.total_size_in_bytes = 1000000; 303 EXPECT_EQ("977 KB vendor, model", GalleryName(gallery)); 304 305 gallery.path = base::FilePath(FILE_PATH_LITERAL("sub/path")); 306 EXPECT_EQ("path - 977 KB vendor, model", GalleryName(gallery)); 307 } 308