Home | History | Annotate | Download | only in drive
      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 "chrome/browser/drive/drive_app_registry.h"
      6 
      7 #include "base/files/file_path.h"
      8 #include "base/macros.h"
      9 #include "base/run_loop.h"
     10 #include "base/values.h"
     11 #include "chrome/browser/drive/drive_app_registry_observer.h"
     12 #include "chrome/browser/drive/fake_drive_service.h"
     13 #include "content/public/test/test_browser_thread_bundle.h"
     14 #include "google_apis/drive/drive_api_parser.h"
     15 #include "google_apis/drive/gdata_wapi_parser.h"
     16 #include "google_apis/drive/test_util.h"
     17 #include "testing/gtest/include/gtest/gtest.h"
     18 
     19 namespace drive {
     20 
     21 class TestDriveAppRegistryObserver : public DriveAppRegistryObserver {
     22  public:
     23   explicit TestDriveAppRegistryObserver(DriveAppRegistry* registry)
     24       : registry_(registry),
     25         update_count_(0) {
     26     registry_->AddObserver(this);
     27   }
     28   virtual ~TestDriveAppRegistryObserver() {
     29     registry_->RemoveObserver(this);
     30   }
     31 
     32   int update_count() const { return update_count_; }
     33 
     34  private:
     35   // DriveAppRegistryObserver overrides:
     36   virtual void OnDriveAppRegistryUpdated() OVERRIDE { ++update_count_; }
     37 
     38   DriveAppRegistry* registry_;
     39   int update_count_;
     40   DISALLOW_COPY_AND_ASSIGN(TestDriveAppRegistryObserver);
     41 };
     42 
     43 class DriveAppRegistryTest : public testing::Test {
     44  protected:
     45   virtual void SetUp() OVERRIDE {
     46     fake_drive_service_.reset(new FakeDriveService);
     47     fake_drive_service_->LoadAppListForDriveApi("drive/applist.json");
     48 
     49     apps_registry_.reset(new DriveAppRegistry(fake_drive_service_.get()));
     50   }
     51 
     52   bool VerifyApp(const std::vector<DriveAppInfo>& list,
     53                  const std::string& app_id,
     54                  const std::string& app_name) {
     55     bool found = false;
     56     for (size_t i = 0; i < list.size(); ++i) {
     57       const DriveAppInfo& app = list[i];
     58       if (app_id == app.app_id) {
     59         EXPECT_EQ(app_name, app.app_name);
     60         found = true;
     61         break;
     62       }
     63     }
     64     EXPECT_TRUE(found) << "Unable to find app with app_id " << app_id;
     65     return found;
     66   }
     67 
     68   content::TestBrowserThreadBundle thread_bundle_;
     69   scoped_ptr<FakeDriveService> fake_drive_service_;
     70   scoped_ptr<DriveAppRegistry> apps_registry_;
     71 };
     72 
     73 TEST_F(DriveAppRegistryTest, BasicParse) {
     74   TestDriveAppRegistryObserver observer(apps_registry_.get());
     75 
     76   apps_registry_->Update();
     77   base::RunLoop().RunUntilIdle();
     78   EXPECT_EQ(1, observer.update_count());
     79 
     80   std::vector<DriveAppInfo> apps;
     81   apps_registry_->GetAppList(&apps);
     82 
     83   ASSERT_EQ(2u, apps.size());
     84   EXPECT_EQ("123456788192", apps[0].app_id);
     85   EXPECT_EQ("Drive app 1", apps[0].app_name);
     86   EXPECT_EQ("https://www.example.com/createForApp1",
     87             apps[0].create_url.spec());
     88   EXPECT_EQ("abcdefghabcdefghabcdefghabcdefgh", apps[0].product_id);
     89   EXPECT_TRUE(apps[0].is_removable);
     90 }
     91 
     92 TEST_F(DriveAppRegistryTest, LoadAndFindDriveApps) {
     93   TestDriveAppRegistryObserver observer(apps_registry_.get());
     94 
     95   apps_registry_->Update();
     96   base::RunLoop().RunUntilIdle();
     97   EXPECT_EQ(1, observer.update_count());
     98 
     99   // Find by primary extension 'exe'.
    100   std::vector<DriveAppInfo> ext_results;
    101   base::FilePath ext_file(FILE_PATH_LITERAL("drive/file.exe"));
    102   apps_registry_->GetAppsForFile(ext_file.Extension(), "", &ext_results);
    103   ASSERT_EQ(1U, ext_results.size());
    104   VerifyApp(ext_results, "123456788192", "Drive app 1");
    105 
    106   // Find by primary MIME type.
    107   std::vector<DriveAppInfo> primary_app;
    108   apps_registry_->GetAppsForFile(base::FilePath::StringType(),
    109       "application/vnd.google-apps.drive-sdk.123456788192", &primary_app);
    110   ASSERT_EQ(1U, primary_app.size());
    111   VerifyApp(primary_app, "123456788192", "Drive app 1");
    112 
    113   // Find by secondary MIME type.
    114   std::vector<DriveAppInfo> secondary_app;
    115   apps_registry_->GetAppsForFile(
    116       base::FilePath::StringType(), "text/html", &secondary_app);
    117   ASSERT_EQ(1U, secondary_app.size());
    118   VerifyApp(secondary_app, "123456788192", "Drive app 1");
    119 }
    120 
    121 TEST_F(DriveAppRegistryTest, UpdateFromAppList) {
    122   scoped_ptr<base::Value> app_info_value =
    123       google_apis::test_util::LoadJSONFile("drive/applist.json");
    124   scoped_ptr<google_apis::AppList> app_list(
    125       google_apis::AppList::CreateFrom(*app_info_value));
    126 
    127   TestDriveAppRegistryObserver observer(apps_registry_.get());
    128   apps_registry_->UpdateFromAppList(*app_list);
    129   EXPECT_EQ(1, observer.update_count());
    130 
    131   // Confirm that something was loaded from applist.json.
    132   std::vector<DriveAppInfo> ext_results;
    133   base::FilePath ext_file(FILE_PATH_LITERAL("drive/file.exe"));
    134   apps_registry_->GetAppsForFile(ext_file.Extension(), "", &ext_results);
    135   ASSERT_EQ(1U, ext_results.size());
    136 }
    137 
    138 TEST_F(DriveAppRegistryTest, MultipleUpdate) {
    139   TestDriveAppRegistryObserver observer(apps_registry_.get());
    140 
    141   // Call Update().
    142   apps_registry_->Update();
    143   EXPECT_EQ(0, observer.update_count());
    144 
    145   // Call Update() again.
    146   // This call should be ignored because there is already an ongoing update.
    147   apps_registry_->Update();
    148   EXPECT_EQ(0, observer.update_count());
    149 
    150   // The app list should be loaded only once.
    151   base::RunLoop().RunUntilIdle();
    152   EXPECT_EQ(1, fake_drive_service_->app_list_load_count());
    153   EXPECT_EQ(1, observer.update_count());
    154 }
    155 
    156 TEST(DriveAppRegistryUtilTest, FindPreferredIcon_Empty) {
    157   DriveAppInfo::IconList icons;
    158   EXPECT_EQ("",
    159             util::FindPreferredIcon(icons, util::kPreferredIconSize).spec());
    160 }
    161 
    162 TEST(DriveAppRegistryUtilTest, FindPreferredIcon_) {
    163   const char kSmallerIconUrl[] = "http://example.com/smaller.png";
    164   const char kMediumIconUrl[] = "http://example.com/medium.png";
    165   const char kBiggerIconUrl[] = "http://example.com/bigger.png";
    166   const int kMediumSize = 16;
    167 
    168   DriveAppInfo::IconList icons;
    169   // The icons are not sorted by the size.
    170   icons.push_back(std::make_pair(kMediumSize,
    171                                  GURL(kMediumIconUrl)));
    172   icons.push_back(std::make_pair(kMediumSize + 2,
    173                                  GURL(kBiggerIconUrl)));
    174   icons.push_back(std::make_pair(kMediumSize - 2,
    175                                  GURL(kSmallerIconUrl)));
    176 
    177   // Exact match.
    178   EXPECT_EQ(kMediumIconUrl,
    179             util::FindPreferredIcon(icons, kMediumSize).spec());
    180   // The requested size is in-between of smaller.png and
    181   // medium.png. medium.png should be returned.
    182   EXPECT_EQ(kMediumIconUrl,
    183             util::FindPreferredIcon(icons, kMediumSize - 1).spec());
    184   // The requested size is smaller than the smallest icon. The smallest icon
    185   // should be returned.
    186   EXPECT_EQ(kSmallerIconUrl,
    187             util::FindPreferredIcon(icons, kMediumSize - 3).spec());
    188   // The requested size is larger than the largest icon. The largest icon
    189   // should be returned.
    190   EXPECT_EQ(kBiggerIconUrl,
    191             util::FindPreferredIcon(icons, kMediumSize + 3).spec());
    192 }
    193 
    194 TEST_F(DriveAppRegistryTest, UninstallDriveApp) {
    195   apps_registry_->Update();
    196   base::RunLoop().RunUntilIdle();
    197 
    198   std::vector<DriveAppInfo> apps;
    199   apps_registry_->GetAppList(&apps);
    200   size_t original_count = apps.size();
    201 
    202   // Uninstall an existing app.
    203   google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
    204   apps_registry_->UninstallApp(
    205       "123456788192",
    206       google_apis::test_util::CreateCopyResultCallback(&error));
    207   base::RunLoop().RunUntilIdle();
    208   EXPECT_EQ(error, google_apis::HTTP_NO_CONTENT);
    209 
    210   // Check that the number of apps is decreased by one.
    211   apps_registry_->GetAppList(&apps);
    212   EXPECT_EQ(original_count - 1, apps.size());
    213 
    214   // Try to uninstall a non-existing app.
    215   error = google_apis::GDATA_OTHER_ERROR;
    216   apps_registry_->UninstallApp(
    217       "non-existing-app-id",
    218       google_apis::test_util::CreateCopyResultCallback(&error));
    219   base::RunLoop().RunUntilIdle();
    220   EXPECT_EQ(error, google_apis::HTTP_NOT_FOUND);
    221 
    222   // Check that the number is not changed this time.
    223   apps_registry_->GetAppList(&apps);
    224   EXPECT_EQ(original_count - 1, apps.size());
    225 }
    226 
    227 }  // namespace drive
    228