blob: 7b5a929b86059814f690b695371b6f2c9e43e9ad [file] [log] [blame]
// Copyright 2013 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 <map>
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/sync/glue/sync_start_util.h"
#include "components/keyed_service/core/keyed_service.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "sync/api/string_ordinal.h"
#include "sync/api/sync_change.h"
#include "sync/api/sync_change_processor.h"
#include "sync/api/sync_error_factory.h"
#include "sync/api/syncable_service.h"
#include "sync/protocol/app_list_specifics.pb.h"
class DriveAppProvider;
class ExtensionAppModelBuilder;
class Profile;
namespace extensions {
class ExtensionSystem;
namespace sync_pb {
class AppListSpecifics;
namespace app_list {
class AppListFolderItem;
class AppListItem;
class AppListModel;
// Keyed Service that owns, stores, and syncs an AppListModel for a profile.
class AppListSyncableService : public syncer::SyncableService,
public KeyedService,
public content::NotificationObserver {
struct SyncItem {
SyncItem(const std::string& id,
sync_pb::AppListSpecifics::AppListItemType type);
const std::string item_id;
sync_pb::AppListSpecifics::AppListItemType item_type;
std::string item_name;
std::string parent_id;
syncer::StringOrdinal page_ordinal;
syncer::StringOrdinal item_ordinal;
std::string ToString() const;
// Populates the model when |extension_system| is ready.
AppListSyncableService(Profile* profile,
extensions::ExtensionSystem* extension_system);
virtual ~AppListSyncableService();
// Adds |item| to |sync_items_| and |model_|. If a sync item already exists,
// updates the existing sync item instead.
void AddItem(scoped_ptr<AppListItem> app_item);
// Removes sync item matching |id|.
void RemoveItem(const std::string& id);
// Called when properties of an item may have changed, e.g. default/oem state.
void UpdateItem(AppListItem* app_item);
// Returns the existing sync item matching |id| or NULL.
const SyncItem* GetSyncItem(const std::string& id) const;
// Sets the name of the folder for OEM apps.
void SetOemFolderName(const std::string& name);
Profile* profile() { return profile_; }
AppListModel* model() { return model_.get(); }
size_t GetNumSyncItemsForTest() const { return sync_items_.size(); }
const std::string& GetOemFolderNameForTest() const {
return oem_folder_name_;
// syncer::SyncableService
virtual syncer::SyncMergeResult MergeDataAndStartSyncing(
syncer::ModelType type,
const syncer::SyncDataList& initial_sync_data,
scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
scoped_ptr<syncer::SyncErrorFactory> error_handler) OVERRIDE;
virtual void StopSyncing(syncer::ModelType type) OVERRIDE;
virtual syncer::SyncDataList GetAllSyncData(
syncer::ModelType type) const OVERRIDE;
virtual syncer::SyncError ProcessSyncChanges(
const tracked_objects::Location& from_here,
const syncer::SyncChangeList& change_list) OVERRIDE;
class ModelObserver;
typedef std::map<std::string, SyncItem*> SyncItemMap;
// KeyedService
virtual void Shutdown() OVERRIDE;
// content::NotificationObserver
virtual void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE;
// Builds the model once ExtensionService is ready.
void BuildModel();
// Returns true if sync has restarted, otherwise runs |flare_|.
bool SyncStarted();
// If |app_item| matches an existing sync item, returns it. Otherwise adds
// |app_item| to |sync_items_| and returns the new item. If |app_item| is
// invalid returns NULL.
SyncItem* FindOrAddSyncItem(AppListItem* app_item);
// Creates a sync item for |app_item| and sends an ADD SyncChange event.
SyncItem* CreateSyncItemFromAppItem(AppListItem* app_item);
// If a sync item for |app_item| already exists, update |app_item| from the
// sync item, otherwise create a new sync item from |app_item|.
void AddOrUpdateFromSyncItem(AppListItem* app_item);
// Either uninstalling a default app or remove the REMOVE_DEFAULT sync item.
// Returns true if the app is removed. Otherwise deletes the existing sync
// item and returns false.
bool RemoveDefaultApp(AppListItem* item, SyncItem* sync_item);
// Deletes a sync item from |sync_items_| and sends a DELETE action.
void DeleteSyncItem(SyncItem* sync_item);
// Updates existing entry in |sync_items_| from |app_item|.
void UpdateSyncItem(AppListItem* app_item);
// Removes sync item matching |id|.
void RemoveSyncItem(const std::string& id);
// Updates folder items that may get created during initial sync.
void ResolveFolderPositions();
// Removes any empty SyncItem folders and deletes them from sync. Called
// after a sync item is removed (which may result in an empty folder).
void PruneEmptySyncFolders();
// Creates or updates a SyncItem from |specifics|. Returns true if a new item
// was created.
bool ProcessSyncItemSpecifics(const sync_pb::AppListSpecifics& specifics);
// Handles a newly created sync item (e.g. creates a new AppItem and adds it
// to the model or uninstalls a deleted default item.
void ProcessNewSyncItem(SyncItem* sync_item);
// Handles an existing sync item.
void ProcessExistingSyncItem(SyncItem* sync_item);
// Updates |app_item| from |sync_item| (e.g. updates item positions).
void UpdateAppItemFromSyncItem(const SyncItem* sync_item,
AppListItem* app_item);
// Sends ADD or CHANGED for sync item.
void SendSyncChange(SyncItem* sync_item,
syncer::SyncChange::SyncChangeType sync_change_type);
// Returns an existing SyncItem corresponding to |item_id| or NULL.
SyncItem* FindSyncItem(const std::string& item_id);
// Creates a new sync item for |item_id|.
SyncItem* CreateSyncItem(
const std::string& item_id,
sync_pb::AppListSpecifics::AppListItemType item_type);
// Deletes a SyncItem matching |specifics|.
void DeleteSyncItemSpecifics(const sync_pb::AppListSpecifics& specifics);
// Creates the OEM folder and sets its name if necessary. Returns the OEM
// folder id or an empty string if the folder can not be created. |item_id|
// is the item that needs to be placed in the folder, used only for tracking
// if the folder can not be created.
std::string FindOrCreateOemFolder(const std::string& item_id);
// Gets the location for the OEM folder. Called when the folder is first
// created.
syncer::StringOrdinal GetOemFolderPos();
// Returns true if an extension matching |id| exists and was installed by
// an OEM (extension->was_installed_by_oem() is true).
bool AppIsOem(const std::string& id);
Profile* profile_;
extensions::ExtensionSystem* extension_system_;
content::NotificationRegistrar registrar_;
scoped_ptr<AppListModel> model_;
scoped_ptr<ModelObserver> model_observer_;
scoped_ptr<ExtensionAppModelBuilder> apps_builder_;
scoped_ptr<syncer::SyncChangeProcessor> sync_processor_;
scoped_ptr<syncer::SyncErrorFactory> sync_error_handler_;
SyncItemMap sync_items_;
syncer::SyncableService::StartSyncFlare flare_;
bool first_app_list_sync_;
std::string oem_folder_name_;
std::vector<std::string> oem_folder_item_ids_;
// Provides integration with Drive apps.
scoped_ptr<DriveAppProvider> drive_app_provider_;
} // namespace app_list