blob: 72234f5f2382d92c93fa8a56278d6bcf45a5b389 [file] [log] [blame]
// Copyright (c) 2012 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.
#ifndef COMPONENTS_SYNC_BOOKMARKS_BOOKMARK_CHANGE_PROCESSOR_H_
#define COMPONENTS_SYNC_BOOKMARKS_BOOKMARK_CHANGE_PROCESSOR_H_
#include <stdint.h>
#include <memory>
#include <set>
#include <vector>
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/sequence_checker.h"
#include "components/bookmarks/browser/bookmark_model_observer.h"
#include "components/bookmarks/browser/bookmark_node.h"
#include "components/sync/model/change_processor.h"
#include "components/sync/model/data_type_error_handler.h"
#include "components/sync_bookmarks/bookmark_model_associator.h"
namespace base {
class RefCountedMemory;
} // namespace base
namespace syncer {
class SyncClient;
class WriteNode;
class WriteTransaction;
} // namespace syncer
namespace sync_bookmarks {
// This class is responsible for taking changes from the BookmarkModel
// and applying them to the sync API 'syncable' model, and vice versa.
// All operations and use of this class are from the UI thread.
// This is currently bookmarks specific.
class BookmarkChangeProcessor : public bookmarks::BookmarkModelObserver,
public syncer::ChangeProcessor {
public:
BookmarkChangeProcessor(
syncer::SyncClient* sync_client,
BookmarkModelAssociator* model_associator,
std::unique_ptr<syncer::DataTypeErrorHandler> error_handler);
~BookmarkChangeProcessor() override;
// bookmarks::BookmarkModelObserver:
// BookmarkModel -> sync API model change application.
void BookmarkModelLoaded(bookmarks::BookmarkModel* model,
bool ids_reassigned) override;
void BookmarkModelBeingDeleted(bookmarks::BookmarkModel* model) override;
void BookmarkNodeMoved(bookmarks::BookmarkModel* model,
const bookmarks::BookmarkNode* old_parent,
int old_index,
const bookmarks::BookmarkNode* new_parent,
int new_index) override;
void BookmarkNodeAdded(bookmarks::BookmarkModel* model,
const bookmarks::BookmarkNode* parent,
int index) override;
void OnWillRemoveBookmarks(bookmarks::BookmarkModel* model,
const bookmarks::BookmarkNode* parent,
int old_index,
const bookmarks::BookmarkNode* node) override;
void BookmarkNodeRemoved(bookmarks::BookmarkModel* model,
const bookmarks::BookmarkNode* parent,
int old_index,
const bookmarks::BookmarkNode* node,
const std::set<GURL>& no_longer_bookmarked) override;
void BookmarkAllUserNodesRemoved(bookmarks::BookmarkModel* model,
const std::set<GURL>& removed_urls) override;
void BookmarkNodeChanged(bookmarks::BookmarkModel* model,
const bookmarks::BookmarkNode* node) override;
void BookmarkMetaInfoChanged(bookmarks::BookmarkModel* model,
const bookmarks::BookmarkNode* node) override;
void BookmarkNodeFaviconChanged(bookmarks::BookmarkModel* model,
const bookmarks::BookmarkNode* node) override;
void BookmarkNodeChildrenReordered(
bookmarks::BookmarkModel* model,
const bookmarks::BookmarkNode* node) override;
// The change processor implementation, responsible for applying changes from
// the sync model to the bookmarks model.
void ApplyChangesFromSyncModel(
const syncer::BaseTransaction* trans,
int64_t model_version,
const syncer::ImmutableChangeRecordList& changes) override;
// The following methods are static and hence may be invoked at any time, and
// do not depend on having a running ChangeProcessor.
// TODO(stanisc): considier refactoring these methods out of this class.
// Updates the title, URL, creation time and favicon of the bookmark |node|
// with data taken from the |sync_node| sync node.
static void UpdateBookmarkWithSyncData(const syncer::BaseNode& sync_node,
bookmarks::BookmarkModel* model,
const bookmarks::BookmarkNode* node,
syncer::SyncClient* sync_client);
// Creates a bookmark node under the given parent node from the given sync
// node. Returns the newly created node. The created node is placed at the
// specified index among the parent's children.
static const bookmarks::BookmarkNode* CreateBookmarkNode(
const syncer::BaseNode* sync_node,
const bookmarks::BookmarkNode* parent,
bookmarks::BookmarkModel* model,
syncer::SyncClient* sync_client,
int index);
// Overload of CreateBookmarkNode function above that helps to avoid
// converting / parsing the bookmark title and URL multiple times.
static const bookmarks::BookmarkNode* CreateBookmarkNode(
const base::string16& title,
const GURL& url,
const syncer::BaseNode* sync_node,
const bookmarks::BookmarkNode* parent,
bookmarks::BookmarkModel* model,
syncer::SyncClient* sync_client,
int index);
// Sets the favicon of the given bookmark node from the given sync node.
static void SetBookmarkFavicon(const syncer::BaseNode* sync_node,
const bookmarks::BookmarkNode* bookmark_node,
syncer::SyncClient* sync_client);
// Applies the 1x favicon |bitmap_data| and |icon_url| to |bookmark_node|.
// |profile| is the profile that contains the HistoryService and BookmarkModel
// for the bookmark in question.
static void ApplyBookmarkFavicon(
const bookmarks::BookmarkNode* bookmark_node,
syncer::SyncClient* sync_client,
const GURL& icon_url,
const scoped_refptr<base::RefCountedMemory>& bitmap_data);
// Sets the favicon of the given sync node from the given bookmark node.
static void SetSyncNodeFavicon(const bookmarks::BookmarkNode* bookmark_node,
bookmarks::BookmarkModel* model,
syncer::WriteNode* sync_node);
// Treat the |index|th child of |parent| as a newly added node, and create a
// corresponding node in the sync domain using |trans|. All properties
// will be transferred to the new node. A node corresponding to |parent|
// must already exist and be associated for this call to succeed. Returns
// the ID of the just-created node, or if creation fails, kInvalidID.
static int64_t CreateSyncNode(const bookmarks::BookmarkNode* parent,
bookmarks::BookmarkModel* model,
int index,
syncer::WriteTransaction* trans,
BookmarkModelAssociator* associator,
syncer::DataTypeErrorHandler* error_handler);
// Update |bookmark_node|'s sync node.
static int64_t UpdateSyncNode(const bookmarks::BookmarkNode* bookmark_node,
bookmarks::BookmarkModel* model,
syncer::WriteTransaction* trans,
BookmarkModelAssociator* associator,
syncer::DataTypeErrorHandler* error_handler);
// Tombstone |topmost_sync_node| node and all its children in the sync domain
// using transaction |trans|. Returns the number of removed nodes.
static int RemoveSyncNodeHierarchy(syncer::WriteTransaction* trans,
syncer::WriteNode* topmost_sync_node,
BookmarkModelAssociator* associator);
// Update transaction version of |model| and |nodes| to |new_version| if
// it's valid.
static void UpdateTransactionVersion(
int64_t new_version,
bookmarks::BookmarkModel* model,
const std::vector<const bookmarks::BookmarkNode*>& nodes);
protected:
void StartImpl() override;
private:
enum MoveOrCreate {
MOVE,
CREATE,
};
// Retrieves the meta info from the given sync node.
static std::unique_ptr<bookmarks::BookmarkNode::MetaInfoMap>
GetBookmarkMetaInfo(const syncer::BaseNode* sync_node);
// Sets the meta info of the given sync node from the given bookmark node.
static void SetSyncNodeMetaInfo(const bookmarks::BookmarkNode* node,
syncer::WriteNode* sync_node);
// Helper function used to fix the position of a sync node so that it matches
// the position of a corresponding bookmark model node. |parent| and
// |index| identify the bookmark model position. |dst| is the node whose
// position is to be fixed. If |operation| is CREATE, treat |dst| as an
// uncreated node and set its position via InitByCreation(); otherwise,
// |dst| is treated as an existing node, and its position will be set via
// SetPosition(). |trans| is the transaction to which |dst| belongs. Returns
// false on failure.
static bool PlaceSyncNode(MoveOrCreate operation,
const bookmarks::BookmarkNode* parent,
int index,
syncer::WriteTransaction* trans,
syncer::WriteNode* dst,
BookmarkModelAssociator* associator);
// Copy properties (but not position) from |src| to |dst|.
static void UpdateSyncNodeProperties(
const bookmarks::BookmarkNode* src,
bookmarks::BookmarkModel* model,
syncer::WriteNode* dst,
syncer::DataTypeErrorHandler* error_handler);
// Helper function to encode a bookmark's favicon into raw PNG data.
static void EncodeFavicon(const bookmarks::BookmarkNode* src,
bookmarks::BookmarkModel* model,
scoped_refptr<base::RefCountedMemory>* dst);
// Remove all sync nodes, except the permanent nodes.
void RemoveAllSyncNodes();
// Remove all the sync nodes associated with |node| and its children.
void RemoveSyncNodeHierarchy(const bookmarks::BookmarkNode* node);
// Remove all children of |sync_node|. Returns the number of removed
// children.
static int RemoveAllChildNodes(syncer::WriteTransaction* trans,
int64_t sync_id,
BookmarkModelAssociator* associator);
// Remove |sync_node|. It should not have any children.
static void RemoveOneSyncNode(syncer::WriteNode* sync_node,
BookmarkModelAssociator* associator);
// Creates or updates a sync node associated with |node|.
void CreateOrUpdateSyncNode(const bookmarks::BookmarkNode* node);
// Returns false if |node| should not be synced.
bool CanSyncNode(const bookmarks::BookmarkNode* node);
SEQUENCE_CHECKER(sequence_checker_);
// The bookmark model we are processing changes from. Non-null when
// |running_| is true.
bookmarks::BookmarkModel* bookmark_model_;
syncer::SyncClient* sync_client_;
// The two models should be associated according to this ModelAssociator.
BookmarkModelAssociator* model_associator_;
DISALLOW_COPY_AND_ASSIGN(BookmarkChangeProcessor);
};
} // namespace sync_bookmarks
#endif // COMPONENTS_SYNC_BOOKMARKS_BOOKMARK_CHANGE_PROCESSOR_H_