Home | History | Annotate | Download | only in media_galleries
      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/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_dialog_controller_test_util.h"
     16 #include "chrome/browser/media_galleries/media_galleries_preferences.h"
     17 #include "chrome/browser/media_galleries/media_galleries_scan_result_controller.h"
     18 #include "chrome/browser/media_galleries/media_galleries_test_util.h"
     19 #include "chrome/test/base/testing_profile.h"
     20 #include "components/storage_monitor/test_storage_monitor.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 "extensions/common/permissions/media_galleries_permission.h"
     25 #include "testing/gtest/include/gtest/gtest.h"
     26 
     27 #if defined(OS_CHROMEOS)
     28 #include "chrome/browser/chromeos/login/users/scoped_test_user_manager.h"
     29 #include "chrome/browser/chromeos/settings/cros_settings.h"
     30 #include "chrome/browser/chromeos/settings/device_settings_service.h"
     31 #endif
     32 
     33 class MediaGalleriesScanResultControllerTest : public testing::Test {
     34  public:
     35   MediaGalleriesScanResultControllerTest()
     36       : dialog_(NULL),
     37         dialog_update_count_at_destruction_(0),
     38         controller_(NULL),
     39         profile_(new TestingProfile()),
     40         weak_factory_(this) {
     41   }
     42 
     43   virtual ~MediaGalleriesScanResultControllerTest() {
     44     EXPECT_FALSE(controller_);
     45     EXPECT_FALSE(dialog_);
     46   }
     47 
     48   virtual void SetUp() OVERRIDE {
     49     ASSERT_TRUE(storage_monitor::TestStorageMonitor::CreateAndInstall());
     50 
     51     extensions::TestExtensionSystem* extension_system(
     52         static_cast<extensions::TestExtensionSystem*>(
     53             extensions::ExtensionSystem::Get(profile_.get())));
     54     extension_system->CreateExtensionService(
     55         CommandLine::ForCurrentProcess(), base::FilePath(), false);
     56 
     57     gallery_prefs_.reset(new MediaGalleriesPreferences(profile_.get()));
     58     base::RunLoop loop;
     59     gallery_prefs_->EnsureInitialized(loop.QuitClosure());
     60     loop.Run();
     61 
     62     std::vector<std::string> read_permissions;
     63     read_permissions.push_back(
     64         extensions::MediaGalleriesPermission::kReadPermission);
     65     extension_ = AddMediaGalleriesApp("read", read_permissions, profile_.get());
     66   }
     67 
     68   virtual void TearDown() OVERRIDE {
     69     storage_monitor::TestStorageMonitor::Destroy();
     70   }
     71 
     72   void StartDialog() {
     73     ASSERT_FALSE(controller_);
     74     controller_ = new MediaGalleriesScanResultController(
     75         *extension_.get(),
     76         gallery_prefs_.get(),
     77         base::Bind(
     78             &MediaGalleriesScanResultControllerTest::CreateMockDialog,
     79             base::Unretained(this)),
     80         base::Bind(
     81             &MediaGalleriesScanResultControllerTest::OnControllerDone,
     82             base::Unretained(this)));
     83   }
     84 
     85   size_t GetFirstSectionSize() const {
     86     return controller()->GetSectionEntries(0).size();
     87   }
     88 
     89   MediaGalleriesScanResultController* controller() const {
     90     return controller_;
     91   }
     92 
     93   MockMediaGalleriesDialog* dialog() {
     94     return dialog_;
     95   }
     96 
     97   int dialog_update_count_at_destruction() {
     98     EXPECT_FALSE(dialog_);
     99     return dialog_update_count_at_destruction_;
    100   }
    101 
    102   extensions::Extension* extension() {
    103     return extension_.get();
    104   }
    105 
    106   MediaGalleriesPreferences* gallery_prefs() {
    107     return gallery_prefs_.get();
    108   }
    109 
    110   MediaGalleryPrefId AddGallery(const std::string& path,
    111                                 MediaGalleryPrefInfo::Type type,
    112                                 int audio_count, int image_count,
    113                                 int video_count) {
    114     MediaGalleryPrefInfo gallery_info;
    115     gallery_prefs_->LookUpGalleryByPath(MakeMediaGalleriesTestingPath(path),
    116                                         &gallery_info);
    117     return gallery_prefs_->AddGallery(
    118         gallery_info.device_id,
    119         gallery_info.path,
    120         type,
    121         gallery_info.volume_label,
    122         gallery_info.vendor_name,
    123         gallery_info.model_name,
    124         gallery_info.total_size_in_bytes,
    125         gallery_info.last_attach_time,
    126         audio_count, image_count, video_count);
    127   }
    128 
    129   MediaGalleryPrefId AddScanResult(const std::string& path, int audio_count,
    130                                    int image_count, int video_count) {
    131     return AddGallery(path, MediaGalleryPrefInfo::kScanResult, audio_count,
    132                       image_count, video_count);
    133   }
    134 
    135  private:
    136   MediaGalleriesDialog* CreateMockDialog(
    137       MediaGalleriesDialogController* controller) {
    138     EXPECT_FALSE(dialog_);
    139     dialog_update_count_at_destruction_ = 0;
    140     dialog_ = new MockMediaGalleriesDialog(base::Bind(
    141         &MediaGalleriesScanResultControllerTest::OnDialogDestroyed,
    142         weak_factory_.GetWeakPtr()));
    143     return dialog_;
    144   }
    145 
    146   void OnDialogDestroyed(int update_count) {
    147     EXPECT_TRUE(dialog_);
    148     dialog_update_count_at_destruction_ = update_count;
    149     dialog_ = NULL;
    150   }
    151 
    152   void OnControllerDone() {
    153     controller_ = NULL;
    154   }
    155 
    156   // Needed for extension service & friends to work.
    157   content::TestBrowserThreadBundle thread_bundle_;
    158 
    159   // The dialog is owned by the controller, but this pointer should only be
    160   // valid while the dialog is live within the controller.
    161   MockMediaGalleriesDialog* dialog_;
    162   int dialog_update_count_at_destruction_;
    163 
    164   // The controller owns itself.
    165   MediaGalleriesScanResultController* controller_;
    166 
    167   scoped_refptr<extensions::Extension> extension_;
    168 
    169   EnsureMediaDirectoriesExists mock_gallery_locations_;
    170 
    171 #if defined OS_CHROMEOS
    172   chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
    173   chromeos::ScopedTestCrosSettings test_cros_settings_;
    174   chromeos::ScopedTestUserManager test_user_manager_;
    175 #endif
    176 
    177   storage_monitor::TestStorageMonitor monitor_;
    178   scoped_ptr<TestingProfile> profile_;
    179   scoped_ptr<MediaGalleriesPreferences> gallery_prefs_;
    180 
    181   base::WeakPtrFactory<MediaGalleriesScanResultControllerTest> weak_factory_;
    182 
    183   DISALLOW_COPY_AND_ASSIGN(MediaGalleriesScanResultControllerTest);
    184 };
    185 
    186 TEST_F(MediaGalleriesScanResultControllerTest, EmptyDialog) {
    187   StartDialog();
    188   EXPECT_TRUE(controller());
    189   EXPECT_TRUE(dialog());
    190   EXPECT_EQ(0U, GetFirstSectionSize());
    191 
    192   controller()->DialogFinished(true);
    193   EXPECT_FALSE(controller());
    194   EXPECT_FALSE(dialog());
    195   EXPECT_EQ(0, dialog_update_count_at_destruction());
    196 }
    197 
    198 TEST_F(MediaGalleriesScanResultControllerTest, AddScanResults) {
    199   // Start with two scan results.
    200   MediaGalleryPrefId scan_id = AddScanResult("scan_id", 1, 0, 0);
    201   MediaGalleryPrefId auto_id =
    202       AddGallery("auto_id", MediaGalleryPrefInfo::kAutoDetected, 2, 0, 0);
    203   EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
    204 
    205   // Show the dialog, but cancel it.
    206   StartDialog();
    207   EXPECT_EQ(2U, GetFirstSectionSize());
    208   controller()->DialogFinished(false);
    209   EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
    210 
    211   // Show the dialog, unselect both and accept it.
    212   StartDialog();
    213   EXPECT_EQ(2U, GetFirstSectionSize());
    214   controller()->DidToggleEntry(scan_id, false);
    215   controller()->DidToggleEntry(auto_id, false);
    216   controller()->DialogFinished(true);
    217   EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
    218 
    219   // Show the dialog, leave one selected and accept it.
    220   StartDialog();
    221   EXPECT_EQ(2U, GetFirstSectionSize());
    222   controller()->DidToggleEntry(scan_id, false);
    223   controller()->DialogFinished(true);
    224   MediaGalleryPrefIdSet permitted =
    225       gallery_prefs()->GalleriesForExtension(*extension());
    226   ASSERT_EQ(1U, permitted.size());
    227   EXPECT_EQ(auto_id, *permitted.begin());
    228 
    229   // Show the dialog, toggle the remaining entry twice and then accept it.
    230   StartDialog();
    231   EXPECT_EQ(1U, GetFirstSectionSize());
    232   controller()->DidToggleEntry(scan_id, false);
    233   controller()->DidToggleEntry(scan_id, true);
    234   controller()->DialogFinished(true);
    235   EXPECT_EQ(2U, gallery_prefs()->GalleriesForExtension(*extension()).size());
    236 }
    237 
    238 TEST_F(MediaGalleriesScanResultControllerTest, Blacklisted) {
    239   // Start with two scan results.
    240   MediaGalleryPrefId scan_id = AddScanResult("scan_id", 1, 0, 0);
    241   MediaGalleryPrefId auto_id =
    242       AddGallery("auto_id", MediaGalleryPrefInfo::kAutoDetected, 2, 0, 0);
    243   EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
    244 
    245   // Show the dialog, but cancel it.
    246   StartDialog();
    247   EXPECT_EQ(2U, GetFirstSectionSize());
    248   controller()->DialogFinished(false);
    249   EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
    250 
    251   // Blacklist one and try again.
    252   gallery_prefs()->ForgetGalleryById(scan_id);
    253   StartDialog();
    254   EXPECT_EQ(1U, GetFirstSectionSize());
    255   controller()->DialogFinished(false);
    256 
    257   // Adding it as a user gallery should change its type.
    258   AddGallery("scan_id", MediaGalleryPrefInfo::kUserAdded, 1, 0, 0);
    259   StartDialog();
    260   EXPECT_EQ(2U, GetFirstSectionSize());
    261 
    262   // Blacklisting the other while the dialog is open should remove it.
    263   gallery_prefs()->ForgetGalleryById(auto_id);
    264   EXPECT_EQ(1U, GetFirstSectionSize());
    265   controller()->DialogFinished(false);
    266   EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
    267   EXPECT_EQ(1, dialog_update_count_at_destruction());
    268 }
    269 
    270 TEST_F(MediaGalleriesScanResultControllerTest, PrefUpdates) {
    271   MediaGalleryPrefId selected = AddScanResult("selected", 1, 0, 0);
    272   MediaGalleryPrefId unselected = AddScanResult("unselected", 1, 0, 0);
    273   MediaGalleryPrefId selected_add_permission =
    274       AddScanResult("selected_add_permission", 1, 0, 0);
    275   MediaGalleryPrefId unselected_add_permission =
    276       AddScanResult("unselected_add_permission", 1, 0, 0);
    277   MediaGalleryPrefId selected_removed =
    278       AddScanResult("selected_removed", 1, 0, 0);
    279   MediaGalleryPrefId unselected_removed =
    280       AddScanResult("unselected_removed", 1, 0, 0);
    281   MediaGalleryPrefId selected_update =
    282       AddScanResult("selected_update", 1, 0, 0);
    283   MediaGalleryPrefId unselected_update =
    284       AddScanResult("unselected_update", 1, 0, 0);
    285 
    286   gallery_prefs()->AddGalleryByPath(MakeMediaGalleriesTestingPath("user"),
    287                                     MediaGalleryPrefInfo::kUserAdded);
    288   gallery_prefs()->AddGalleryByPath(
    289       MakeMediaGalleriesTestingPath("auto_detected"),
    290       MediaGalleryPrefInfo::kAutoDetected);
    291   MediaGalleryPrefId blacklisted = gallery_prefs()->AddGalleryByPath(
    292       MakeMediaGalleriesTestingPath("blacklisted"),
    293       MediaGalleryPrefInfo::kAutoDetected);
    294   gallery_prefs()->ForgetGalleryById(blacklisted);
    295   EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
    296 
    297   StartDialog();
    298   EXPECT_EQ(8U, GetFirstSectionSize());
    299   controller()->DidToggleEntry(unselected, false);
    300   controller()->DidToggleEntry(unselected_add_permission, false);
    301   controller()->DidToggleEntry(unselected_removed, false);
    302   controller()->DidToggleEntry(unselected_update, false);
    303   EXPECT_EQ(0, dialog()->update_count());
    304   EXPECT_EQ(8U, GetFirstSectionSize());
    305 
    306   // Add permission.
    307   gallery_prefs()->SetGalleryPermissionForExtension(*extension(),
    308                                                     unselected_add_permission,
    309                                                     true);
    310   EXPECT_EQ(1, dialog()->update_count());
    311   EXPECT_EQ(7U, GetFirstSectionSize());
    312   gallery_prefs()->SetGalleryPermissionForExtension(*extension(),
    313                                                     selected_add_permission,
    314                                                     true);
    315   EXPECT_EQ(2, dialog()->update_count());
    316   EXPECT_EQ(6U, GetFirstSectionSize());
    317 
    318   // Blacklist scan results.
    319   gallery_prefs()->ForgetGalleryById(unselected_removed);
    320   EXPECT_EQ(3, dialog()->update_count());
    321   EXPECT_EQ(5U, GetFirstSectionSize());
    322   gallery_prefs()->ForgetGalleryById(selected_removed);
    323   EXPECT_EQ(4, dialog()->update_count());
    324   EXPECT_EQ(4U, GetFirstSectionSize());
    325 
    326   // Update names.
    327   const MediaGalleryPrefInfo& unselected_update_info =
    328       gallery_prefs()->known_galleries().find(unselected_update)->second;
    329   gallery_prefs()->AddGallery(
    330       unselected_update_info.device_id, base::FilePath(),
    331       MediaGalleryPrefInfo::kScanResult,
    332       base::ASCIIToUTF16("Updated & Unselected"),
    333       base::string16(), base::string16(), 0, base::Time(), 1, 0, 0);
    334   EXPECT_EQ(5, dialog()->update_count());
    335   EXPECT_EQ(4U, GetFirstSectionSize());
    336   const MediaGalleryPrefInfo& selected_update_info =
    337       gallery_prefs()->known_galleries().find(selected_update)->second;
    338   gallery_prefs()->AddGallery(
    339       selected_update_info.device_id, base::FilePath(),
    340       MediaGalleryPrefInfo::kScanResult,
    341       base::ASCIIToUTF16("Updated & Selected"),
    342       base::string16(), base::string16(), 0, base::Time(), 1, 0, 0);
    343   EXPECT_EQ(6, dialog()->update_count());
    344   EXPECT_EQ(4U, GetFirstSectionSize());
    345 
    346   MediaGalleriesDialogController::Entries results =
    347       controller()->GetSectionEntries(0);
    348   EXPECT_EQ(selected, results[0].pref_info.pref_id);
    349   EXPECT_TRUE(results[0].selected);
    350   EXPECT_EQ(selected_update, results[1].pref_info.pref_id);
    351   EXPECT_TRUE(results[1].selected);
    352   EXPECT_EQ(base::ASCIIToUTF16("Updated & Selected"),
    353             results[1].pref_info.volume_label);
    354   EXPECT_EQ(unselected, results[2].pref_info.pref_id);
    355   EXPECT_FALSE(results[2].selected);
    356   EXPECT_EQ(unselected_update, results[3].pref_info.pref_id);
    357   EXPECT_FALSE(results[3].selected);
    358   EXPECT_EQ(base::ASCIIToUTF16("Updated & Unselected"),
    359             results[3].pref_info.volume_label);
    360 
    361   controller()->DialogFinished(true);
    362   EXPECT_EQ(4U, gallery_prefs()->GalleriesForExtension(*extension()).size());
    363   StartDialog();
    364   EXPECT_EQ(2U, GetFirstSectionSize());
    365   controller()->DialogFinished(false);
    366 }
    367 
    368 TEST_F(MediaGalleriesScanResultControllerTest, ForgetGallery) {
    369   // Start with two scan results.
    370   MediaGalleryPrefId scan1 = AddScanResult("scan1", 1, 0, 0);
    371   MediaGalleryPrefId scan2 = AddScanResult("scan2", 2, 0, 0);
    372   EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
    373 
    374   // Remove one and then cancel.
    375   StartDialog();
    376   EXPECT_EQ(2U, GetFirstSectionSize());
    377   controller()->DidForgetEntry(scan1);
    378   controller()->DialogFinished(false);
    379   EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
    380 
    381   // Remove one and then have it blacklisted from prefs.
    382   StartDialog();
    383   EXPECT_EQ(2U, GetFirstSectionSize());
    384   controller()->DidForgetEntry(scan1);
    385   EXPECT_EQ(1, dialog()->update_count());
    386   controller()->DidToggleEntry(scan2, false);  // Uncheck the second.
    387   gallery_prefs()->ForgetGalleryById(scan1);
    388   controller()->DialogFinished(true);
    389   EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
    390   EXPECT_EQ(2, dialog_update_count_at_destruction());
    391 
    392   // Remove the other.
    393   StartDialog();
    394   EXPECT_EQ(1U, GetFirstSectionSize());
    395   controller()->DidForgetEntry(scan2);
    396   controller()->DialogFinished(true);
    397   EXPECT_EQ(0U, gallery_prefs()->GalleriesForExtension(*extension()).size());
    398 
    399   // Check that nothing shows up.
    400   StartDialog();
    401   EXPECT_EQ(0U, GetFirstSectionSize());
    402   controller()->DialogFinished(false);
    403 }
    404 
    405 TEST_F(MediaGalleriesScanResultControllerTest, SortOrder) {
    406   // Intentionally out of order numerically and alphabetically.
    407   MediaGalleryPrefId third = AddScanResult("third", 2, 2, 2);
    408   MediaGalleryPrefId second =
    409       AddGallery("second", MediaGalleryPrefInfo::kAutoDetected, 9, 0, 0);
    410   MediaGalleryPrefId first = AddScanResult("first", 8, 2, 3);
    411   MediaGalleryPrefId fifth = AddScanResult("abb", 3, 0, 0);
    412   MediaGalleryPrefId fourth = AddScanResult("aaa", 3, 0, 0);
    413 
    414   StartDialog();
    415   MediaGalleriesDialogController::Entries results =
    416       controller()->GetSectionEntries(0);
    417   ASSERT_EQ(5U, results.size());
    418   EXPECT_EQ(first, results[0].pref_info.pref_id);
    419   EXPECT_EQ(second, results[1].pref_info.pref_id);
    420   EXPECT_EQ(third, results[2].pref_info.pref_id);
    421   EXPECT_EQ(fourth, results[3].pref_info.pref_id);
    422   EXPECT_EQ(fifth, results[4].pref_info.pref_id);
    423   controller()->DialogFinished(false);
    424 }
    425