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.
6 #include "base/command_line.h"
7 #include "base/files/file_path.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/memory/weak_ptr.h"
10 #include "base/run_loop.h"
11 #include "base/strings/string16.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/time/time.h"
14 #include "chrome/browser/extensions/test_extension_system.h"
15 #include "chrome/browser/media_galleries/media_galleries_preferences.h"
16 #include "chrome/browser/media_galleries/media_galleries_scan_result_dialog_controller.h"
17 #include "chrome/browser/media_galleries/media_galleries_test_util.h"
18 #include "chrome/browser/storage_monitor/test_storage_monitor.h"
19 #include "chrome/common/extensions/permissions/media_galleries_permission.h"
20 #include "chrome/test/base/testing_profile.h"
21 #include "content/public/test/test_browser_thread_bundle.h"
22 #include "extensions/browser/extension_system.h"
23 #include "extensions/common/extension.h"
24 #include "testing/gtest/include/gtest/gtest.h"
26 #if defined(OS_CHROMEOS)
27 #include "chrome/browser/chromeos/login/user_manager.h"
28 #include "chrome/browser/chromeos/settings/cros_settings.h"
29 #include "chrome/browser/chromeos/settings/device_settings_service.h"
34 class MockMediaGalleriesScanResultDialog
35 : public MediaGalleriesScanResultDialog
{
37 typedef base::Callback
<void(int update_count
)> DialogDestroyedCallback
;
39 explicit MockMediaGalleriesScanResultDialog(
40 const DialogDestroyedCallback
& callback
)
42 dialog_destroyed_callback_(callback
) {
45 virtual ~MockMediaGalleriesScanResultDialog() {
46 dialog_destroyed_callback_
.Run(update_count_
);
49 // MockMediaGalleriesScanResultDialog implementation.
50 virtual void UpdateResults() OVERRIDE
{
54 // Number up times UpdateResults has been called.
62 DialogDestroyedCallback dialog_destroyed_callback_
;
64 DISALLOW_COPY_AND_ASSIGN(MockMediaGalleriesScanResultDialog
);
69 class MediaGalleriesScanResultDialogControllerTest
: public testing::Test
{
71 MediaGalleriesScanResultDialogControllerTest()
73 dialog_update_count_at_destruction_(0),
75 profile_(new TestingProfile()),
79 virtual ~MediaGalleriesScanResultDialogControllerTest() {
80 EXPECT_FALSE(controller_
);
81 EXPECT_FALSE(dialog_
);
84 virtual void SetUp() OVERRIDE
{
85 ASSERT_TRUE(TestStorageMonitor::CreateAndInstall());
87 extensions::TestExtensionSystem
* extension_system(
88 static_cast<extensions::TestExtensionSystem
*>(
89 extensions::ExtensionSystem::Get(profile_
.get())));
90 extension_system
->CreateExtensionService(
91 CommandLine::ForCurrentProcess(), base::FilePath(), false);
93 gallery_prefs_
.reset(new MediaGalleriesPreferences(profile_
.get()));
95 gallery_prefs_
->EnsureInitialized(loop
.QuitClosure());
98 std::vector
<std::string
> read_permissions
;
99 read_permissions
.push_back(
100 extensions::MediaGalleriesPermission::kReadPermission
);
101 extension_
= AddMediaGalleriesApp("read", read_permissions
, profile_
.get());
104 virtual void TearDown() OVERRIDE
{
105 TestStorageMonitor::RemoveSingleton();
109 ASSERT_FALSE(controller_
);
110 controller_
= new MediaGalleriesScanResultDialogController(
112 gallery_prefs_
.get(),
114 &MediaGalleriesScanResultDialogControllerTest::CreateMockDialog
,
115 base::Unretained(this)),
117 &MediaGalleriesScanResultDialogControllerTest::OnControllerDone
,
118 base::Unretained(this)));
121 MediaGalleriesScanResultDialogController
* controller() {
125 MockMediaGalleriesScanResultDialog
* dialog() {
129 int dialog_update_count_at_destruction() {
130 EXPECT_FALSE(dialog_
);
131 return dialog_update_count_at_destruction_
;
134 extensions::Extension
* extension() {
135 return extension_
.get();
138 MediaGalleriesPreferences
* gallery_prefs() {
139 return gallery_prefs_
.get();
142 MediaGalleryPrefId
AddGallery(const std::string
& path
,
143 MediaGalleryPrefInfo::Type type
,
144 int audio_count
, int image_count
,
146 MediaGalleryPrefInfo gallery_info
;
147 gallery_prefs_
->LookUpGalleryByPath(MakeMediaGalleriesTestingPath(path
),
149 return gallery_prefs_
->AddGallery(
150 gallery_info
.device_id
,
153 gallery_info
.volume_label
,
154 gallery_info
.vendor_name
,
155 gallery_info
.model_name
,
156 gallery_info
.total_size_in_bytes
,
157 gallery_info
.last_attach_time
,
158 audio_count
, image_count
, video_count
);
161 MediaGalleryPrefId
AddScanResult(const std::string
& path
, int audio_count
,
162 int image_count
, int video_count
) {
163 return AddGallery(path
, MediaGalleryPrefInfo::kScanResult
, audio_count
,
164 image_count
, video_count
);
168 MediaGalleriesScanResultDialog
* CreateMockDialog(
169 MediaGalleriesScanResultDialogController
* controller
) {
170 EXPECT_FALSE(dialog_
);
171 dialog_update_count_at_destruction_
= 0;
172 dialog_
= new MockMediaGalleriesScanResultDialog(base::Bind(
173 &MediaGalleriesScanResultDialogControllerTest::OnDialogDestroyed
,
174 weak_factory_
.GetWeakPtr()));
178 void OnDialogDestroyed(int update_count
) {
179 EXPECT_TRUE(dialog_
);
180 dialog_update_count_at_destruction_
= update_count
;
184 void OnControllerDone() {
188 // Needed for extension service & friends to work.
189 content::TestBrowserThreadBundle thread_bundle_
;
191 // The dialog is owned by the controller, but this pointer should only be
192 // valid while the dialog is live within the controller.
193 MockMediaGalleriesScanResultDialog
* dialog_
;
194 int dialog_update_count_at_destruction_
;
196 // The controller owns itself.
197 MediaGalleriesScanResultDialogController
* controller_
;
199 scoped_refptr
<extensions::Extension
> extension_
;
201 EnsureMediaDirectoriesExists mock_gallery_locations_
;
203 #if defined OS_CHROMEOS
204 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_
;
205 chromeos::ScopedTestCrosSettings test_cros_settings_
;
206 chromeos::ScopedTestUserManager test_user_manager_
;
209 TestStorageMonitor monitor_
;
210 scoped_ptr
<TestingProfile
> profile_
;
211 scoped_ptr
<MediaGalleriesPreferences
> gallery_prefs_
;
213 base::WeakPtrFactory
<MediaGalleriesScanResultDialogControllerTest
>
216 DISALLOW_COPY_AND_ASSIGN(MediaGalleriesScanResultDialogControllerTest
);
219 TEST_F(MediaGalleriesScanResultDialogControllerTest
, EmptyDialog
) {
221 EXPECT_TRUE(controller());
222 EXPECT_TRUE(dialog());
223 EXPECT_EQ(0U, controller()->GetGalleryList().size());
225 controller()->DialogFinished(true);
226 EXPECT_FALSE(controller());
227 EXPECT_FALSE(dialog());
228 EXPECT_EQ(0, dialog_update_count_at_destruction());
231 TEST_F(MediaGalleriesScanResultDialogControllerTest
, AddScanResults
) {
232 // Start with two scan results.
233 MediaGalleryPrefId scan_id
= AddScanResult("scan_id", 1, 0, 0);
234 MediaGalleryPrefId auto_id
=
235 AddGallery("auto_id", MediaGalleryPrefInfo::kAutoDetected
, 2, 0, 0);
236 EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
238 // Show the dialog, but cancel it.
240 EXPECT_EQ(2U, controller()->GetGalleryList().size());
241 controller()->DialogFinished(false);
242 EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
244 // Show the dialog, unselect both and accept it.
246 EXPECT_EQ(2U, controller()->GetGalleryList().size());
247 controller()->DidToggleGalleryId(scan_id
, false);
248 controller()->DidToggleGalleryId(auto_id
, false);
249 controller()->DialogFinished(true);
250 EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
252 // Show the dialog, leave one selected and accept it.
254 EXPECT_EQ(2U, controller()->GetGalleryList().size());
255 controller()->DidToggleGalleryId(scan_id
, false);
256 controller()->DialogFinished(true);
257 MediaGalleryPrefIdSet permitted
=
258 gallery_prefs()->GalleriesForExtension(*extension());
259 ASSERT_EQ(1U, permitted
.size());
260 EXPECT_EQ(auto_id
, *permitted
.begin());
262 // Show the dialog, toggle the remaining entry twice and then accept it.
264 EXPECT_EQ(1U, controller()->GetGalleryList().size());
265 controller()->DidToggleGalleryId(scan_id
, false);
266 controller()->DidToggleGalleryId(scan_id
, true);
267 controller()->DialogFinished(true);
268 EXPECT_EQ(2U, gallery_prefs()->GalleriesForExtension(*extension()).size());
271 TEST_F(MediaGalleriesScanResultDialogControllerTest
, Blacklisted
) {
272 // Start with two scan results.
273 MediaGalleryPrefId scan_id
= AddScanResult("scan_id", 1, 0, 0);
274 MediaGalleryPrefId auto_id
=
275 AddGallery("auto_id", MediaGalleryPrefInfo::kAutoDetected
, 2, 0, 0);
276 EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
278 // Show the dialog, but cancel it.
280 EXPECT_EQ(2U, controller()->GetGalleryList().size());
281 controller()->DialogFinished(false);
282 EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
284 // Blacklist one and try again.
285 gallery_prefs()->ForgetGalleryById(scan_id
);
287 EXPECT_EQ(1U, controller()->GetGalleryList().size());
288 controller()->DialogFinished(false);
290 // Adding it as a user gallery should change its type.
291 AddGallery("scan_id", MediaGalleryPrefInfo::kUserAdded
, 1, 0, 0);
293 EXPECT_EQ(2U, controller()->GetGalleryList().size());
295 // Blacklisting the other while the dialog is open should remove it.
296 gallery_prefs()->ForgetGalleryById(auto_id
);
297 EXPECT_EQ(1U, controller()->GetGalleryList().size());
298 controller()->DialogFinished(false);
299 EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
300 EXPECT_EQ(1, dialog_update_count_at_destruction());
303 TEST_F(MediaGalleriesScanResultDialogControllerTest
, PrefUpdates
) {
304 MediaGalleryPrefId selected
= AddScanResult("selected", 1, 0, 0);
305 MediaGalleryPrefId unselected
= AddScanResult("unselected", 1, 0, 0);
306 MediaGalleryPrefId selected_add_permission
=
307 AddScanResult("selected_add_permission", 1, 0, 0);
308 MediaGalleryPrefId unselected_add_permission
=
309 AddScanResult("unselected_add_permission", 1, 0, 0);
310 MediaGalleryPrefId selected_removed
=
311 AddScanResult("selected_removed", 1, 0, 0);
312 MediaGalleryPrefId unselected_removed
=
313 AddScanResult("unselected_removed", 1, 0, 0);
314 MediaGalleryPrefId selected_update
=
315 AddScanResult("selected_update", 1, 0, 0);
316 MediaGalleryPrefId unselected_update
=
317 AddScanResult("unselected_update", 1, 0, 0);
319 gallery_prefs()->AddGalleryByPath(MakeMediaGalleriesTestingPath("user"),
320 MediaGalleryPrefInfo::kUserAdded
);
321 gallery_prefs()->AddGalleryByPath(
322 MakeMediaGalleriesTestingPath("auto_detected"),
323 MediaGalleryPrefInfo::kAutoDetected
);
324 MediaGalleryPrefId blacklisted
= gallery_prefs()->AddGalleryByPath(
325 MakeMediaGalleriesTestingPath("blacklisted"),
326 MediaGalleryPrefInfo::kAutoDetected
);
327 gallery_prefs()->ForgetGalleryById(blacklisted
);
328 EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
331 EXPECT_EQ(8U, controller()->GetGalleryList().size());
332 controller()->DidToggleGalleryId(unselected
, false);
333 controller()->DidToggleGalleryId(unselected_add_permission
, false);
334 controller()->DidToggleGalleryId(unselected_removed
, false);
335 controller()->DidToggleGalleryId(unselected_update
, false);
336 EXPECT_EQ(0, dialog()->update_count());
337 EXPECT_EQ(8U, controller()->GetGalleryList().size());
340 gallery_prefs()->SetGalleryPermissionForExtension(*extension(),
341 unselected_add_permission
,
343 EXPECT_EQ(1, dialog()->update_count());
344 EXPECT_EQ(7U, controller()->GetGalleryList().size());
345 gallery_prefs()->SetGalleryPermissionForExtension(*extension(),
346 selected_add_permission
,
348 EXPECT_EQ(2, dialog()->update_count());
349 EXPECT_EQ(6U, controller()->GetGalleryList().size());
351 // Blacklist scan results.
352 gallery_prefs()->ForgetGalleryById(unselected_removed
);
353 EXPECT_EQ(3, dialog()->update_count());
354 EXPECT_EQ(5U, controller()->GetGalleryList().size());
355 gallery_prefs()->ForgetGalleryById(selected_removed
);
356 EXPECT_EQ(4, dialog()->update_count());
357 EXPECT_EQ(4U, controller()->GetGalleryList().size());
360 const MediaGalleryPrefInfo
& unselected_update_info
=
361 gallery_prefs()->known_galleries().find(unselected_update
)->second
;
362 gallery_prefs()->AddGallery(
363 unselected_update_info
.device_id
, base::FilePath(),
364 MediaGalleryPrefInfo::kScanResult
,
365 base::ASCIIToUTF16("Updated & Unselected"),
366 base::string16(), base::string16(), 0, base::Time(), 0, 0, 0);
367 EXPECT_EQ(5, dialog()->update_count());
368 EXPECT_EQ(4U, controller()->GetGalleryList().size());
369 const MediaGalleryPrefInfo
& selected_update_info
=
370 gallery_prefs()->known_galleries().find(selected_update
)->second
;
371 gallery_prefs()->AddGallery(
372 selected_update_info
.device_id
, base::FilePath(),
373 MediaGalleryPrefInfo::kScanResult
,
374 base::ASCIIToUTF16("Updated & Selected"),
375 base::string16(), base::string16(), 0, base::Time(), 0, 0, 0);
376 EXPECT_EQ(6, dialog()->update_count());
377 ASSERT_EQ(4U, controller()->GetGalleryList().size());
379 MediaGalleriesScanResultDialogController::OrderedScanResults results
=
380 controller()->GetGalleryList();
381 EXPECT_EQ(selected
, results
[0].pref_info
.pref_id
);
382 EXPECT_TRUE(results
[0].selected
);
383 EXPECT_EQ(selected_update
, results
[1].pref_info
.pref_id
);
384 EXPECT_TRUE(results
[1].selected
);
385 EXPECT_EQ(base::ASCIIToUTF16("Updated & Selected"),
386 results
[1].pref_info
.volume_label
);
387 EXPECT_EQ(unselected
, results
[2].pref_info
.pref_id
);
388 EXPECT_FALSE(results
[2].selected
);
389 EXPECT_EQ(unselected_update
, results
[3].pref_info
.pref_id
);
390 EXPECT_FALSE(results
[3].selected
);
391 EXPECT_EQ(base::ASCIIToUTF16("Updated & Unselected"),
392 results
[3].pref_info
.volume_label
);
394 controller()->DialogFinished(true);
395 EXPECT_EQ(4U, gallery_prefs()->GalleriesForExtension(*extension()).size());
397 EXPECT_EQ(2U, controller()->GetGalleryList().size());
398 controller()->DialogFinished(false);
401 TEST_F(MediaGalleriesScanResultDialogControllerTest
, ForgetGallery
) {
402 // Start with two scan results.
403 MediaGalleryPrefId scan1
= AddScanResult("scan1", 1, 0, 0);
404 MediaGalleryPrefId scan2
= AddScanResult("scan2", 2, 0, 0);
405 EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
407 // Remove one and then cancel.
409 EXPECT_EQ(2U, controller()->GetGalleryList().size());
410 controller()->DidForgetGallery(scan1
);
411 controller()->DialogFinished(false);
412 EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
414 // Remove one and then have it blacklisted from prefs.
416 EXPECT_EQ(2U, controller()->GetGalleryList().size());
417 controller()->DidForgetGallery(scan1
);
418 EXPECT_EQ(1, dialog()->update_count());
419 controller()->DidToggleGalleryId(scan2
, false); // Uncheck the second.
420 gallery_prefs()->ForgetGalleryById(scan1
);
421 controller()->DialogFinished(true);
422 EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
423 EXPECT_EQ(2, dialog_update_count_at_destruction());
427 EXPECT_EQ(1U, controller()->GetGalleryList().size());
428 controller()->DidForgetGallery(scan2
);
429 controller()->DialogFinished(true);
430 EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
432 // Check that nothing shows up.
434 EXPECT_EQ(0U, controller()->GetGalleryList().size());
435 controller()->DialogFinished(false);
438 TEST_F(MediaGalleriesScanResultDialogControllerTest
, SortOrder
) {
439 // Intentionally out of order numerically and alphabetically.
440 MediaGalleryPrefId third
= AddScanResult("third", 2, 2, 2);
441 MediaGalleryPrefId second
=
442 AddGallery("second", MediaGalleryPrefInfo::kAutoDetected
, 9, 0, 0);
443 MediaGalleryPrefId first
= AddScanResult("first", 8, 2, 3);
444 MediaGalleryPrefId fifth
= AddScanResult("abb", 3, 0, 0);
445 MediaGalleryPrefId fourth
= AddScanResult("aaa", 3, 0, 0);
448 MediaGalleriesScanResultDialogController::OrderedScanResults results
=
449 controller()->GetGalleryList();
450 ASSERT_EQ(5U, results
.size());
451 EXPECT_EQ(first
, results
[0].pref_info
.pref_id
);
452 EXPECT_EQ(second
, results
[1].pref_info
.pref_id
);
453 EXPECT_EQ(third
, results
[2].pref_info
.pref_id
);
454 EXPECT_EQ(fourth
, results
[3].pref_info
.pref_id
);
455 EXPECT_EQ(fifth
, results
[4].pref_info
.pref_id
);
456 controller()->DialogFinished(false);