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

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: Store ExtensionService* in AppListSyncableService Created 7 years 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 52ce18dcbf35bee9d8dc64b1631563e3597b2f19..007fc046eca8fd83d2510f15efec46236bfe43d1 100644
--- a/chrome/browser/ui/app_list/app_list_syncable_service.cc
+++ b/chrome/browser/ui/app_list/app_list_syncable_service.cc
@@ -6,8 +6,8 @@
#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"
#include "chrome/browser/ui/app_list/app_list_service.h"
#include "chrome/browser/ui/app_list/extension_app_item.h"
@@ -19,6 +19,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_model.h"
#include "ui/app_list/app_list_model.h"
@@ -44,6 +45,10 @@ bool UpdateSyncItemFromAppItem(const AppListItemModel* 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 +80,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
@@ -95,6 +117,7 @@ AppListSyncableService::AppListSyncableService(
Profile* profile,
ExtensionService* extension_service)
: profile_(profile),
+ extension_service_(extension_service),
model_(new AppListModel) {
if (extension_service && extension_service->is_ready()) {
BuildModel();
@@ -152,26 +175,66 @@ 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(AppListItemModel* item) {
+ const std::string& item_id = item->id();
+ if (item_id.empty()) {
+ LOG(ERROR) << "AppListItemModel 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 entry, uninstall the app instead.
+ if (type == sync_pb::AppListSpecifics_AppListItemType_TYPE_APP &&
+ AppIsDefault(extension_service_, item_id)) {
+ DVLOG(1) << this << ": AddItem: Uninstall: " << sync_item->ToString();
+ UninstallExtension(extension_service_, item_id);
+ return;
+ }
+ // Otherwise, delete the REMOVE_DEFAULT entry.
+ 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);
+ }
+
+ 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_service_, item->id());
SendSyncChange(sync_item, SyncChange::ACTION_ADD);
}
-void AppListSyncableService::UpdateExtensionAppItem(ExtensionAppItem* item) {
+void AppListSyncableService::UpdateItem(AppListItemModel* 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;
@@ -182,9 +245,24 @@ 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;
+ }
+
+ // 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,
@@ -194,7 +272,15 @@ void AppListSyncableService::RemoveItem(const std::string& id) {
}
delete sync_item;
sync_items_.erase(iter);
- model_->item_list()->DeleteItem(id);
+
+ if (!AppIsDefault(extension_service_, id))
+ return;
+ // This is a Default app; create and send a REMOVE_DEFAULT sync change.
+ // Note: we add the REMOVE_DEFAULT entry after we delete the existing entry.
+ sync_item = CreateSyncItem(
+ id, sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP);
+ DVLOG(1) << this << ": RemoveDefaultItem: " << sync_item->ToString();
+ SendSyncChange(sync_item, SyncChange::ACTION_ADD);
}
// AppListSyncableService syncer::SyncableService
@@ -228,8 +314,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;
@@ -266,7 +355,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) {
@@ -286,14 +375,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 {
@@ -305,36 +396,87 @@ 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_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_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) {
+ AppListItemModel* 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() {
@@ -348,26 +490,6 @@ bool AppListSyncableService::SyncStarted() {
return false;
}
-AppListSyncableService::SyncItem* AppListSyncableService::AddItem(
- sync_pb::AppListSpecifics::AppListItemType type,
- AppListItemModel* app_item) {
- const std::string& item_id = app_item->id();
- if (item_id.empty()) {
- LOG(ERROR) << "AppListItemModel 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) {
@@ -394,47 +516,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
- AppListItemModel* 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(
@@ -444,18 +533,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
« no previous file with comments | « chrome/browser/ui/app_list/app_list_syncable_service.h ('k') | chrome/browser/ui/app_list/extension_app_model_builder.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698