Upstream version 7.35.139.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / app_list / app_list_syncable_service.cc
index 3c8b35d..a49b8b2 100644 (file)
@@ -36,11 +36,6 @@ namespace {
 
 const char kOemFolderId[] = "ddb1da55-d478-4243-8642-56d3041f0263";
 
-bool SyncAppListEnabled() {
-  return !CommandLine::ForCurrentProcess()->HasSwitch(
-      ::switches::kDisableSyncAppList);
-}
-
 void UpdateSyncItemFromSync(const sync_pb::AppListSpecifics& specifics,
                             AppListSyncableService::SyncItem* item) {
   DCHECK_EQ(item->item_id, specifics.item_id());
@@ -140,7 +135,8 @@ AppListSyncableService::SyncItem::~SyncItem() {
 class AppListSyncableService::ModelObserver : public AppListModelObserver {
  public:
   explicit ModelObserver(AppListSyncableService* owner)
-      : owner_(owner) {
+      : owner_(owner),
+        adding_item_(NULL) {
     DVLOG(2) << owner_ << ": ModelObserver Added";
     owner_->model()->AddObserver(this);
   }
@@ -153,21 +149,37 @@ class AppListSyncableService::ModelObserver : public AppListModelObserver {
  private:
   // AppListModelObserver
   virtual void OnAppListItemAdded(AppListItem* item) OVERRIDE {
-    DVLOG(2) << owner_ << " OnAppListItemAdded: " << item->ToDebugString();
+    DCHECK(!adding_item_);
+    adding_item_ = item;  // Ignore updates while adding an item.
+    VLOG(2) << owner_ << " OnAppListItemAdded: " << item->ToDebugString();
     owner_->AddOrUpdateFromSyncItem(item);
+    adding_item_ = NULL;
   }
 
   virtual void OnAppListItemWillBeDeleted(AppListItem* item) OVERRIDE {
-    DVLOG(2) << owner_ << " OnAppListItemDeleted: " << item->ToDebugString();
+    DCHECK(!adding_item_);
+    VLOG(2) << owner_ << " OnAppListItemDeleted: " << item->ToDebugString();
+    // Don't sync folder removal in case the folder still exists on another
+    // device (e.g. with device specific items in it). Empty folders will be
+    // deleted when the last item is removed (in PruneEmptySyncFolders()).
+    if (item->GetItemType() == AppListFolderItem::kItemType)
+      return;
     owner_->RemoveSyncItem(item->id());
   }
 
   virtual void OnAppListItemUpdated(AppListItem* item) OVERRIDE {
-    DVLOG(2) << owner_ << " OnAppListItemUpdated: " << item->ToDebugString();
+    if (adding_item_) {
+      // Adding an item may trigger update notifications which should be
+      // ignored.
+      DCHECK_EQ(adding_item_, item);
+      return;
+    }
+    VLOG(2) << owner_ << " OnAppListItemUpdated: " << item->ToDebugString();
     owner_->UpdateSyncItem(item);
   }
 
   AppListSyncableService* owner_;
+  AppListItem* adding_item_;  // Unowned pointer to item being added.
 
   DISALLOW_COPY_AND_ASSIGN(ModelObserver);
 };
@@ -222,12 +234,14 @@ void AppListSyncableService::BuildModel() {
   apps_builder_.reset(new ExtensionAppModelBuilder(controller));
   DCHECK(profile_);
   // TODO(stevenjb): Correctly handle OTR profiles for Guest mode.
-  if (!profile_->IsOffTheRecord() && SyncAppListEnabled()) {
-    DVLOG(1) << this << ": AppListSyncableService: InitializeWithService.";
+  // crbug.com/359176.
+  if (!profile_->IsOffTheRecord() &&
+      app_list::switches::IsAppListSyncEnabled()) {
+    VLOG(1) << this << ": AppListSyncableService: InitializeWithService.";
     SyncStarted();
     apps_builder_->InitializeWithService(this);
   } else {
-    DVLOG(1) << this << ": AppListSyncableService: InitializeWithProfile.";
+    VLOG(1) << this << ": AppListSyncableService: InitializeWithProfile.";
     apps_builder_->InitializeWithProfile(profile_, model_.get());
   }
 }
@@ -263,14 +277,16 @@ void AppListSyncableService::AddItem(scoped_ptr<AppListItem> app_item) {
     return;  // Item is not valid.
 
   std::string folder_id;
-  if (AppIsOem(app_item->id())) {
-    folder_id = FindOrCreateOemFolder();
-    DVLOG(1) << this << ": AddItem to OEM folder: " << sync_item->ToString();
-  } else {
-    folder_id = sync_item->parent_id;
-    DVLOG(1) << this << ": AddItem: " << sync_item->ToString()
-             << " Folder: '" << folder_id << "'";
+  if (app_list::switches::IsFolderUIEnabled()) {
+    if (AppIsOem(app_item->id())) {
+      folder_id = FindOrCreateOemFolder();
+      VLOG(2) << this << ": AddItem to OEM folder: " << sync_item->ToString();
+    } else {
+      folder_id = sync_item->parent_id;
+    }
   }
+  VLOG(2) << this << ": AddItem: " << sync_item->ToString()
+          << "Folder: '" << folder_id << "'";
   model_->AddItemToFolder(app_item.Pass(), folder_id);
 }
 
@@ -305,6 +321,7 @@ AppListSyncableService::CreateSyncItemFromAppItem(AppListItem* app_item) {
   sync_pb::AppListSpecifics::AppListItemType type;
   if (!GetAppListItemType(app_item, &type))
     return NULL;
+  VLOG(2) << this << " CreateSyncItemFromAppItem:" << app_item->ToDebugString();
   SyncItem* sync_item = CreateSyncItem(app_item->id(), type);
   UpdateSyncItemFromAppItem(app_item, sync_item);
   SendSyncChange(sync_item, SyncChange::ACTION_ADD);
@@ -329,8 +346,8 @@ bool AppListSyncableService::RemoveDefaultApp(AppListItem* item,
   // installed as a Default app, uninstall the app instead of adding it.
   if (sync_item->item_type == sync_pb::AppListSpecifics::TYPE_APP &&
       AppIsDefault(extension_system_->extension_service(), item->id())) {
-    DVLOG(1) << this << ": HandleDefaultApp: Uninstall: "
-             << sync_item->ToString();
+    VLOG(2) << this << ": HandleDefaultApp: Uninstall: "
+            << sync_item->ToString();
     UninstallExtension(extension_system_->extension_service(), item->id());
     return true;
   }
@@ -344,7 +361,7 @@ bool AppListSyncableService::RemoveDefaultApp(AppListItem* item,
 
 void AppListSyncableService::DeleteSyncItem(SyncItem* sync_item) {
   if (SyncStarted()) {
-    DVLOG(2) << this << " -> SYNC DELETE: " << sync_item->ToString();
+    VLOG(2) << this << " -> SYNC DELETE: " << sync_item->ToString();
     SyncChange sync_change(FROM_HERE, SyncChange::ACTION_DELETE,
                            GetSyncDataFromSyncItem(sync_item));
     sync_processor_->ProcessSyncChanges(
@@ -377,6 +394,8 @@ void AppListSyncableService::RemoveItem(const std::string& id) {
 
 void AppListSyncableService::UpdateItem(AppListItem* app_item) {
   // Check to see if the item needs to be moved to/from the OEM folder.
+  if (!app_list::switches::IsFolderUIEnabled())
+    return;
   bool is_oem = AppIsOem(app_item->id());
   if (!is_oem && app_item->folder_id() == kOemFolderId)
     model_->MoveItemToFolder(app_item, "");
@@ -385,7 +404,7 @@ void AppListSyncableService::UpdateItem(AppListItem* app_item) {
 }
 
 void AppListSyncableService::RemoveSyncItem(const std::string& id) {
-  DVLOG(2) << this << ": RemoveSyncItem: " << id.substr(0, 8);
+  VLOG(2) << this << ": RemoveSyncItem: " << id.substr(0, 8);
   SyncItemMap::iterator iter = sync_items_.find(id);
   if (iter == sync_items_.end()) {
     DVLOG(2) << this << " : RemoveSyncItem: No Item.";
@@ -405,8 +424,8 @@ void AppListSyncableService::RemoveSyncItem(const std::string& id) {
       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;
+    VLOG(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;
@@ -470,8 +489,8 @@ syncer::SyncMergeResult AppListSyncableService::MergeDataAndStartSyncing(
 
   syncer::SyncMergeResult result = syncer::SyncMergeResult(type);
   result.set_num_items_before_association(sync_items_.size());
-  DVLOG(1) << this << ": MergeDataAndStartSyncing: "
-           << initial_sync_data.size();
+  VLOG(1) << this << ": MergeDataAndStartSyncing: "
+          << initial_sync_data.size();
 
   // Copy all sync items to |unsynced_items|.
   std::set<std::string> unsynced_items;
@@ -509,7 +528,7 @@ syncer::SyncMergeResult AppListSyncableService::MergeDataAndStartSyncing(
   for (std::set<std::string>::iterator iter = unsynced_items.begin();
        iter != unsynced_items.end(); ++iter) {
     SyncItem* sync_item = FindSyncItem(*iter);
-    DVLOG(2) << this << " -> SYNC ADD: " << sync_item->ToString();
+    VLOG(2) << this << " -> SYNC ADD: " << sync_item->ToString();
     change_list.push_back(SyncChange(FROM_HERE,  SyncChange::ACTION_ADD,
                                      GetSyncDataFromSyncItem(sync_item)));
   }
@@ -538,11 +557,11 @@ syncer::SyncDataList AppListSyncableService::GetAllSyncData(
     syncer::ModelType type) const {
   DCHECK_EQ(syncer::APP_LIST, type);
 
-  DVLOG(1) << this << ": GetAllSyncData: " << sync_items_.size();
+  VLOG(1) << this << ": GetAllSyncData: " << sync_items_.size();
   syncer::SyncDataList list;
   for (SyncItemMap::const_iterator iter = sync_items_.begin();
        iter != sync_items_.end(); ++iter) {
-    DVLOG(2) << this << " -> SYNC: " << iter->second->ToString();
+    VLOG(2) << this << " -> SYNC: " << iter->second->ToString();
     list.push_back(GetSyncDataFromSyncItem(iter->second));
   }
   return list;
@@ -561,13 +580,13 @@ syncer::SyncError AppListSyncableService::ProcessSyncChanges(
   // Don't observe the model while processing incoming sync changes.
   model_observer_.reset();
 
-  DVLOG(1) << this << ": ProcessSyncChanges: " << change_list.size();
+  VLOG(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() << ")";
+    VLOG(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) {
       ProcessSyncItemSpecifics(change.sync_data().GetSpecifics().app_list());
@@ -599,7 +618,7 @@ bool AppListSyncableService::ProcessSyncItemSpecifics(
     if (sync_item->item_type == specifics.item_type()) {
       UpdateSyncItemFromSync(specifics, sync_item);
       ProcessExistingSyncItem(sync_item);
-      DVLOG(2) << this << " <- SYNC UPDATE: " << sync_item->ToString();
+      VLOG(2) << this << " <- SYNC UPDATE: " << sync_item->ToString();
       return false;
     }
     // Otherwise, one of the entries should be TYPE_REMOVE_DEFAULT_APP.
@@ -612,8 +631,8 @@ bool AppListSyncableService::ProcessSyncItemSpecifics(
                  << " Deleting item from model!";
       model_->DeleteItem(item_id);
     }
-    DVLOG(2) << this << " - ProcessSyncItem: Delete existing entry: "
-             << sync_item->ToString();
+    VLOG(2) << this << " - ProcessSyncItem: Delete existing entry: "
+            << sync_item->ToString();
     delete sync_item;
     sync_items_.erase(item_id);
   }
@@ -621,12 +640,12 @@ bool AppListSyncableService::ProcessSyncItemSpecifics(
   sync_item = CreateSyncItem(item_id, specifics.item_type());
   UpdateSyncItemFromSync(specifics, sync_item);
   ProcessNewSyncItem(sync_item);
-  DVLOG(2) << this << " <- SYNC ADD: " << sync_item->ToString();
+  VLOG(2) << this << " <- SYNC ADD: " << sync_item->ToString();
   return true;
 }
 
 void AppListSyncableService::ProcessNewSyncItem(SyncItem* sync_item) {
-  DVLOG(2) << "ProcessNewSyncItem: " << sync_item->ToString();
+  VLOG(2) << "ProcessNewSyncItem: " << sync_item->ToString();
   switch (sync_item->item_type) {
     case sync_pb::AppListSpecifics::TYPE_APP: {
       // New apps are added through ExtensionAppModelBuilder.
@@ -635,7 +654,7 @@ void AppListSyncableService::ProcessNewSyncItem(SyncItem* sync_item) {
       return;
     }
     case sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP: {
-      DVLOG(1) << this << ": Uninstall: " << sync_item->ToString();
+      VLOG(1) << this << ": Uninstall: " << sync_item->ToString();
       UninstallExtension(extension_system_->extension_service(),
                          sync_item->item_id);
       return;
@@ -661,7 +680,7 @@ void AppListSyncableService::ProcessExistingSyncItem(SyncItem* sync_item) {
       sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP) {
     return;
   }
-  DVLOG(2) << "ProcessExistingSyncItem: " << sync_item->ToString();
+  VLOG(2) << "ProcessExistingSyncItem: " << sync_item->ToString();
   AppListItem* app_item = model_->FindItem(sync_item->item_id);
   DVLOG(2) << " AppItem: " << app_item->ToDebugString();
   if (!app_item) {
@@ -681,6 +700,7 @@ void AppListSyncableService::ProcessExistingSyncItem(SyncItem* sync_item) {
 void AppListSyncableService::UpdateAppItemFromSyncItem(
     const AppListSyncableService::SyncItem* sync_item,
     AppListItem* app_item) {
+  VLOG(2) << this << "UpdateAppItemFromSyncItem: " << sync_item->ToString();
   if (!app_item->position().Equals(sync_item->item_ordinal))
     model_->SetItemPosition(app_item, sync_item->item_ordinal);
   // Only update the item name if it is a Folder or the name is empty.
@@ -696,7 +716,7 @@ bool AppListSyncableService::SyncStarted() {
   if (sync_processor_.get())
     return true;
   if (flare_.is_null()) {
-    DVLOG(2) << this << ": SyncStarted: Flare.";
+    VLOG(1) << this << ": SyncStarted: Flare.";
     flare_ = sync_start_util::GetFlareForSyncableService(profile_->GetPath());
     flare_.Run(syncer::APP_LIST);
   }
@@ -712,9 +732,9 @@ void AppListSyncableService::SendSyncChange(
     return;
   }
   if (sync_change_type == SyncChange::ACTION_ADD)
-    DVLOG(2) << this << " -> SYNC ADD: " << sync_item->ToString();
+    VLOG(2) << this << " -> SYNC ADD: " << sync_item->ToString();
   else
-    DVLOG(2) << this << " -> SYNC UPDATE: " << sync_item->ToString();
+    VLOG(2) << this << " -> SYNC UPDATE: " << sync_item->ToString();
   SyncChange sync_change(FROM_HERE, sync_change_type,
                          GetSyncDataFromSyncItem(sync_item));
   sync_processor_->ProcessSyncChanges(
@@ -746,13 +766,13 @@ void AppListSyncableService::DeleteSyncItemSpecifics(
     LOG(ERROR) << "Delete AppList item with empty ID";
     return;
   }
-  DVLOG(2) << this << ": DeleteSyncItemSpecifics: " << item_id.substr(0, 8);
+  VLOG(2) << this << ": DeleteSyncItemSpecifics: " << 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();
+  VLOG(2) << this << " <- SYNC DELETE: " << iter->second->ToString();
   delete iter->second;
   sync_items_.erase(iter);
   // Only delete apps from the model. Folders will be deleted when all