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