// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "components/drive/drive_app_registry.h" #include "base/files/file_path.h" #include "base/macros.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/values.h" #include "components/drive/drive_app_registry_observer.h" #include "components/drive/service/fake_drive_service.h" #include "google_apis/drive/drive_api_parser.h" #include "google_apis/drive/test_util.h" #include "testing/gtest/include/gtest/gtest.h" namespace drive { class TestDriveAppRegistryObserver : public DriveAppRegistryObserver { public: explicit TestDriveAppRegistryObserver(DriveAppRegistry* registry) : registry_(registry), update_count_(0) { registry_->AddObserver(this); } ~TestDriveAppRegistryObserver() override { registry_->RemoveObserver(this); } int update_count() const { return update_count_; } private: // DriveAppRegistryObserver overrides: void OnDriveAppRegistryUpdated() override { ++update_count_; } DriveAppRegistry* registry_; int update_count_; DISALLOW_COPY_AND_ASSIGN(TestDriveAppRegistryObserver); }; class DriveAppRegistryTest : public testing::Test { protected: void SetUp() override { fake_drive_service_.reset(new FakeDriveService); fake_drive_service_->LoadAppListForDriveApi("drive/applist.json"); apps_registry_.reset(new DriveAppRegistry(fake_drive_service_.get())); } bool VerifyApp(const std::vector& list, const std::string& app_id, const std::string& app_name) { bool found = false; for (size_t i = 0; i < list.size(); ++i) { const DriveAppInfo& app = list[i]; if (app_id == app.app_id) { EXPECT_EQ(app_name, app.app_name); found = true; break; } } EXPECT_TRUE(found) << "Unable to find app with app_id " << app_id; return found; } base::MessageLoop message_loop_; scoped_ptr fake_drive_service_; scoped_ptr apps_registry_; }; TEST_F(DriveAppRegistryTest, BasicParse) { TestDriveAppRegistryObserver observer(apps_registry_.get()); apps_registry_->Update(); base::RunLoop().RunUntilIdle(); EXPECT_EQ(1, observer.update_count()); std::vector apps; apps_registry_->GetAppList(&apps); ASSERT_EQ(2u, apps.size()); EXPECT_EQ("123456788192", apps[0].app_id); EXPECT_EQ("Drive app 1", apps[0].app_name); EXPECT_EQ("https://www.example.com/createForApp1", apps[0].create_url.spec()); EXPECT_EQ("abcdefghabcdefghabcdefghabcdefgh", apps[0].product_id); EXPECT_TRUE(apps[0].is_removable); } TEST_F(DriveAppRegistryTest, LoadAndFindDriveApps) { TestDriveAppRegistryObserver observer(apps_registry_.get()); apps_registry_->Update(); base::RunLoop().RunUntilIdle(); EXPECT_EQ(1, observer.update_count()); // Find by primary extension 'exe'. std::vector ext_results; base::FilePath ext_file(FILE_PATH_LITERAL("drive/file.exe")); apps_registry_->GetAppsForFile(ext_file.Extension(), "", &ext_results); ASSERT_EQ(1U, ext_results.size()); VerifyApp(ext_results, "123456788192", "Drive app 1"); // Find by primary MIME type. std::vector primary_app; apps_registry_->GetAppsForFile(base::FilePath::StringType(), "application/vnd.google-apps.drive-sdk.123456788192", &primary_app); ASSERT_EQ(1U, primary_app.size()); VerifyApp(primary_app, "123456788192", "Drive app 1"); // Find by secondary MIME type. std::vector secondary_app; apps_registry_->GetAppsForFile( base::FilePath::StringType(), "text/html", &secondary_app); ASSERT_EQ(1U, secondary_app.size()); VerifyApp(secondary_app, "123456788192", "Drive app 1"); } TEST_F(DriveAppRegistryTest, UpdateFromAppList) { scoped_ptr app_info_value = google_apis::test_util::LoadJSONFile("drive/applist.json"); scoped_ptr app_list( google_apis::AppList::CreateFrom(*app_info_value)); TestDriveAppRegistryObserver observer(apps_registry_.get()); apps_registry_->UpdateFromAppList(*app_list); EXPECT_EQ(1, observer.update_count()); // Confirm that something was loaded from applist.json. std::vector ext_results; base::FilePath ext_file(FILE_PATH_LITERAL("drive/file.exe")); apps_registry_->GetAppsForFile(ext_file.Extension(), "", &ext_results); ASSERT_EQ(1U, ext_results.size()); } TEST_F(DriveAppRegistryTest, MultipleUpdate) { TestDriveAppRegistryObserver observer(apps_registry_.get()); // Call Update(). apps_registry_->Update(); EXPECT_EQ(0, observer.update_count()); // Call Update() again. // This call should be ignored because there is already an ongoing update. apps_registry_->Update(); EXPECT_EQ(0, observer.update_count()); // The app list should be loaded only once. base::RunLoop().RunUntilIdle(); EXPECT_EQ(1, fake_drive_service_->app_list_load_count()); EXPECT_EQ(1, observer.update_count()); } TEST(DriveAppRegistryUtilTest, FindPreferredIcon_Empty) { DriveAppInfo::IconList icons; EXPECT_EQ("", util::FindPreferredIcon(icons, util::kPreferredIconSize).spec()); } TEST(DriveAppRegistryUtilTest, FindPreferredIcon_) { const char kSmallerIconUrl[] = "http://example.com/smaller.png"; const char kMediumIconUrl[] = "http://example.com/medium.png"; const char kBiggerIconUrl[] = "http://example.com/bigger.png"; const int kMediumSize = 16; DriveAppInfo::IconList icons; // The icons are not sorted by the size. icons.push_back(std::make_pair(kMediumSize, GURL(kMediumIconUrl))); icons.push_back(std::make_pair(kMediumSize + 2, GURL(kBiggerIconUrl))); icons.push_back(std::make_pair(kMediumSize - 2, GURL(kSmallerIconUrl))); // Exact match. EXPECT_EQ(kMediumIconUrl, util::FindPreferredIcon(icons, kMediumSize).spec()); // The requested size is in-between of smaller.png and // medium.png. medium.png should be returned. EXPECT_EQ(kMediumIconUrl, util::FindPreferredIcon(icons, kMediumSize - 1).spec()); // The requested size is smaller than the smallest icon. The smallest icon // should be returned. EXPECT_EQ(kSmallerIconUrl, util::FindPreferredIcon(icons, kMediumSize - 3).spec()); // The requested size is larger than the largest icon. The largest icon // should be returned. EXPECT_EQ(kBiggerIconUrl, util::FindPreferredIcon(icons, kMediumSize + 3).spec()); } TEST_F(DriveAppRegistryTest, UninstallDriveApp) { apps_registry_->Update(); base::RunLoop().RunUntilIdle(); std::vector apps; apps_registry_->GetAppList(&apps); size_t original_count = apps.size(); // Uninstall an existing app. google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR; apps_registry_->UninstallApp( "123456788192", google_apis::test_util::CreateCopyResultCallback(&error)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(error, google_apis::HTTP_NO_CONTENT); // Check that the number of apps is decreased by one. apps_registry_->GetAppList(&apps); EXPECT_EQ(original_count - 1, apps.size()); // Try to uninstall a non-existing app. error = google_apis::DRIVE_OTHER_ERROR; apps_registry_->UninstallApp( "non-existing-app-id", google_apis::test_util::CreateCopyResultCallback(&error)); base::RunLoop().RunUntilIdle(); EXPECT_EQ(error, google_apis::HTTP_NOT_FOUND); // Check that the number is not changed this time. apps_registry_->GetAppList(&apps); EXPECT_EQ(original_count - 1, apps.size()); } } // namespace drive