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/test/base/testing_profile.h"
19 #include "components/storage_monitor/test_storage_monitor.h"
20 #include "content/public/test/test_browser_thread_bundle.h"
21 #include "extensions/browser/extension_system.h"
22 #include "extensions/common/extension.h"
23 #include "extensions/common/permissions/media_galleries_permission.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 // MediaGalleriesScanResultDialog implementation.
50 virtual void UpdateResults() OVERRIDE
{
54 // Number up times UpdateResults has been called.
60 // MediaGalleriesScanResultDialog implementation.
61 virtual void AcceptDialogForTesting() OVERRIDE
{
66 DialogDestroyedCallback dialog_destroyed_callback_
;
68 DISALLOW_COPY_AND_ASSIGN(MockMediaGalleriesScanResultDialog
);
73 class MediaGalleriesScanResultDialogControllerTest
: public testing::Test
{
75 MediaGalleriesScanResultDialogControllerTest()
77 dialog_update_count_at_destruction_(0),
79 profile_(new TestingProfile()),
83 virtual ~MediaGalleriesScanResultDialogControllerTest() {
84 EXPECT_FALSE(controller_
);
85 EXPECT_FALSE(dialog_
);
88 virtual void SetUp() OVERRIDE
{
89 ASSERT_TRUE(storage_monitor::TestStorageMonitor::CreateAndInstall());
91 extensions::TestExtensionSystem
* extension_system(
92 static_cast<extensions::TestExtensionSystem
*>(
93 extensions::ExtensionSystem::Get(profile_
.get())));
94 extension_system
->CreateExtensionService(
95 CommandLine::ForCurrentProcess(), base::FilePath(), false);
97 gallery_prefs_
.reset(new MediaGalleriesPreferences(profile_
.get()));
99 gallery_prefs_
->EnsureInitialized(loop
.QuitClosure());
102 std::vector
<std::string
> read_permissions
;
103 read_permissions
.push_back(
104 extensions::MediaGalleriesPermission::kReadPermission
);
105 extension_
= AddMediaGalleriesApp("read", read_permissions
, profile_
.get());
108 virtual void TearDown() OVERRIDE
{
109 storage_monitor::TestStorageMonitor::Destroy();
113 ASSERT_FALSE(controller_
);
114 controller_
= new MediaGalleriesScanResultDialogController(
116 gallery_prefs_
.get(),
118 &MediaGalleriesScanResultDialogControllerTest::CreateMockDialog
,
119 base::Unretained(this)),
121 &MediaGalleriesScanResultDialogControllerTest::OnControllerDone
,
122 base::Unretained(this)));
125 MediaGalleriesScanResultDialogController
* controller() {
129 MockMediaGalleriesScanResultDialog
* dialog() {
133 int dialog_update_count_at_destruction() {
134 EXPECT_FALSE(dialog_
);
135 return dialog_update_count_at_destruction_
;
138 extensions::Extension
* extension() {
139 return extension_
.get();
142 MediaGalleriesPreferences
* gallery_prefs() {
143 return gallery_prefs_
.get();
146 MediaGalleryPrefId
AddGallery(const std::string
& path
,
147 MediaGalleryPrefInfo::Type type
,
148 int audio_count
, int image_count
,
150 MediaGalleryPrefInfo gallery_info
;
151 gallery_prefs_
->LookUpGalleryByPath(MakeMediaGalleriesTestingPath(path
),
153 return gallery_prefs_
->AddGallery(
154 gallery_info
.device_id
,
157 gallery_info
.volume_label
,
158 gallery_info
.vendor_name
,
159 gallery_info
.model_name
,
160 gallery_info
.total_size_in_bytes
,
161 gallery_info
.last_attach_time
,
162 audio_count
, image_count
, video_count
);
165 MediaGalleryPrefId
AddScanResult(const std::string
& path
, int audio_count
,
166 int image_count
, int video_count
) {
167 return AddGallery(path
, MediaGalleryPrefInfo::kScanResult
, audio_count
,
168 image_count
, video_count
);
172 MediaGalleriesScanResultDialog
* CreateMockDialog(
173 MediaGalleriesScanResultDialogController
* controller
) {
174 EXPECT_FALSE(dialog_
);
175 dialog_update_count_at_destruction_
= 0;
176 dialog_
= new MockMediaGalleriesScanResultDialog(base::Bind(
177 &MediaGalleriesScanResultDialogControllerTest::OnDialogDestroyed
,
178 weak_factory_
.GetWeakPtr()));
182 void OnDialogDestroyed(int update_count
) {
183 EXPECT_TRUE(dialog_
);
184 dialog_update_count_at_destruction_
= update_count
;
188 void OnControllerDone() {
192 // Needed for extension service & friends to work.
193 content::TestBrowserThreadBundle thread_bundle_
;
195 // The dialog is owned by the controller, but this pointer should only be
196 // valid while the dialog is live within the controller.
197 MockMediaGalleriesScanResultDialog
* dialog_
;
198 int dialog_update_count_at_destruction_
;
200 // The controller owns itself.
201 MediaGalleriesScanResultDialogController
* controller_
;
203 scoped_refptr
<extensions::Extension
> extension_
;
205 EnsureMediaDirectoriesExists mock_gallery_locations_
;
207 #if defined OS_CHROMEOS
208 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_
;
209 chromeos::ScopedTestCrosSettings test_cros_settings_
;
210 chromeos::ScopedTestUserManager test_user_manager_
;
213 storage_monitor::TestStorageMonitor monitor_
;
214 scoped_ptr
<TestingProfile
> profile_
;
215 scoped_ptr
<MediaGalleriesPreferences
> gallery_prefs_
;
217 base::WeakPtrFactory
<MediaGalleriesScanResultDialogControllerTest
>
220 DISALLOW_COPY_AND_ASSIGN(MediaGalleriesScanResultDialogControllerTest
);
223 TEST_F(MediaGalleriesScanResultDialogControllerTest
, EmptyDialog
) {
225 EXPECT_TRUE(controller());
226 EXPECT_TRUE(dialog());
227 EXPECT_EQ(0U, controller()->GetGalleryList().size());
229 controller()->DialogFinished(true);
230 EXPECT_FALSE(controller());
231 EXPECT_FALSE(dialog());
232 EXPECT_EQ(0, dialog_update_count_at_destruction());
235 TEST_F(MediaGalleriesScanResultDialogControllerTest
, AddScanResults
) {
236 // Start with two scan results.
237 MediaGalleryPrefId scan_id
= AddScanResult("scan_id", 1, 0, 0);
238 MediaGalleryPrefId auto_id
=
239 AddGallery("auto_id", MediaGalleryPrefInfo::kAutoDetected
, 2, 0, 0);
240 EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
242 // Show the dialog, but cancel it.
244 EXPECT_EQ(2U, controller()->GetGalleryList().size());
245 controller()->DialogFinished(false);
246 EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
248 // Show the dialog, unselect both and accept it.
250 EXPECT_EQ(2U, controller()->GetGalleryList().size());
251 controller()->DidToggleGalleryId(scan_id
, false);
252 controller()->DidToggleGalleryId(auto_id
, false);
253 controller()->DialogFinished(true);
254 EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
256 // Show the dialog, leave one selected and accept it.
258 EXPECT_EQ(2U, controller()->GetGalleryList().size());
259 controller()->DidToggleGalleryId(scan_id
, false);
260 controller()->DialogFinished(true);
261 MediaGalleryPrefIdSet permitted
=
262 gallery_prefs()->GalleriesForExtension(*extension());
263 ASSERT_EQ(1U, permitted
.size());
264 EXPECT_EQ(auto_id
, *permitted
.begin());
266 // Show the dialog, toggle the remaining entry twice and then accept it.
268 EXPECT_EQ(1U, controller()->GetGalleryList().size());
269 controller()->DidToggleGalleryId(scan_id
, false);
270 controller()->DidToggleGalleryId(scan_id
, true);
271 controller()->DialogFinished(true);
272 EXPECT_EQ(2U, gallery_prefs()->GalleriesForExtension(*extension()).size());
275 TEST_F(MediaGalleriesScanResultDialogControllerTest
, Blacklisted
) {
276 // Start with two scan results.
277 MediaGalleryPrefId scan_id
= AddScanResult("scan_id", 1, 0, 0);
278 MediaGalleryPrefId auto_id
=
279 AddGallery("auto_id", MediaGalleryPrefInfo::kAutoDetected
, 2, 0, 0);
280 EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
282 // Show the dialog, but cancel it.
284 EXPECT_EQ(2U, controller()->GetGalleryList().size());
285 controller()->DialogFinished(false);
286 EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
288 // Blacklist one and try again.
289 gallery_prefs()->ForgetGalleryById(scan_id
);
291 EXPECT_EQ(1U, controller()->GetGalleryList().size());
292 controller()->DialogFinished(false);
294 // Adding it as a user gallery should change its type.
295 AddGallery("scan_id", MediaGalleryPrefInfo::kUserAdded
, 1, 0, 0);
297 EXPECT_EQ(2U, controller()->GetGalleryList().size());
299 // Blacklisting the other while the dialog is open should remove it.
300 gallery_prefs()->ForgetGalleryById(auto_id
);
301 EXPECT_EQ(1U, controller()->GetGalleryList().size());
302 controller()->DialogFinished(false);
303 EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
304 EXPECT_EQ(1, dialog_update_count_at_destruction());
307 TEST_F(MediaGalleriesScanResultDialogControllerTest
, PrefUpdates
) {
308 MediaGalleryPrefId selected
= AddScanResult("selected", 1, 0, 0);
309 MediaGalleryPrefId unselected
= AddScanResult("unselected", 1, 0, 0);
310 MediaGalleryPrefId selected_add_permission
=
311 AddScanResult("selected_add_permission", 1, 0, 0);
312 MediaGalleryPrefId unselected_add_permission
=
313 AddScanResult("unselected_add_permission", 1, 0, 0);
314 MediaGalleryPrefId selected_removed
=
315 AddScanResult("selected_removed", 1, 0, 0);
316 MediaGalleryPrefId unselected_removed
=
317 AddScanResult("unselected_removed", 1, 0, 0);
318 MediaGalleryPrefId selected_update
=
319 AddScanResult("selected_update", 1, 0, 0);
320 MediaGalleryPrefId unselected_update
=
321 AddScanResult("unselected_update", 1, 0, 0);
323 gallery_prefs()->AddGalleryByPath(MakeMediaGalleriesTestingPath("user"),
324 MediaGalleryPrefInfo::kUserAdded
);
325 gallery_prefs()->AddGalleryByPath(
326 MakeMediaGalleriesTestingPath("auto_detected"),
327 MediaGalleryPrefInfo::kAutoDetected
);
328 MediaGalleryPrefId blacklisted
= gallery_prefs()->AddGalleryByPath(
329 MakeMediaGalleriesTestingPath("blacklisted"),
330 MediaGalleryPrefInfo::kAutoDetected
);
331 gallery_prefs()->ForgetGalleryById(blacklisted
);
332 EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
335 EXPECT_EQ(8U, controller()->GetGalleryList().size());
336 controller()->DidToggleGalleryId(unselected
, false);
337 controller()->DidToggleGalleryId(unselected_add_permission
, false);
338 controller()->DidToggleGalleryId(unselected_removed
, false);
339 controller()->DidToggleGalleryId(unselected_update
, false);
340 EXPECT_EQ(0, dialog()->update_count());
341 EXPECT_EQ(8U, controller()->GetGalleryList().size());
344 gallery_prefs()->SetGalleryPermissionForExtension(*extension(),
345 unselected_add_permission
,
347 EXPECT_EQ(1, dialog()->update_count());
348 EXPECT_EQ(7U, controller()->GetGalleryList().size());
349 gallery_prefs()->SetGalleryPermissionForExtension(*extension(),
350 selected_add_permission
,
352 EXPECT_EQ(2, dialog()->update_count());
353 EXPECT_EQ(6U, controller()->GetGalleryList().size());
355 // Blacklist scan results.
356 gallery_prefs()->ForgetGalleryById(unselected_removed
);
357 EXPECT_EQ(3, dialog()->update_count());
358 EXPECT_EQ(5U, controller()->GetGalleryList().size());
359 gallery_prefs()->ForgetGalleryById(selected_removed
);
360 EXPECT_EQ(4, dialog()->update_count());
361 EXPECT_EQ(4U, controller()->GetGalleryList().size());
364 const MediaGalleryPrefInfo
& unselected_update_info
=
365 gallery_prefs()->known_galleries().find(unselected_update
)->second
;
366 gallery_prefs()->AddGallery(
367 unselected_update_info
.device_id
, base::FilePath(),
368 MediaGalleryPrefInfo::kScanResult
,
369 base::ASCIIToUTF16("Updated & Unselected"),
370 base::string16(), base::string16(), 0, base::Time(), 1, 0, 0);
371 EXPECT_EQ(5, dialog()->update_count());
372 EXPECT_EQ(4U, controller()->GetGalleryList().size());
373 const MediaGalleryPrefInfo
& selected_update_info
=
374 gallery_prefs()->known_galleries().find(selected_update
)->second
;
375 gallery_prefs()->AddGallery(
376 selected_update_info
.device_id
, base::FilePath(),
377 MediaGalleryPrefInfo::kScanResult
,
378 base::ASCIIToUTF16("Updated & Selected"),
379 base::string16(), base::string16(), 0, base::Time(), 1, 0, 0);
380 EXPECT_EQ(6, dialog()->update_count());
381 ASSERT_EQ(4U, controller()->GetGalleryList().size());
383 MediaGalleriesScanResultDialogController::OrderedScanResults results
=
384 controller()->GetGalleryList();
385 EXPECT_EQ(selected
, results
[0].pref_info
.pref_id
);
386 EXPECT_TRUE(results
[0].selected
);
387 EXPECT_EQ(selected_update
, results
[1].pref_info
.pref_id
);
388 EXPECT_TRUE(results
[1].selected
);
389 EXPECT_EQ(base::ASCIIToUTF16("Updated & Selected"),
390 results
[1].pref_info
.volume_label
);
391 EXPECT_EQ(unselected
, results
[2].pref_info
.pref_id
);
392 EXPECT_FALSE(results
[2].selected
);
393 EXPECT_EQ(unselected_update
, results
[3].pref_info
.pref_id
);
394 EXPECT_FALSE(results
[3].selected
);
395 EXPECT_EQ(base::ASCIIToUTF16("Updated & Unselected"),
396 results
[3].pref_info
.volume_label
);
398 controller()->DialogFinished(true);
399 EXPECT_EQ(4U, gallery_prefs()->GalleriesForExtension(*extension()).size());
401 EXPECT_EQ(2U, controller()->GetGalleryList().size());
402 controller()->DialogFinished(false);
405 TEST_F(MediaGalleriesScanResultDialogControllerTest
, ForgetGallery
) {
406 // Start with two scan results.
407 MediaGalleryPrefId scan1
= AddScanResult("scan1", 1, 0, 0);
408 MediaGalleryPrefId scan2
= AddScanResult("scan2", 2, 0, 0);
409 EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
411 // Remove one and then cancel.
413 EXPECT_EQ(2U, controller()->GetGalleryList().size());
414 controller()->DidForgetGallery(scan1
);
415 controller()->DialogFinished(false);
416 EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
418 // Remove one and then have it blacklisted from prefs.
420 EXPECT_EQ(2U, controller()->GetGalleryList().size());
421 controller()->DidForgetGallery(scan1
);
422 EXPECT_EQ(1, dialog()->update_count());
423 controller()->DidToggleGalleryId(scan2
, false); // Uncheck the second.
424 gallery_prefs()->ForgetGalleryById(scan1
);
425 controller()->DialogFinished(true);
426 EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
427 EXPECT_EQ(2, dialog_update_count_at_destruction());
431 EXPECT_EQ(1U, controller()->GetGalleryList().size());
432 controller()->DidForgetGallery(scan2
);
433 controller()->DialogFinished(true);
434 EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
436 // Check that nothing shows up.
438 EXPECT_EQ(0U, controller()->GetGalleryList().size());
439 controller()->DialogFinished(false);
442 TEST_F(MediaGalleriesScanResultDialogControllerTest
, SortOrder
) {
443 // Intentionally out of order numerically and alphabetically.
444 MediaGalleryPrefId third
= AddScanResult("third", 2, 2, 2);
445 MediaGalleryPrefId second
=
446 AddGallery("second", MediaGalleryPrefInfo::kAutoDetected
, 9, 0, 0);
447 MediaGalleryPrefId first
= AddScanResult("first", 8, 2, 3);
448 MediaGalleryPrefId fifth
= AddScanResult("abb", 3, 0, 0);
449 MediaGalleryPrefId fourth
= AddScanResult("aaa", 3, 0, 0);
452 MediaGalleriesScanResultDialogController::OrderedScanResults results
=
453 controller()->GetGalleryList();
454 ASSERT_EQ(5U, results
.size());
455 EXPECT_EQ(first
, results
[0].pref_info
.pref_id
);
456 EXPECT_EQ(second
, results
[1].pref_info
.pref_id
);
457 EXPECT_EQ(third
, results
[2].pref_info
.pref_id
);
458 EXPECT_EQ(fourth
, results
[3].pref_info
.pref_id
);
459 EXPECT_EQ(fifth
, results
[4].pref_info
.pref_id
);
460 controller()->DialogFinished(false);