Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Unified Diff: chrome/browser/ui/app_list/app_list_syncable_service.cc

Issue 118463002: Sync removal of Default apps. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/app_list/app_list_syncable_service.cc
diff --git a/chrome/browser/ui/app_list/app_list_syncable_service.cc b/chrome/browser/ui/app_list/app_list_syncable_service.cc
index e3a5e065843e6d4323805ba671c38d088fe10afe..0d0baee923c7cab9a02d7b7195a4c972790fc35a 100644
--- a/chrome/browser/ui/app_list/app_list_syncable_service.cc
+++ b/chrome/browser/ui/app_list/app_list_syncable_service.cc
@@ -6,6 +6,7 @@
#include "base/command_line.h"
#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/extensions/extension_prefs.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/profiles/profile.h"
@@ -19,6 +20,7 @@
#include "sync/api/sync_data.h"
#include "sync/api/sync_merge_result.h"
#include "sync/protocol/sync.pb.h"
+#include "ui/app_list/app_list_folder_item.h"
#include "ui/app_list/app_list_item.h"
#include "ui/app_list/app_list_model.h"
@@ -44,6 +46,10 @@ bool UpdateSyncItemFromAppItem(const AppListItem* app_item,
AppListSyncableService::SyncItem* sync_item) {
DCHECK_EQ(sync_item->item_id, app_item->id());
bool changed = false;
+ if (sync_item->item_name != app_item->title()) {
+ sync_item->item_name = app_item->title();
+ changed = true;
+ }
if (!sync_item->item_ordinal.IsValid() ||
!app_item->position().Equals(sync_item->item_ordinal)) {
sync_item->item_ordinal = app_item->position();
@@ -75,6 +81,23 @@ syncer::SyncData GetSyncDataFromSyncItem(
specifics);
}
+bool AppIsDefault(ExtensionService* service, const std::string& id) {
+ return service && service->extension_prefs()->WasInstalledByDefault(id);
+}
+
+bool AppIsPlatformApp(ExtensionService* service, const std::string& id) {
+ if (!service)
+ return false;
+ const extensions::Extension* app = service->GetInstalledExtension(id);
+ DVLOG_IF(1, !app) << "No App for ID: " << id;
+ return app ? app->is_platform_app() : false;
+}
+
+void UninstallExtension(ExtensionService* service, const std::string& id) {
+ if (service && service->GetInstalledExtension(id))
+ service->UninstallExtension(id, false, NULL);
+}
+
} // namespace
// AppListSyncableService::SyncItem
@@ -93,10 +116,16 @@ AppListSyncableService::SyncItem::~SyncItem() {
AppListSyncableService::AppListSyncableService(
Profile* profile,
- ExtensionService* extension_service)
+ extensions::ExtensionSystem* extension_system)
: profile_(profile),
+ extension_system_(extension_system),
model_(new AppListModel) {
- if (extension_service && extension_service->is_ready()) {
+ if (!extension_system || !extension_system->extension_service()) {
+ LOG(WARNING) << "AppListSyncableService created with no ExtensionService";
+ return;
+ }
+
+ if (extension_system->extension_service()->is_ready()) {
BuildModel();
return;
}
@@ -153,26 +182,71 @@ AppListSyncableService::GetSyncItem(const std::string& id) const {
return NULL;
}
-void AppListSyncableService::AddExtensionAppItem(ExtensionAppItem* item) {
- SyncItem* sync_item = AddItem(
- sync_pb::AppListSpecifics_AppListItemType_TYPE_APP, item);
- if (!sync_item)
- return; // Item already exists.
- sync_item->item_name = item->extension_name();
+void AppListSyncableService::AddItem(AppListItem* item) {
+ const std::string& item_id = item->id();
+ if (item_id.empty()) {
+ LOG(ERROR) << "AppListItem item with empty ID";
+ return;
+ }
+ sync_pb::AppListSpecifics::AppListItemType type;
+ const char* item_type = item->GetAppType();
+ if (item_type == ExtensionAppItem::kAppType) {
+ type = sync_pb::AppListSpecifics_AppListItemType_TYPE_APP;
+ } else if (item_type == AppListFolderItem::kAppType) {
+ type = sync_pb::AppListSpecifics_AppListItemType_TYPE_FOLDER;
+ } else {
+ LOG(ERROR) << "Unrecognized model type: " << item_type;
+ return;
+ }
+ SyncItem* sync_item = FindSyncItem(item_id);
+ if (sync_item) {
+ // If there is an existing, non-REMOVE_DEFAULT entry, update it.
+ if (sync_item->item_type !=
+ sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP) {
+ DCHECK_EQ(sync_item->item_type, type);
+ DVLOG(2) << this << ": AddItem already exists: " << sync_item->ToString();
+ UpdateItem(item);
+ return;
+ }
+ // If there is an existing REMOVE_DEFAULT_APP entry, and the app is
+ // installed as a Default app, uninstall the app instead of adding it.
+ if (type == sync_pb::AppListSpecifics_AppListItemType_TYPE_APP &&
+ AppIsDefault(extension_system_->extension_service(), item_id)) {
+ DVLOG(1) << this << ": AddItem: Uninstall: " << sync_item->ToString();
+ UninstallExtension(extension_system_->extension_service(), item_id);
+ return;
+ }
+ // Otherwise, we are adding the app as a non-default app (i.e. an app that
+ // was installed by Default and removed is getting installed explicitly by
+ // the user), so delete the REMOVE_DEFAULT_APP.
+ if (SyncStarted()) {
+ DVLOG(2) << this << " -> SYNC DELETE: " << sync_item->ToString();
+ SyncChange sync_change(FROM_HERE, SyncChange::ACTION_DELETE,
+ GetSyncDataFromSyncItem(sync_item));
+ sync_processor_->ProcessSyncChanges(
+ FROM_HERE, syncer::SyncChangeList(1, sync_change));
+ }
+ delete sync_item;
+ sync_items_.erase(item_id);
+ // Fall through. The REMOVE_DEFAULT_APP entry has been deleted, now an App
+ // entry can be added as usual.
+ }
+
+ sync_item = CreateSyncItem(item_id, type);
+ UpdateSyncItemFromAppItem(item, sync_item);
+ model_->item_list()->AddItem(item);
+ DVLOG(1) << this << ": AddItem: " << sync_item->ToString() << " Default: "
+ << AppIsDefault(extension_system_->extension_service(), item->id());
SendSyncChange(sync_item, SyncChange::ACTION_ADD);
}
-void AppListSyncableService::UpdateExtensionAppItem(ExtensionAppItem* item) {
+void AppListSyncableService::UpdateItem(AppListItem* item) {
SyncItem* sync_item = FindSyncItem(item->id());
if (!sync_item) {
- LOG(ERROR) << "UpdateExtensionAppItem: no sync item: " << item->id();
+ LOG(ERROR) << "UpdateItem: no sync item: " << item->id();
return;
}
bool changed = UpdateSyncItemFromAppItem(item, sync_item);
- if (sync_item->item_name != item->extension_name()) {
- sync_item->item_name = item->extension_name();
- changed = true;
- }
if (!changed) {
DVLOG(2) << this << " - Update: SYNC NO CHANGE: " << sync_item->ToString();
return;
@@ -183,9 +257,34 @@ void AppListSyncableService::UpdateExtensionAppItem(ExtensionAppItem* item) {
void AppListSyncableService::RemoveItem(const std::string& id) {
DVLOG(2) << this << ": RemoveItem: " << id.substr(0, 8);
SyncItemMap::iterator iter = sync_items_.find(id);
- if (iter == sync_items_.end())
+ if (iter == sync_items_.end()) {
+ DVLOG(2) << this << " : No Sync Item.";
return;
+ }
+ // Always delete the item from the model.
+ model_->item_list()->DeleteItem(id);
+
+ // Check for existing RemoveDefault sync item.
SyncItem* sync_item = iter->second;
+ if (sync_item->item_type ==
+ sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP) {
+ // RemoveDefault item exists, just return.
+ DVLOG(2) << this << " : RemoveDefault Item exists.";
+ return;
+ }
+
+ if (AppIsDefault(extension_system_->extension_service(), id)) {
+ // This is a Default app; update the entry to a REMOVE_DEFAULT entry. This
+ // will overwrite any existing entry for the item.
+ DVLOG(2) << this << " -> SYNC UPDATE: REMOVE_DEFAULT: "
+ << sync_item->item_id;
+ sync_item->item_type = sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP;
+ SendSyncChange(sync_item, SyncChange::ACTION_UPDATE);
+ return;
+ }
+
+ // Existing entry is a normal entry, send a Delete sync change and remove
+ // the entry.
if (SyncStarted()) {
DVLOG(2) << this << " -> SYNC DELETE: " << sync_item->ToString();
SyncChange sync_change(FROM_HERE, SyncChange::ACTION_DELETE,
@@ -195,7 +294,6 @@ void AppListSyncableService::RemoveItem(const std::string& id) {
}
delete sync_item;
sync_items_.erase(iter);
- model_->item_list()->DeleteItem(id);
}
// AppListSyncableService syncer::SyncableService
@@ -229,8 +327,11 @@ syncer::SyncMergeResult AppListSyncableService::MergeDataAndStartSyncing(
for (syncer::SyncDataList::const_iterator iter = initial_sync_data.begin();
iter != initial_sync_data.end(); ++iter) {
const syncer::SyncData& data = *iter;
+ DVLOG(2) << this << " Initial Sync Item: "
+ << data.GetSpecifics().app_list().item_id()
+ << " Type: " << data.GetSpecifics().app_list().item_type();
DCHECK_EQ(syncer::APP_LIST, data.GetDataType());
- if (CreateOrUpdateSyncItem(data.GetSpecifics().app_list()))
+ if (ProcessSyncItem(data.GetSpecifics().app_list()))
++new_items;
else
++updated_items;
@@ -267,7 +368,7 @@ syncer::SyncDataList AppListSyncableService::GetAllSyncData(
syncer::ModelType type) const {
DCHECK_EQ(syncer::APP_LIST, type);
- DVLOG(1) << this << "GetAllSyncData: " << sync_items_.size();
+ DVLOG(1) << this << ": GetAllSyncData: " << sync_items_.size();
syncer::SyncDataList list;
for (SyncItemMap::const_iterator iter = sync_items_.begin();
iter != sync_items_.end(); ++iter) {
@@ -287,14 +388,16 @@ syncer::SyncError AppListSyncableService::ProcessSyncChanges(
syncer::APP_LIST);
}
- // Process incoming changes first.
DVLOG(1) << this << ": ProcessSyncChanges: " << change_list.size();
for (syncer::SyncChangeList::const_iterator iter = change_list.begin();
iter != change_list.end(); ++iter) {
const SyncChange& change = *iter;
+ DVLOG(2) << this << " Change: "
+ << change.sync_data().GetSpecifics().app_list().item_id()
+ << " (" << change.change_type() << ")";
if (change.change_type() == SyncChange::ACTION_ADD ||
change.change_type() == SyncChange::ACTION_UPDATE) {
- CreateOrUpdateSyncItem(change.sync_data().GetSpecifics().app_list());
+ ProcessSyncItem(change.sync_data().GetSpecifics().app_list());
} else if (change.change_type() == SyncChange::ACTION_DELETE) {
DeleteSyncItem(change.sync_data().GetSpecifics().app_list());
} else {
@@ -306,36 +409,89 @@ syncer::SyncError AppListSyncableService::ProcessSyncChanges(
// AppListSyncableService private
-void AppListSyncableService::CreateAppItemFromSyncItem(SyncItem* sync_item) {
- if (sync_item->item_type == sync_pb::AppListSpecifics::TYPE_APP) {
- std::string extension_id = sync_item->item_id;
- const ExtensionService* extension_service =
- extensions::ExtensionSystem::Get(profile_)->extension_service();
- const extensions::Extension* app =
- extension_service->GetInstalledExtension(extension_id);
- DVLOG_IF(1, !app) << this << "No App for ID: " << extension_id;
- bool is_platform_app = app ? app->is_platform_app() : false;
- ExtensionAppItem* app_item = new ExtensionAppItem(
- profile_,
- sync_item,
- extension_id,
- sync_item->item_name,
- gfx::ImageSkia(),
- is_platform_app);
- model_->item_list()->AddItem(app_item);
- return;
+bool AppListSyncableService::ProcessSyncItem(
+ const sync_pb::AppListSpecifics& specifics) {
+ const std::string& item_id = specifics.item_id();
+ if (item_id.empty()) {
+ LOG(ERROR) << "AppList item with empty ID";
+ return false;
}
- if (sync_item->item_type ==
- sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP) {
- // TODO(stevenjb): Implement
+ SyncItem* sync_item = FindSyncItem(item_id);
+ if (sync_item) {
+ // If an item of the same type exists, update it.
+ if (sync_item->item_type == specifics.item_type()) {
+ UpdateSyncItemFromSync(specifics, sync_item);
+ ProcessExistingSyncItem(sync_item);
+ DVLOG(2) << this << " <- SYNC UPDATE: " << sync_item->ToString();
+ return false;
+ }
+ // Otherwise, one of the entries should be TYPE_REMOVE_DEFAULT_APP.
+ if (sync_item->item_type !=
+ sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP &&
+ specifics.item_type() !=
+ sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP) {
+ LOG(ERROR) << "Synced item type: " << specifics.item_type()
+ << " != existing sync item type: " << sync_item->item_type
+ << " Deleting item from model!";
+ model_->item_list()->DeleteItem(item_id);
+ }
+ DVLOG(2) << this << " - ProcessSyncItem: Delete existing entry: "
+ << sync_item->ToString();
+ delete sync_item;
+ sync_items_.erase(item_id);
}
- if (sync_item->item_type == sync_pb::AppListSpecifics::TYPE_FOLDER) {
- // TODO(stevenjb): Implement
+
+ sync_item = CreateSyncItem(item_id, specifics.item_type());
+ UpdateSyncItemFromSync(specifics, sync_item);
+ ProcessNewSyncItem(sync_item);
+ DVLOG(2) << this << " <- SYNC ADD: " << sync_item->ToString();
+ return true;
+}
+
+void AppListSyncableService::ProcessNewSyncItem(SyncItem* sync_item) {
+ switch (sync_item->item_type) {
+ case sync_pb::AppListSpecifics::TYPE_APP: {
+ std::string extension_id = sync_item->item_id;
+ bool is_platform_app =
+ AppIsPlatformApp(extension_system_->extension_service(),
+ extension_id);
+ ExtensionAppItem* app_item = new ExtensionAppItem(
+ profile_,
+ sync_item,
+ extension_id,
+ sync_item->item_name,
+ gfx::ImageSkia(),
+ is_platform_app);
+ model_->item_list()->AddItem(app_item);
+ return;
+ }
+ case sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP: {
+ DVLOG(1) << this << ": Uninstall: " << sync_item->ToString();
+ UninstallExtension(extension_system_->extension_service(),
+ sync_item->item_id);
+ return;
+ }
+ case sync_pb::AppListSpecifics::TYPE_FOLDER: {
+ // TODO(stevenjb): Implement
+ LOG(WARNING) << "TYPE_FOLDER not supported";
+ return;
+ }
+ case sync_pb::AppListSpecifics::TYPE_URL: {
+ // TODO(stevenjb): Implement
+ LOG(WARNING) << "TYPE_URL not supported";
+ return;
+ }
}
- if (sync_item->item_type == sync_pb::AppListSpecifics::TYPE_URL) {
- // TODO(stevenjb): Implement
+ NOTREACHED() << "Unrecoginized sync item type: " << sync_item->ToString();
+}
+
+void AppListSyncableService::ProcessExistingSyncItem(SyncItem* sync_item) {
+ if (sync_item->item_type !=
+ sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP) {
+ AppListItem* item = model_->item_list()->FindItem(sync_item->item_id);
+ if (item && !item->position().Equals(sync_item->item_ordinal))
+ model_->item_list()->SetItemPosition(item, sync_item->item_ordinal);
}
- LOG(ERROR) << "Unsupported type: " << sync_item->item_type;
}
bool AppListSyncableService::SyncStarted() {
@@ -349,26 +505,6 @@ bool AppListSyncableService::SyncStarted() {
return false;
}
-AppListSyncableService::SyncItem* AppListSyncableService::AddItem(
- sync_pb::AppListSpecifics::AppListItemType type,
- AppListItem* app_item) {
- const std::string& item_id = app_item->id();
- if (item_id.empty()) {
- LOG(ERROR) << "AppListItem item with empty ID";
- return NULL;
- }
- bool new_item = false;
- SyncItem* sync_item = FindOrCreateSyncItem(item_id, type, &new_item);
- if (!new_item) {
- DVLOG(2) << this << ": AddItem already exists: " << sync_item->ToString();
- return NULL; // Item already exists.
- }
- UpdateSyncItemFromAppItem(app_item, sync_item);
- DVLOG(1) << this << ": AddItem: " << sync_item->ToString();
- model_->item_list()->AddItem(app_item);
- return sync_item;
-}
-
void AppListSyncableService::SendSyncChange(
SyncItem* sync_item,
SyncChange::SyncChangeType sync_change_type) {
@@ -395,47 +531,14 @@ AppListSyncableService::FindSyncItem(const std::string& item_id) {
return iter->second;
}
-AppListSyncableService::SyncItem* AppListSyncableService::FindOrCreateSyncItem(
+AppListSyncableService::SyncItem*
+AppListSyncableService::CreateSyncItem(
const std::string& item_id,
- sync_pb::AppListSpecifics::AppListItemType type,
- bool* new_item) {
- SyncItem* item = FindSyncItem(item_id);
- if (item) {
- DCHECK(type == item->item_type);
- *new_item = false;
- return item;
- }
-
- item = new SyncItem(item_id, type);
- sync_items_[item_id] = item;
- *new_item = true;
- return item;
-}
-
-bool AppListSyncableService::CreateOrUpdateSyncItem(
- const sync_pb::AppListSpecifics& specifics) {
- const std::string& item_id = specifics.item_id();
- if (item_id.empty()) {
- LOG(ERROR) << "CreateOrUpdate AppList item with empty ID";
- return false;
- }
- bool new_item = false;
- SyncItem* sync_item =
- FindOrCreateSyncItem(item_id, specifics.item_type(), &new_item);
- DVLOG(2) << this << "CreateOrUpdateSyncItem: " << sync_item->ToString()
- << " New: " << new_item << " Pos: " << specifics.item_ordinal();
- UpdateSyncItemFromSync(specifics, sync_item);
- // Update existing item in model
- AppListItem* item = model_->item_list()->FindItem(sync_item->item_id);
- if (item && !item->position().Equals(sync_item->item_ordinal))
- model_->item_list()->SetItemPosition(item, sync_item->item_ordinal);
- if (new_item) {
- CreateAppItemFromSyncItem(sync_item);
- DVLOG(2) << this << " <- SYNC ADD: " << sync_item->ToString();
- } else {
- DVLOG(2) << this << " <- SYNC UPDATE: " << sync_item->ToString();
- }
- return new_item;
+ sync_pb::AppListSpecifics::AppListItemType item_type) {
+ DCHECK(!ContainsKey(sync_items_, item_id));
+ SyncItem* sync_item = new SyncItem(item_id, item_type);
+ sync_items_[item_id] = sync_item;
+ return sync_item;
}
void AppListSyncableService::DeleteSyncItem(
@@ -445,18 +548,28 @@ void AppListSyncableService::DeleteSyncItem(
LOG(ERROR) << "Delete AppList item with empty ID";
return;
}
- DVLOG(2) << this << "DeleteSyncItem: " << item_id.substr(0, 8);
+ DVLOG(2) << this << ": DeleteSyncItem: " << item_id.substr(0, 8);
SyncItemMap::iterator iter = sync_items_.find(item_id);
if (iter == sync_items_.end())
return;
+ sync_pb::AppListSpecifics::AppListItemType item_type =
+ iter->second->item_type;
DVLOG(2) << this << " <- SYNC DELETE: " << iter->second->ToString();
delete iter->second;
sync_items_.erase(iter);
- model_->item_list()->DeleteItem(item_id);
+ if (item_type != sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP)
+ model_->item_list()->DeleteItem(item_id);
}
std::string AppListSyncableService::SyncItem::ToString() const {
- return item_id.substr(0, 8) + " [" + item_ordinal.ToDebugString() + "]";
+ std::string res = item_id.substr(0, 8);
+ if (item_type == sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP) {
+ res += " { RemoveDefault }";
+ } else {
+ res += " { " + item_name + " }";
+ res += " [" + item_ordinal.ToDebugString() + "]";
+ }
+ return res;
}
} // namespace app_list

Powered by Google App Engine
This is Rietveld 408576698