Commit 7fef56a1 authored by kinaba@chromium.org's avatar kinaba@chromium.org

Implement DriveAppRegistry::UninstallApp() and GetAppList().

BUG=324166

Review URL: https://codereview.chromium.org/133123004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@244182 0039d316-1c4b-4281-b951-d872f2087c98
parent 6d817973
...@@ -35,6 +35,16 @@ void FindAppsForSelector(const std::string& selector, ...@@ -35,6 +35,16 @@ void FindAppsForSelector(const std::string& selector,
matched_apps->push_back(it->second); matched_apps->push_back(it->second);
} }
void RemoveAppFromSelector(const std::string& app_id,
std::multimap<std::string, std::string>* map) {
typedef std::multimap<std::string, std::string>::iterator iterator;
for (iterator it = map->begin(); it != map->end(); ) {
iterator now = it++;
if (now->second == app_id)
map->erase(now);
}
}
} // namespace } // namespace
namespace drive { namespace drive {
...@@ -95,6 +105,16 @@ void DriveAppRegistry::GetAppsForFile( ...@@ -95,6 +105,16 @@ void DriveAppRegistry::GetAppsForFile(
} }
} }
void DriveAppRegistry::GetAppList(std::vector<DriveAppInfo>* apps) const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
apps->clear();
for (std::map<std::string, DriveAppInfo>::const_iterator
it = all_apps_.begin(); it != all_apps_.end(); ++it) {
apps->push_back(it->second);
}
}
void DriveAppRegistry::Update() { void DriveAppRegistry::Update() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
...@@ -160,6 +180,37 @@ void DriveAppRegistry::UpdateFromAppList(const google_apis::AppList& app_list) { ...@@ -160,6 +180,37 @@ void DriveAppRegistry::UpdateFromAppList(const google_apis::AppList& app_list) {
} }
} }
void DriveAppRegistry::UninstallApp(const std::string& app_id,
const UninstallCallback& callback) {
DCHECK(!callback.is_null());
drive_service_->UninstallApp(app_id,
base::Bind(&DriveAppRegistry::OnAppUninstalled,
weak_ptr_factory_.GetWeakPtr(),
app_id,
callback));
}
void DriveAppRegistry::OnAppUninstalled(const std::string& app_id,
const UninstallCallback& callback,
google_apis::GDataErrorCode error) {
if (error == google_apis::HTTP_SUCCESS) {
all_apps_.erase(app_id);
RemoveAppFromSelector(app_id, &mimetype_map_);
RemoveAppFromSelector(app_id, &extension_map_);
}
callback.Run(error);
}
// static
bool DriveAppRegistry::IsAppUninstallSupported() {
#ifdef USE_OFFICIAL_GOOGLE_API_KEYS
return true;
#else
return false;
#endif
}
namespace util { namespace util {
GURL FindPreferredIcon(const google_apis::InstalledApp::IconList& icons, GURL FindPreferredIcon(const google_apis::InstalledApp::IconList& icons,
......
...@@ -51,6 +51,9 @@ struct DriveAppInfo { ...@@ -51,6 +51,9 @@ struct DriveAppInfo {
GURL create_url; GURL create_url;
}; };
// Callback type for UninstallApp().
typedef base::Callback<void(google_apis::GDataErrorCode)> UninstallCallback;
// Keeps the track of installed drive applications in-memory. // Keeps the track of installed drive applications in-memory.
class DriveAppRegistry { class DriveAppRegistry {
public: public:
...@@ -63,6 +66,19 @@ class DriveAppRegistry { ...@@ -63,6 +66,19 @@ class DriveAppRegistry {
const std::string& mime_type, const std::string& mime_type,
std::vector<DriveAppInfo>* apps) const; std::vector<DriveAppInfo>* apps) const;
// Returns the list of all Drive apps installed.
void GetAppList(std::vector<DriveAppInfo>* apps) const;
// Uninstalls the app specified by |app_id|. This method sends requests to the
// remote server, and returns the result to |callback| asynchronously.
// |callback| must not be null.
void UninstallApp(const std::string& app_id,
const UninstallCallback& callback);
// Checks whether UinstallApp is supported. The feature is available only for
// clients with whitelisted API keys (like Official Google Chrome build).
static bool IsAppUninstallSupported();
// Updates this registry by fetching the data from the server. // Updates this registry by fetching the data from the server.
void Update(); void Update();
...@@ -75,6 +91,11 @@ class DriveAppRegistry { ...@@ -75,6 +91,11 @@ class DriveAppRegistry {
void UpdateAfterGetAppList(google_apis::GDataErrorCode gdata_error, void UpdateAfterGetAppList(google_apis::GDataErrorCode gdata_error,
scoped_ptr<google_apis::AppList> app_list); scoped_ptr<google_apis::AppList> app_list);
// Part of UninstallApp(). Receives the response from the server.
void OnAppUninstalled(const std::string& app_id,
const UninstallCallback& callback,
google_apis::GDataErrorCode error);
// Map of application id to each app's info. // Map of application id to each app's info.
std::map<std::string, DriveAppInfo> all_apps_; std::map<std::string, DriveAppInfo> all_apps_;
......
...@@ -137,4 +137,37 @@ TEST(DriveAppRegistryUtilTest, FindPreferredIcon_) { ...@@ -137,4 +137,37 @@ TEST(DriveAppRegistryUtilTest, FindPreferredIcon_) {
util::FindPreferredIcon(icons, kMediumSize + 3).spec()); util::FindPreferredIcon(icons, kMediumSize + 3).spec());
} }
TEST_F(DriveAppRegistryTest, UninstallDriveApp) {
apps_registry_->Update();
base::RunLoop().RunUntilIdle();
std::vector<DriveAppInfo> apps;
apps_registry_->GetAppList(&apps);
size_t original_count = apps.size();
// Uninstall an existing app.
google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
apps_registry_->UninstallApp(
"123456788192",
google_apis::test_util::CreateCopyResultCallback(&error));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(error, google_apis::HTTP_SUCCESS);
// 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::GDATA_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 } // namespace drive
...@@ -267,7 +267,12 @@ bool FakeDriveService::LoadAccountMetadataForWapi( ...@@ -267,7 +267,12 @@ bool FakeDriveService::LoadAccountMetadataForWapi(
bool FakeDriveService::LoadAppListForDriveApi( bool FakeDriveService::LoadAppListForDriveApi(
const std::string& relative_path) { const std::string& relative_path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
app_info_value_ = test_util::LoadJSONFile(relative_path);
// Load JSON data, which must be a dictionary.
scoped_ptr<base::Value> value = test_util::LoadJSONFile(relative_path);
CHECK_EQ(base::Value::TYPE_DICTIONARY, value->GetType());
app_info_value_.reset(
static_cast<base::DictionaryValue*>(value.release()));
return app_info_value_; return app_info_value_;
} }
...@@ -1261,6 +1266,29 @@ CancelCallback FakeDriveService::UninstallApp( ...@@ -1261,6 +1266,29 @@ CancelCallback FakeDriveService::UninstallApp(
const google_apis::EntryActionCallback& callback) { const google_apis::EntryActionCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(!callback.is_null()); DCHECK(!callback.is_null());
// Find app_id from app_info_value_ and delete.
google_apis::GDataErrorCode error = google_apis::HTTP_NOT_FOUND;
if (offline_) {
error = google_apis::GDATA_NO_CONNECTION;
} else {
base::ListValue* items = NULL;
if (app_info_value_->GetList("items", &items)) {
for (size_t i = 0; i < items->GetSize(); ++i) {
base::DictionaryValue* item = NULL;
std::string id;
if (items->GetDictionary(i, &item) && item->GetString("id", &id) &&
id == app_id) {
if (items->Remove(i, NULL))
error = google_apis::HTTP_SUCCESS;
break;
}
}
}
}
base::MessageLoop::current()->PostTask(FROM_HERE,
base::Bind(callback, error));
return CancelCallback(); return CancelCallback();
} }
......
...@@ -299,7 +299,7 @@ class FakeDriveService : public DriveServiceInterface { ...@@ -299,7 +299,7 @@ class FakeDriveService : public DriveServiceInterface {
scoped_ptr<base::DictionaryValue> resource_list_value_; scoped_ptr<base::DictionaryValue> resource_list_value_;
scoped_ptr<base::DictionaryValue> account_metadata_value_; scoped_ptr<base::DictionaryValue> account_metadata_value_;
scoped_ptr<base::Value> app_info_value_; scoped_ptr<base::DictionaryValue> app_info_value_;
std::map<GURL, UploadSession> upload_sessions_; std::map<GURL, UploadSession> upload_sessions_;
int64 largest_changestamp_; int64 largest_changestamp_;
int64 published_date_seq_; int64 published_date_seq_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment