Commit f7a91481 authored by rfevang's avatar rfevang Committed by Commit bot

Only set remote id during url node creation.

Folders should only have their id set by the server, and the clients
should only set the remote id on clips they created themselves.

Additionally, EnhancedBookmarkModel now monitors the remote id field for bookmarks, and initiates a de-duping protocol whenever two (or more) nodes with the same id are detected.
BUG=413876

Review URL: https://codereview.chromium.org/563363002

Cr-Commit-Position: refs/heads/master@{#295790}
parent f75586ad
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
'enhanced_bookmarks/bookmark_server_service.h', 'enhanced_bookmarks/bookmark_server_service.h',
'enhanced_bookmarks/enhanced_bookmark_model.cc', 'enhanced_bookmarks/enhanced_bookmark_model.cc',
'enhanced_bookmarks/enhanced_bookmark_model.h', 'enhanced_bookmarks/enhanced_bookmark_model.h',
'enhanced_bookmarks/enhanced_bookmark_model_observer.h',
'enhanced_bookmarks/enhanced_bookmark_utils.cc', 'enhanced_bookmarks/enhanced_bookmark_utils.cc',
'enhanced_bookmarks/enhanced_bookmark_utils.h', 'enhanced_bookmarks/enhanced_bookmark_utils.h',
'enhanced_bookmarks/image_store.cc', 'enhanced_bookmarks/image_store.cc',
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
#include "components/enhanced_bookmarks/bookmark_server_search_service.h" #include "components/enhanced_bookmarks/bookmark_server_search_service.h"
#include "components/bookmarks/browser/bookmark_model.h"
#include "components/enhanced_bookmarks/enhanced_bookmark_utils.h" #include "components/enhanced_bookmarks/enhanced_bookmark_utils.h"
#include "components/enhanced_bookmarks/proto/search.pb.h" #include "components/enhanced_bookmarks/proto/search.pb.h"
#include "net/base/url_util.h" #include "net/base/url_util.h"
...@@ -21,11 +20,11 @@ BookmarkServerSearchService::BookmarkServerSearchService( ...@@ -21,11 +20,11 @@ BookmarkServerSearchService::BookmarkServerSearchService(
scoped_refptr<net::URLRequestContextGetter> request_context_getter, scoped_refptr<net::URLRequestContextGetter> request_context_getter,
ProfileOAuth2TokenService* token_service, ProfileOAuth2TokenService* token_service,
SigninManagerBase* signin_manager, SigninManagerBase* signin_manager,
BookmarkModel* bookmark_model) EnhancedBookmarkModel* enhanced_bookmark_model)
: BookmarkServerService(request_context_getter, : BookmarkServerService(request_context_getter,
token_service, token_service,
signin_manager, signin_manager,
bookmark_model) { enhanced_bookmark_model) {
} }
BookmarkServerSearchService::~BookmarkServerSearchService() { BookmarkServerSearchService::~BookmarkServerSearchService() {
...@@ -99,17 +98,19 @@ void BookmarkServerSearchService::CleanAfterFailure() { ...@@ -99,17 +98,19 @@ void BookmarkServerSearchService::CleanAfterFailure() {
searches_.clear(); searches_.clear();
} }
void BookmarkServerSearchService::BookmarkNodeAdded(BookmarkModel* model, void BookmarkServerSearchService::EnhancedBookmarkAdded(
const BookmarkNode* parent, const BookmarkNode* node) {
int index) {
BookmarkServerService::BookmarkNodeAdded(model, parent, index);
searches_.clear(); searches_.clear();
} }
void BookmarkServerSearchService::BookmarkMetaInfoChanged( void BookmarkServerSearchService::EnhancedBookmarkAllUserNodesRemoved() {
BookmarkModel* model, searches_.clear();
const BookmarkNode* node) { }
BookmarkServerService::BookmarkMetaInfoChanged(model, node);
void BookmarkServerSearchService::EnhancedBookmarkRemoteIdChanged(
const BookmarkNode* node,
const std::string& old_remote_id,
const std::string& remote_id) {
searches_.clear(); searches_.clear();
} }
} // namespace enhanced_bookmarks } // namespace enhanced_bookmarks
...@@ -8,13 +8,14 @@ ...@@ -8,13 +8,14 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "components/bookmarks/browser/base_bookmark_model_observer.h"
#include "components/enhanced_bookmarks/bookmark_server_service.h" #include "components/enhanced_bookmarks/bookmark_server_service.h"
#include "net/url_request/url_fetcher.h" #include "net/url_request/url_fetcher.h"
class BookmarkModel;
namespace enhanced_bookmarks { namespace enhanced_bookmarks {
class EnhancedBookmarkModel;
// Sends requests to the bookmark server to search for bookmarks relevant to a // Sends requests to the bookmark server to search for bookmarks relevant to a
// given query. Will handle one outgoing request at a time. // given query. Will handle one outgoing request at a time.
class BookmarkServerSearchService : public BookmarkServerService { class BookmarkServerSearchService : public BookmarkServerService {
...@@ -23,7 +24,7 @@ class BookmarkServerSearchService : public BookmarkServerService { ...@@ -23,7 +24,7 @@ class BookmarkServerSearchService : public BookmarkServerService {
scoped_refptr<net::URLRequestContextGetter> request_context_getter, scoped_refptr<net::URLRequestContextGetter> request_context_getter,
ProfileOAuth2TokenService* token_service, ProfileOAuth2TokenService* token_service,
SigninManagerBase* signin_manager, SigninManagerBase* signin_manager,
BookmarkModel* bookmark_model); EnhancedBookmarkModel* bookmark_model);
virtual ~BookmarkServerSearchService(); virtual ~BookmarkServerSearchService();
// Triggers a search. The query must not be empty. A call to this method // Triggers a search. The query must not be empty. A call to this method
...@@ -45,12 +46,15 @@ class BookmarkServerSearchService : public BookmarkServerService { ...@@ -45,12 +46,15 @@ class BookmarkServerSearchService : public BookmarkServerService {
virtual void CleanAfterFailure() OVERRIDE; virtual void CleanAfterFailure() OVERRIDE;
// BookmarkModelObserver methods. // EnhancedBookmarkModelObserver methods.
virtual void BookmarkNodeAdded(BookmarkModel* model, virtual void EnhancedBookmarkModelLoaded() OVERRIDE{};
const BookmarkNode* parent, virtual void EnhancedBookmarkAdded(const BookmarkNode* node) OVERRIDE;
int index) OVERRIDE; virtual void EnhancedBookmarkRemoved(const BookmarkNode* node) OVERRIDE{};
virtual void BookmarkMetaInfoChanged(BookmarkModel* model, virtual void EnhancedBookmarkAllUserNodesRemoved() OVERRIDE;
const BookmarkNode* node) OVERRIDE; virtual void EnhancedBookmarkRemoteIdChanged(
const BookmarkNode* node,
const std::string& old_remote_id,
const std::string& remote_id) OVERRIDE;
private: private:
// The search data, a map from query to a vector of stars.id. // The search data, a map from query to a vector of stars.id.
......
...@@ -5,9 +5,7 @@ ...@@ -5,9 +5,7 @@
#include "components/enhanced_bookmarks/bookmark_server_service.h" #include "components/enhanced_bookmarks/bookmark_server_service.h"
#include "base/auto_reset.h" #include "base/auto_reset.h"
#include "components/bookmarks/browser/bookmark_model.h" #include "components/enhanced_bookmarks/enhanced_bookmark_model.h"
#include "components/bookmarks/browser/bookmark_model_observer.h"
#include "components/enhanced_bookmarks/metadata_accessor.h"
#include "components/signin/core/browser/profile_oauth2_token_service.h" #include "components/signin/core/browser/profile_oauth2_token_service.h"
#include "components/signin/core/browser/signin_manager_base.h" #include "components/signin/core/browser/signin_manager_base.h"
#include "google_apis/gaia/gaia_constants.h" #include "google_apis/gaia/gaia_constants.h"
...@@ -21,24 +19,21 @@ BookmarkServerService::BookmarkServerService( ...@@ -21,24 +19,21 @@ BookmarkServerService::BookmarkServerService(
scoped_refptr<net::URLRequestContextGetter> request_context_getter, scoped_refptr<net::URLRequestContextGetter> request_context_getter,
ProfileOAuth2TokenService* token_service, ProfileOAuth2TokenService* token_service,
SigninManagerBase* signin_manager, SigninManagerBase* signin_manager,
BookmarkModel* bookmark_model) EnhancedBookmarkModel* enhanced_bookmark_model)
: OAuth2TokenService::Consumer("bookmark_server_service"), : OAuth2TokenService::Consumer("bookmark_server_service"),
bookmark_model_(bookmark_model), model_(enhanced_bookmark_model),
token_service_(token_service), token_service_(token_service),
signin_manager_(signin_manager), signin_manager_(signin_manager),
request_context_getter_(request_context_getter), request_context_getter_(request_context_getter) {
inhibit_change_notifications_(false) {
DCHECK(request_context_getter.get()); DCHECK(request_context_getter.get());
DCHECK(token_service); DCHECK(token_service);
DCHECK(signin_manager); DCHECK(signin_manager);
DCHECK(bookmark_model); DCHECK(enhanced_bookmark_model);
bookmark_model_->AddObserver(this); model_->AddObserver(this);
if (bookmark_model_->loaded())
BuildIdMap();
} }
BookmarkServerService::~BookmarkServerService() { BookmarkServerService::~BookmarkServerService() {
bookmark_model_->RemoveObserver(this); model_->RemoveObserver(this);
} }
void BookmarkServerService::AddObserver( void BookmarkServerService::AddObserver(
...@@ -51,23 +46,6 @@ void BookmarkServerService::RemoveObserver( ...@@ -51,23 +46,6 @@ void BookmarkServerService::RemoveObserver(
observers_.RemoveObserver(observer); observers_.RemoveObserver(observer);
} }
void BookmarkServerService::BuildIdMap() {
ui::TreeNodeIterator<const BookmarkNode> iterator(
bookmark_model_->root_node());
while (iterator.has_next()) {
const BookmarkNode* bookmark = iterator.Next();
if (bookmark_model_->is_permanent_node(bookmark))
continue;
// RemoteIdFromBookmark() will create the ID if it doesn't exists yet.
std::string starid =
enhanced_bookmarks::RemoteIdFromBookmark(bookmark_model_, bookmark);
if (bookmark->is_url()) {
starsid_to_bookmark_[starid] = bookmark;
}
}
}
const BookmarkNode* BookmarkServerService::BookmarkForRemoteId( const BookmarkNode* BookmarkServerService::BookmarkForRemoteId(
const std::string& remote_id) const { const std::string& remote_id) const {
std::map<std::string, const BookmarkNode*>::const_iterator it = std::map<std::string, const BookmarkNode*>::const_iterator it =
...@@ -79,7 +57,7 @@ const BookmarkNode* BookmarkServerService::BookmarkForRemoteId( ...@@ -79,7 +57,7 @@ const BookmarkNode* BookmarkServerService::BookmarkForRemoteId(
const std::string BookmarkServerService::RemoteIDForBookmark( const std::string BookmarkServerService::RemoteIDForBookmark(
const BookmarkNode* bookmark) const { const BookmarkNode* bookmark) const {
return enhanced_bookmarks::RemoteIdFromBookmark(bookmark_model_, bookmark); return model_->GetRemoteId(bookmark);
} }
void BookmarkServerService::Notify() { void BookmarkServerService::Notify() {
...@@ -165,66 +143,8 @@ void BookmarkServerService::OnURLFetchComplete(const net::URLFetcher* source) { ...@@ -165,66 +143,8 @@ void BookmarkServerService::OnURLFetchComplete(const net::URLFetcher* source) {
Notify(); Notify();
} }
// void BookmarkServerService::EnhancedBookmarkModelShuttingDown() {
// BookmarkModelObserver methods. NOTREACHED();
//
void BookmarkServerService::BookmarkModelLoaded(BookmarkModel* model,
bool ids_reassigned) {
BuildIdMap();
}
void BookmarkServerService::BookmarkNodeAdded(BookmarkModel* model,
const BookmarkNode* parent,
int index) {
DCHECK(!inhibit_change_notifications_);
const BookmarkNode* bookmark = parent->GetChild(index);
if (!bookmark->is_url())
return;
base::AutoReset<bool> inhibitor(&inhibit_change_notifications_, true);
std::string starid =
enhanced_bookmarks::RemoteIdFromBookmark(model, bookmark);
starsid_to_bookmark_[starid] = bookmark;
}
void BookmarkServerService::BookmarkNodeRemoved(
BookmarkModel* model,
const BookmarkNode* parent,
int old_index,
const BookmarkNode* node,
const std::set<GURL>& removed_urls) {
DCHECK(!inhibit_change_notifications_);
if (!node->is_url())
return;
base::AutoReset<bool> inhibitor(&inhibit_change_notifications_, true);
std::string starid = enhanced_bookmarks::RemoteIdFromBookmark(model, node);
starsid_to_bookmark_.erase(starid);
}
void BookmarkServerService::OnWillChangeBookmarkMetaInfo(
BookmarkModel* model,
const BookmarkNode* node) {
if (!node->is_url() || inhibit_change_notifications_)
return;
base::AutoReset<bool> inhibitor(&inhibit_change_notifications_, true);
std::string starid = enhanced_bookmarks::RemoteIdFromBookmark(model, node);
starsid_to_bookmark_.erase(starid);
}
void BookmarkServerService::BookmarkMetaInfoChanged(BookmarkModel* model,
const BookmarkNode* node) {
if (!node->is_url() || inhibit_change_notifications_)
return;
std::string starid = enhanced_bookmarks::RemoteIdFromBookmark(model, node);
starsid_to_bookmark_[starid] = node;
}
void BookmarkServerService::BookmarkAllUserNodesRemoved(
BookmarkModel* model,
const std::set<GURL>& removed_urls) {
DCHECK(!inhibit_change_notifications_);
starsid_to_bookmark_.clear();
} }
SigninManagerBase* BookmarkServerService::GetSigninManager() { SigninManagerBase* BookmarkServerService::GetSigninManager() {
......
...@@ -8,20 +8,21 @@ ...@@ -8,20 +8,21 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "components/bookmarks/browser/bookmark_model_observer.h" #include "components/enhanced_bookmarks/enhanced_bookmark_model_observer.h"
#include "google_apis/gaia/google_service_auth_error.h" #include "google_apis/gaia/google_service_auth_error.h"
#include "google_apis/gaia/oauth2_token_service.h" #include "google_apis/gaia/oauth2_token_service.h"
#include "net/url_request/url_fetcher.h" #include "net/url_request/url_fetcher.h"
#include "net/url_request/url_fetcher_delegate.h" #include "net/url_request/url_fetcher_delegate.h"
#include "net/url_request/url_request_context_getter.h" #include "net/url_request/url_request_context_getter.h"
class BookmarkModel;
class ProfileOAuth2TokenService; class ProfileOAuth2TokenService;
class SigninManagerBase; class SigninManagerBase;
class BookmarkNode;
namespace enhanced_bookmarks { namespace enhanced_bookmarks {
class BookmarkServerService; class BookmarkServerService;
class EnhancedBookmarkModel;
class BookmarkServerServiceObserver { class BookmarkServerServiceObserver {
public: public:
...@@ -36,14 +37,14 @@ class BookmarkServerServiceObserver { ...@@ -36,14 +37,14 @@ class BookmarkServerServiceObserver {
// BookmarkNodes. Subclasses just have to provide the right query and the // BookmarkNodes. Subclasses just have to provide the right query and the
// parsing of the response. // parsing of the response.
class BookmarkServerService : protected net::URLFetcherDelegate, class BookmarkServerService : protected net::URLFetcherDelegate,
protected BookmarkModelObserver, private OAuth2TokenService::Consumer,
private OAuth2TokenService::Consumer { public EnhancedBookmarkModelObserver {
public: public:
BookmarkServerService( BookmarkServerService(
scoped_refptr<net::URLRequestContextGetter> request_context_getter, scoped_refptr<net::URLRequestContextGetter> request_context_getter,
ProfileOAuth2TokenService* token_service, ProfileOAuth2TokenService* token_service,
SigninManagerBase* signin_manager, SigninManagerBase* signin_manager,
BookmarkModel* bookmark_model); EnhancedBookmarkModel* enhanced_bookmark_model);
virtual ~BookmarkServerService(); virtual ~BookmarkServerService();
void AddObserver(BookmarkServerServiceObserver* observer); void AddObserver(BookmarkServerServiceObserver* observer);
...@@ -75,52 +76,19 @@ class BookmarkServerService : protected net::URLFetcherDelegate, ...@@ -75,52 +76,19 @@ class BookmarkServerService : protected net::URLFetcherDelegate,
// If the token can't be retrieved or the query fails this method is called. // If the token can't be retrieved or the query fails this method is called.
virtual void CleanAfterFailure() = 0; virtual void CleanAfterFailure() = 0;
// BookmarkModelObserver methods. // EnhancedBookmarkModelObserver:
virtual void BookmarkModelLoaded(BookmarkModel* model, virtual void EnhancedBookmarkModelShuttingDown() OVERRIDE;
bool ids_reassigned) OVERRIDE;
virtual void BookmarkNodeMoved(BookmarkModel* model,
const BookmarkNode* old_parent,
int old_index,
const BookmarkNode* new_parent,
int new_index) OVERRIDE {};
virtual void BookmarkNodeAdded(BookmarkModel* model,
const BookmarkNode* parent,
int index) OVERRIDE;
virtual void BookmarkNodeRemoved(BookmarkModel* model,
const BookmarkNode* parent,
int old_index,
const BookmarkNode* node,
const std::set<GURL>& removed_urls) OVERRIDE;
virtual void BookmarkNodeChanged(BookmarkModel* model,
const BookmarkNode* node) OVERRIDE {};
virtual void OnWillChangeBookmarkMetaInfo(BookmarkModel* model,
const BookmarkNode* node) OVERRIDE;
virtual void BookmarkMetaInfoChanged(BookmarkModel* model,
const BookmarkNode* node) OVERRIDE;
virtual void BookmarkNodeFaviconChanged(BookmarkModel* model,
const BookmarkNode* node) OVERRIDE {};
virtual void BookmarkNodeChildrenReordered(BookmarkModel* model,
const BookmarkNode* node)
OVERRIDE {};
virtual void BookmarkAllUserNodesRemoved(
BookmarkModel* model,
const std::set<GURL>& removed_urls) OVERRIDE;
SigninManagerBase* GetSigninManager(); SigninManagerBase* GetSigninManager();
// Cached pointer to the bookmarks model. // Cached pointer to the bookmarks model.
BookmarkModel* bookmark_model_; // weak EnhancedBookmarkModel* model_; // weak
private: private:
FRIEND_TEST_ALL_PREFIXES(BookmarkServerServiceTest, Cluster); FRIEND_TEST_ALL_PREFIXES(BookmarkServerServiceTest, Cluster);
FRIEND_TEST_ALL_PREFIXES(BookmarkServerServiceTest, FRIEND_TEST_ALL_PREFIXES(BookmarkServerServiceTest,
ClearClusterMapOnRemoveAllBookmarks); ClearClusterMapOnRemoveAllBookmarks);
// Once the model is ready this method fills in the starsid_to_bookmark_ map.
void BuildIdMap();
// net::URLFetcherDelegate methods. Called when the query is finished. // net::URLFetcherDelegate methods. Called when the query is finished.
virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
...@@ -145,9 +113,6 @@ class BookmarkServerService : protected net::URLFetcherDelegate, ...@@ -145,9 +113,6 @@ class BookmarkServerService : protected net::URLFetcherDelegate,
scoped_ptr<net::URLFetcher> url_fetcher_; scoped_ptr<net::URLFetcher> url_fetcher_;
// A map from stars.id to bookmark nodes. With no null entries. // A map from stars.id to bookmark nodes. With no null entries.
std::map<std::string, const BookmarkNode*> starsid_to_bookmark_; std::map<std::string, const BookmarkNode*> starsid_to_bookmark_;
// Set to true during the creation of a new bookmark in order to send only the
// proper notification.
bool inhibit_change_notifications_;
DISALLOW_COPY_AND_ASSIGN(BookmarkServerService); DISALLOW_COPY_AND_ASSIGN(BookmarkServerService);
}; };
......
...@@ -9,10 +9,13 @@ ...@@ -9,10 +9,13 @@
#include "base/base64.h" #include "base/base64.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/rand_util.h" #include "base/rand_util.h"
#include "components/bookmarks/browser/bookmark_model.h" #include "components/bookmarks/browser/bookmark_model.h"
#include "components/bookmarks/browser/bookmark_node.h" #include "components/bookmarks/browser/bookmark_node.h"
#include "components/enhanced_bookmarks/enhanced_bookmark_model_observer.h"
#include "components/enhanced_bookmarks/proto/metadata.pb.h" #include "components/enhanced_bookmarks/proto/metadata.pb.h"
#include "ui/base/models/tree_node_iterator.h"
#include "url/gurl.h" #include "url/gurl.h"
namespace { namespace {
...@@ -21,11 +24,10 @@ const char* kBookmarkBarId = "f_bookmarks_bar"; ...@@ -21,11 +24,10 @@ const char* kBookmarkBarId = "f_bookmarks_bar";
const char* kIdKey = "stars.id"; const char* kIdKey = "stars.id";
const char* kImageDataKey = "stars.imageData"; const char* kImageDataKey = "stars.imageData";
const char* kNoteKey = "stars.note"; const char* kNoteKey = "stars.note";
const char* kOldIdKey = "stars.oldId";
const char* kPageDataKey = "stars.pageData"; const char* kPageDataKey = "stars.pageData";
const char* kUserEditKey = "stars.userEdit";
const char* kVersionKey = "stars.version"; const char* kVersionKey = "stars.version";
const char* kFolderPrefix = "ebf_";
const char* kBookmarkPrefix = "ebc_"; const char* kBookmarkPrefix = "ebc_";
// Helper method for working with bookmark metainfo. // Helper method for working with bookmark metainfo.
...@@ -62,13 +64,9 @@ bool PopulateImageData(const image::collections::ImageData_ImageInfo& info, ...@@ -62,13 +64,9 @@ bool PopulateImageData(const image::collections::ImageData_ImageInfo& info,
// Generate a random remote id, with a prefix that depends on whether the node // Generate a random remote id, with a prefix that depends on whether the node
// is a folder or a bookmark. // is a folder or a bookmark.
std::string GenerateRemoteId(bool is_folder) { std::string GenerateRemoteId() {
std::stringstream random_id; std::stringstream random_id;
// Add prefix depending on whether the node is a folder or not. random_id << kBookmarkPrefix;
if (is_folder)
random_id << kFolderPrefix;
else
random_id << kBookmarkPrefix;
// Generate 32 digit hex string random suffix. // Generate 32 digit hex string random suffix.
random_id << std::hex << std::setfill('0') << std::setw(16); random_id << std::hex << std::setfill('0') << std::setw(16);
...@@ -81,17 +79,43 @@ namespace enhanced_bookmarks { ...@@ -81,17 +79,43 @@ namespace enhanced_bookmarks {
EnhancedBookmarkModel::EnhancedBookmarkModel(BookmarkModel* bookmark_model, EnhancedBookmarkModel::EnhancedBookmarkModel(BookmarkModel* bookmark_model,
const std::string& version) const std::string& version)
: bookmark_model_(bookmark_model), version_(version) { : bookmark_model_(bookmark_model),
loaded_(false),
weak_ptr_factory_(this),
version_(version) {
bookmark_model_->AddObserver(this);
if (bookmark_model_->loaded()) {
InitializeIdMap();
loaded_ = true;
}
} }
EnhancedBookmarkModel::~EnhancedBookmarkModel() { EnhancedBookmarkModel::~EnhancedBookmarkModel() {
} }
void EnhancedBookmarkModel::ShutDown() {
FOR_EACH_OBSERVER(EnhancedBookmarkModelObserver,
observers_,
EnhancedBookmarkModelShuttingDown());
weak_ptr_factory_.InvalidateWeakPtrs();
bookmark_model_->RemoveObserver(this);
bookmark_model_ = NULL;
}
void EnhancedBookmarkModel::AddObserver(
EnhancedBookmarkModelObserver* observer) {
observers_.AddObserver(observer);
}
void EnhancedBookmarkModel::RemoveObserver(
EnhancedBookmarkModelObserver* observer) {
observers_.RemoveObserver(observer);
}
// Moves |node| to |new_parent| and inserts it at the given |index|. // Moves |node| to |new_parent| and inserts it at the given |index|.
void EnhancedBookmarkModel::Move(const BookmarkNode* node, void EnhancedBookmarkModel::Move(const BookmarkNode* node,
const BookmarkNode* new_parent, const BookmarkNode* new_parent,
int index) { int index) {
// TODO(rfevang): Update meta info placement fields.
bookmark_model_->Move(node, new_parent, index); bookmark_model_->Move(node, new_parent, index);
} }
...@@ -100,12 +124,7 @@ const BookmarkNode* EnhancedBookmarkModel::AddFolder( ...@@ -100,12 +124,7 @@ const BookmarkNode* EnhancedBookmarkModel::AddFolder(
const BookmarkNode* parent, const BookmarkNode* parent,
int index, int index,
const base::string16& title) { const base::string16& title) {
BookmarkNode::MetaInfoMap meta_info; return bookmark_model_->AddFolder(parent, index, title);
meta_info[kIdKey] = GenerateRemoteId(true);
// TODO(rfevang): Set meta info placement fields.
return bookmark_model_->AddFolderWithMetaInfo(
parent, index, title, &meta_info);
} }
// Adds a url at the specified position. // Adds a url at the specified position.
...@@ -116,9 +135,7 @@ const BookmarkNode* EnhancedBookmarkModel::AddURL( ...@@ -116,9 +135,7 @@ const BookmarkNode* EnhancedBookmarkModel::AddURL(
const GURL& url, const GURL& url,
const base::Time& creation_time) { const base::Time& creation_time) {
BookmarkNode::MetaInfoMap meta_info; BookmarkNode::MetaInfoMap meta_info;
meta_info[kIdKey] = GenerateRemoteId(false); meta_info[kIdKey] = GenerateRemoteId();
// TODO(rfevang): Set meta info placement fields.
return bookmark_model_->AddURLWithCreationTimeAndMetaInfo( return bookmark_model_->AddURLWithCreationTimeAndMetaInfo(
parent, index, title, url, creation_time, &meta_info); parent, index, title, url, creation_time, &meta_info);
} }
...@@ -127,24 +144,23 @@ std::string EnhancedBookmarkModel::GetRemoteId(const BookmarkNode* node) { ...@@ -127,24 +144,23 @@ std::string EnhancedBookmarkModel::GetRemoteId(const BookmarkNode* node) {
if (node == bookmark_model_->bookmark_bar_node()) if (node == bookmark_model_->bookmark_bar_node())
return kBookmarkBarId; return kBookmarkBarId;
// Permanent nodes other than the bookmarks bar don't have ids.
DCHECK(!bookmark_model_->is_permanent_node(node));
std::string id; std::string id;
if (!node->GetMetaInfo(kIdKey, &id) || id.empty()) if (!node->GetMetaInfo(kIdKey, &id))
return SetRemoteId(node); return std::string();
return id; return id;
} }
std::string EnhancedBookmarkModel::SetRemoteId(const BookmarkNode* node) { const BookmarkNode* EnhancedBookmarkModel::BookmarkForRemoteId(
std::string remote_id = GenerateRemoteId(node->is_folder()); const std::string& remote_id) {
SetMetaInfo(node, kIdKey, remote_id, false); IdToNodeMap::iterator it = id_map_.find(remote_id);
return remote_id; if (it != id_map_.end())
return it->second;
return NULL;
} }
void EnhancedBookmarkModel::SetDescription(const BookmarkNode* node, void EnhancedBookmarkModel::SetDescription(const BookmarkNode* node,
const std::string& description) { const std::string& description) {
SetMetaInfo(node, kNoteKey, description, true); SetMetaInfo(node, kNoteKey, description);
} }
std::string EnhancedBookmarkModel::GetDescription(const BookmarkNode* node) { std::string EnhancedBookmarkModel::GetDescription(const BookmarkNode* node) {
...@@ -189,9 +205,7 @@ bool EnhancedBookmarkModel::SetOriginalImage(const BookmarkNode* node, ...@@ -189,9 +205,7 @@ bool EnhancedBookmarkModel::SetOriginalImage(const BookmarkNode* node,
std::string encoded; std::string encoded;
base::Base64Encode(output, &encoded); base::Base64Encode(output, &encoded);
SetMetaInfo(node, kImageDataKey, encoded, true); SetMetaInfo(node, kImageDataKey, encoded);
// Ensure that the bookmark has a stars.id, to trigger the server processing.
GetRemoteId(node);
return true; return true;
} }
...@@ -251,10 +265,120 @@ void EnhancedBookmarkModel::SetVersionSuffix( ...@@ -251,10 +265,120 @@ void EnhancedBookmarkModel::SetVersionSuffix(
version_suffix_ = version_suffix; version_suffix_ = version_suffix;
} }
void EnhancedBookmarkModel::BookmarkModelChanged() {
}
void EnhancedBookmarkModel::BookmarkModelLoaded(BookmarkModel* model,
bool ids_reassigned) {
InitializeIdMap();
FOR_EACH_OBSERVER(
EnhancedBookmarkModelObserver, observers_, EnhancedBookmarkModelLoaded());
}
void EnhancedBookmarkModel::BookmarkNodeAdded(BookmarkModel* model,
const BookmarkNode* parent,
int index) {
const BookmarkNode* node = parent->GetChild(index);
AddToIdMap(node);
ScheduleResetDuplicateRemoteIds();
FOR_EACH_OBSERVER(
EnhancedBookmarkModelObserver, observers_, EnhancedBookmarkAdded(node));
}
void EnhancedBookmarkModel::BookmarkNodeRemoved(
BookmarkModel* model,
const BookmarkNode* parent,
int old_index,
const BookmarkNode* node,
const std::set<GURL>& removed_urls) {
std::string remote_id = GetRemoteId(node);
id_map_.erase(remote_id);
FOR_EACH_OBSERVER(
EnhancedBookmarkModelObserver, observers_, EnhancedBookmarkRemoved(node));
}
void EnhancedBookmarkModel::OnWillChangeBookmarkMetaInfo(
BookmarkModel* model,
const BookmarkNode* node) {
prev_remote_id_ = GetRemoteId(node);
}
void EnhancedBookmarkModel::BookmarkMetaInfoChanged(BookmarkModel* model,
const BookmarkNode* node) {
std::string remote_id = GetRemoteId(node);
if (remote_id != prev_remote_id_) {
id_map_.erase(prev_remote_id_);
if (!remote_id.empty()) {
AddToIdMap(node);
ScheduleResetDuplicateRemoteIds();
}
FOR_EACH_OBSERVER(
EnhancedBookmarkModelObserver,
observers_,
EnhancedBookmarkRemoteIdChanged(node, prev_remote_id_, remote_id));
}
}
void EnhancedBookmarkModel::BookmarkAllUserNodesRemoved(
BookmarkModel* model,
const std::set<GURL>& removed_urls) {
id_map_.clear();
// Re-initialize so non-user nodes with remote ids are present in the map.
InitializeIdMap();
FOR_EACH_OBSERVER(EnhancedBookmarkModelObserver,
observers_,
EnhancedBookmarkAllUserNodesRemoved());
}
void EnhancedBookmarkModel::InitializeIdMap() {
ui::TreeNodeIterator<const BookmarkNode> iterator(
bookmark_model_->root_node());
while (iterator.has_next()) {
AddToIdMap(iterator.Next());
}
ScheduleResetDuplicateRemoteIds();
}
void EnhancedBookmarkModel::AddToIdMap(const BookmarkNode* node) {
std::string remote_id = GetRemoteId(node);
if (remote_id.empty())
return;
// Try to insert the node.
std::pair<IdToNodeMap::iterator, bool> result =
id_map_.insert(make_pair(remote_id, node));
if (!result.second) {
// Some node already had the same remote id, so add both nodes to the
// to-be-reset set.
nodes_to_reset_[result.first->second] = remote_id;
nodes_to_reset_[node] = remote_id;
}
}
void EnhancedBookmarkModel::ScheduleResetDuplicateRemoteIds() {
if (!nodes_to_reset_.empty()) {
base::MessageLoopProxy::current()->PostTask(
FROM_HERE,
base::Bind(&EnhancedBookmarkModel::ResetDuplicateRemoteIds,
weak_ptr_factory_.GetWeakPtr()));
}
}
void EnhancedBookmarkModel::ResetDuplicateRemoteIds() {
for (NodeToIdMap::iterator it = nodes_to_reset_.begin();
it != nodes_to_reset_.end();
++it) {
BookmarkNode::MetaInfoMap meta_info;
meta_info[kIdKey] = "";
meta_info[kOldIdKey] = it->second;
SetMultipleMetaInfo(it->first, meta_info);
}
nodes_to_reset_.clear();
}
void EnhancedBookmarkModel::SetMetaInfo(const BookmarkNode* node, void EnhancedBookmarkModel::SetMetaInfo(const BookmarkNode* node,
const std::string& field, const std::string& field,
const std::string& value, const std::string& value) {
bool user_edit) {
DCHECK(!bookmark_model_->is_permanent_node(node)); DCHECK(!bookmark_model_->is_permanent_node(node));
BookmarkNode::MetaInfoMap meta_info; BookmarkNode::MetaInfoMap meta_info;
...@@ -269,7 +393,6 @@ void EnhancedBookmarkModel::SetMetaInfo(const BookmarkNode* node, ...@@ -269,7 +393,6 @@ void EnhancedBookmarkModel::SetMetaInfo(const BookmarkNode* node,
meta_info[field] = value; meta_info[field] = value;
meta_info[kVersionKey] = GetVersionString(); meta_info[kVersionKey] = GetVersionString();
meta_info[kUserEditKey] = user_edit ? "true" : "false";
bookmark_model_->SetNodeMetaInfoMap(node, meta_info); bookmark_model_->SetNodeMetaInfoMap(node, meta_info);
} }
...@@ -279,6 +402,37 @@ std::string EnhancedBookmarkModel::GetVersionString() { ...@@ -279,6 +402,37 @@ std::string EnhancedBookmarkModel::GetVersionString() {
return version_ + '/' + version_suffix_; return version_ + '/' + version_suffix_;
} }
void EnhancedBookmarkModel::SetMultipleMetaInfo(
const BookmarkNode* node,
BookmarkNode::MetaInfoMap meta_info) {
DCHECK(!bookmark_model_->is_permanent_node(node));
// Don't update anything if every value is already set correctly.
if (node->GetMetaInfoMap()) {
bool changed = false;
const BookmarkNode::MetaInfoMap* old_meta_info = node->GetMetaInfoMap();
for (BookmarkNode::MetaInfoMap::iterator it = meta_info.begin();
it != meta_info.end();
++it) {
BookmarkNode::MetaInfoMap::const_iterator old_field =
old_meta_info->find(it->first);
if (old_field == old_meta_info->end() ||
old_field->second != it->second) {
changed = true;
break;
}
}
if (!changed)
return;
// Fill in the values that aren't changing
meta_info.insert(old_meta_info->begin(), old_meta_info->end());
}
meta_info[kVersionKey] = GetVersionString();
bookmark_model_->SetNodeMetaInfoMap(node, meta_info);
}
bool EnhancedBookmarkModel::SetAllImages(const BookmarkNode* node, bool EnhancedBookmarkModel::SetAllImages(const BookmarkNode* node,
const GURL& image_url, const GURL& image_url,
int image_width, int image_width,
......
...@@ -5,9 +5,13 @@ ...@@ -5,9 +5,13 @@
#ifndef COMPONENTS_ENHANCED_BOOKMARKS_ENHANCED_BOOKMARK_MODEL_H_ #ifndef COMPONENTS_ENHANCED_BOOKMARKS_ENHANCED_BOOKMARK_MODEL_H_
#define COMPONENTS_ENHANCED_BOOKMARKS_ENHANCED_BOOKMARK_MODEL_H_ #define COMPONENTS_ENHANCED_BOOKMARKS_ENHANCED_BOOKMARK_MODEL_H_
#include <map>
#include <string> #include <string>
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/strings/string16.h" #include "base/strings/string16.h"
#include "components/bookmarks/browser/base_bookmark_model_observer.h"
#include "components/bookmarks/browser/bookmark_node.h" #include "components/bookmarks/browser/bookmark_node.h"
#include "components/keyed_service/core/keyed_service.h" #include "components/keyed_service/core/keyed_service.h"
...@@ -16,17 +20,29 @@ class Time; ...@@ -16,17 +20,29 @@ class Time;
} // namespace base } // namespace base
class BookmarkModel; class BookmarkModel;
class BookmarkNode;
class GURL; class GURL;
FORWARD_DECLARE_TEST(EnhancedBookmarkModelTest, SetMultipleMetaInfo);
namespace enhanced_bookmarks { namespace enhanced_bookmarks {
class EnhancedBookmarkModelObserver;
// Wrapper around BookmarkModel providing utility functions for enhanced // Wrapper around BookmarkModel providing utility functions for enhanced
// bookmarks. // bookmarks.
class EnhancedBookmarkModel : public KeyedService { class EnhancedBookmarkModel : public KeyedService,
public BaseBookmarkModelObserver {
public: public:
EnhancedBookmarkModel(BookmarkModel* bookmark_model, EnhancedBookmarkModel(BookmarkModel* bookmark_model,
const std::string& version); const std::string& version);
virtual ~EnhancedBookmarkModel(); virtual ~EnhancedBookmarkModel();
virtual void ShutDown();
void AddObserver(EnhancedBookmarkModelObserver* observer);
void RemoveObserver(EnhancedBookmarkModelObserver* observer);
// Moves |node| to |new_parent| and inserts it at the given |index|. // Moves |node| to |new_parent| and inserts it at the given |index|.
void Move(const BookmarkNode* node, void Move(const BookmarkNode* node,
const BookmarkNode* new_parent, const BookmarkNode* new_parent,
...@@ -47,6 +63,10 @@ class EnhancedBookmarkModel : public KeyedService { ...@@ -47,6 +63,10 @@ class EnhancedBookmarkModel : public KeyedService {
// Returns the remote id for a bookmark |node|. // Returns the remote id for a bookmark |node|.
std::string GetRemoteId(const BookmarkNode* node); std::string GetRemoteId(const BookmarkNode* node);
// Returns the bookmark node corresponding to the given |remote_id|, or NULL
// if there is no node with the id.
const BookmarkNode* BookmarkForRemoteId(const std::string& remote_id);
// Sets the description of a bookmark |node|. // Sets the description of a bookmark |node|.
void SetDescription(const BookmarkNode* node, const std::string& description); void SetDescription(const BookmarkNode* node, const std::string& description);
...@@ -104,22 +124,77 @@ class EnhancedBookmarkModel : public KeyedService { ...@@ -104,22 +124,77 @@ class EnhancedBookmarkModel : public KeyedService {
// Remove when that is actually the case. // Remove when that is actually the case.
BookmarkModel* bookmark_model() { return bookmark_model_; } BookmarkModel* bookmark_model() { return bookmark_model_; }
// Returns true if the enhanced bookmark model is done loading.
bool loaded() { return loaded_; }
private: private:
// Generates and sets a remote id for the given bookmark |node|. FRIEND_TEST_ALL_PREFIXES(::EnhancedBookmarkModelTest, SetMultipleMetaInfo);
// Returns the id set.
std::string SetRemoteId(const BookmarkNode* node); typedef std::map<std::string, const BookmarkNode*> IdToNodeMap;
typedef std::map<const BookmarkNode*, std::string> NodeToIdMap;
// BaseBookmarkModelObserver:
virtual void BookmarkModelChanged() OVERRIDE;
virtual void BookmarkModelLoaded(BookmarkModel* model,
bool ids_reassigned) OVERRIDE;
virtual void BookmarkNodeAdded(BookmarkModel* model,
const BookmarkNode* parent,
int index) OVERRIDE;
virtual void BookmarkNodeRemoved(BookmarkModel* model,
const BookmarkNode* parent,
int old_index,
const BookmarkNode* node,
const std::set<GURL>& removed_urls) OVERRIDE;
virtual void OnWillChangeBookmarkMetaInfo(BookmarkModel* model,
const BookmarkNode* node) OVERRIDE;
virtual void BookmarkMetaInfoChanged(BookmarkModel* model,
const BookmarkNode* node) OVERRIDE;
virtual void BookmarkAllUserNodesRemoved(
BookmarkModel* model,
const std::set<GURL>& removed_urls) OVERRIDE;
// Initialize the mapping from remote ids to nodes.
void InitializeIdMap();
// Adds a node to the id map if it has a (unique) remote id. Must be followed
// by a (Schedule)ResetDuplicateRemoteIds call when done adding nodes.
void AddToIdMap(const BookmarkNode* node);
// If there are nodes that needs to reset their remote ids, schedules
// ResetDuplicateRemoteIds to be run asynchronously.
void ScheduleResetDuplicateRemoteIds();
// Clears out any duplicate remote ids detected by AddToIdMap calls.
void ResetDuplicateRemoteIds();
// Helper method for setting a meta info field on a node. Also updates the // Helper method for setting a meta info field on a node. Also updates the
// version and userEdits fields. // version field.
void SetMetaInfo(const BookmarkNode* node, void SetMetaInfo(const BookmarkNode* node,
const std::string& field, const std::string& field,
const std::string& value, const std::string& value);
bool user_edit);
// Helper method for setting multiple meta info fields at once. All the fields
// in |meta_info| will be set, but the method will not delete fields not
// present.
void SetMultipleMetaInfo(const BookmarkNode* node,
BookmarkNode::MetaInfoMap meta_info);
// Returns the version string to use when setting stars.version. // Returns the version string to use when setting stars.version.
std::string GetVersionString(); std::string GetVersionString();
BookmarkModel* bookmark_model_; BookmarkModel* bookmark_model_;
bool loaded_;
ObserverList<EnhancedBookmarkModelObserver> observers_;
base::WeakPtrFactory<EnhancedBookmarkModel> weak_ptr_factory_;
IdToNodeMap id_map_;
NodeToIdMap nodes_to_reset_;
// Caches the remote id of a node before its meta info changes.
std::string prev_remote_id_;
std::string version_; std::string version_;
std::string version_suffix_; std::string version_suffix_;
}; };
......
// Copyright 2014 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_ENHANCED_BOOKMARKS_ENHANCED_BOOKMARK_MODEL_OBSERVER_H_
#define COMPONENTS_ENHANCED_BOOKMARKS_ENHANCED_BOOKMARK_MODEL_OBSERVER_H_
#include <string>
class BookmarkNode;
namespace enhanced_bookmarks {
class EnhancedBookmarkModelObserver {
public:
// Called when the model has finished loading.
virtual void EnhancedBookmarkModelLoaded() = 0;
// Called from EnhancedBookmarkModel::ShutDown.
virtual void EnhancedBookmarkModelShuttingDown() = 0;
// Called when a node is added to the model.
virtual void EnhancedBookmarkAdded(const BookmarkNode* node) = 0;
// Called when a node is removed from the model.
virtual void EnhancedBookmarkRemoved(const BookmarkNode* node) = 0;
// Called when all user editable nodes are removed from the model.
virtual void EnhancedBookmarkAllUserNodesRemoved() = 0;
// Called when the remote id of a node changes. If |remote_id| is empty, the
// remote id has been cleared. This could happen if multiple nodes with the
// same remote id has been detected.
virtual void EnhancedBookmarkRemoteIdChanged(const BookmarkNode* node,
const std::string& old_remote_id,
const std::string& remote_id) {};
protected:
virtual ~EnhancedBookmarkModelObserver() {}
};
} // namespace enhanced_bookmarks
#endif // COMPONENTS_ENHANCED_BOOKMARKS_ENHANCED_BOOKMARK_MODEL_OBSERVER_H_
...@@ -7,34 +7,55 @@ ...@@ -7,34 +7,55 @@
#include "base/base64.h" #include "base/base64.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "components/bookmarks/browser/bookmark_model.h" #include "components/bookmarks/browser/bookmark_model.h"
#include "components/bookmarks/browser/bookmark_node.h" #include "components/bookmarks/browser/bookmark_node.h"
#include "components/bookmarks/test/test_bookmark_client.h" #include "components/bookmarks/test/test_bookmark_client.h"
#include "components/enhanced_bookmarks/enhanced_bookmark_model_observer.h"
#include "components/enhanced_bookmarks/proto/metadata.pb.h" #include "components/enhanced_bookmarks/proto/metadata.pb.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h" #include "url/gurl.h"
namespace { using enhanced_bookmarks::EnhancedBookmarkModel;
namespace {
const std::string BOOKMARK_URL("http://example.com/index.html"); const std::string BOOKMARK_URL("http://example.com/index.html");
} // namespace
class EnhancedBookmarkModelTest : public testing::Test { class EnhancedBookmarkModelTest
: public testing::Test,
public enhanced_bookmarks::EnhancedBookmarkModelObserver {
public: public:
EnhancedBookmarkModelTest() {} EnhancedBookmarkModelTest()
: loaded_calls_(0),
shutting_down_calls_(0),
added_calls_(0),
removed_calls_(0),
all_user_nodes_removed_calls_(0),
remote_id_changed_calls_(0),
last_added_(NULL),
last_removed_(NULL),
last_remote_id_node_(NULL) {}
virtual ~EnhancedBookmarkModelTest() {} virtual ~EnhancedBookmarkModelTest() {}
virtual void SetUp() OVERRIDE { virtual void SetUp() OVERRIDE {
bookmarks::TestBookmarkClient bookmark_client; message_loop_.reset(new base::MessageLoop(base::MessageLoop::TYPE_DEFAULT));
bookmark_model_.reset(bookmark_client.CreateModel().release()); bookmark_client_.reset(new bookmarks::TestBookmarkClient());
model_.reset(new enhanced_bookmarks::EnhancedBookmarkModel( bookmark_model_.reset(bookmark_client_->CreateModel().release());
bookmark_model_.get(), "v1.0")); model_.reset(new EnhancedBookmarkModel(bookmark_model_.get(), "v1.0"));
model_->AddObserver(this);
} }
virtual void TearDown() OVERRIDE { virtual void TearDown() OVERRIDE {
if (model_)
model_->ShutDown();
model_.reset(); model_.reset();
bookmark_model_.reset(); bookmark_model_.reset();
bookmark_client_.reset();
message_loop_.reset();
} }
protected: protected:
...@@ -48,26 +69,83 @@ class EnhancedBookmarkModelTest : public testing::Test { ...@@ -48,26 +69,83 @@ class EnhancedBookmarkModelTest : public testing::Test {
const BookmarkNode* AddBookmark(const std::string& name, const BookmarkNode* AddBookmark(const std::string& name,
const BookmarkNode* parent) { const BookmarkNode* parent) {
return bookmark_model_->AddURL(parent, return model_->AddURL(parent,
0, // index. 0, // index.
base::ASCIIToUTF16(name), base::ASCIIToUTF16(name),
GURL(BOOKMARK_URL)); GURL(BOOKMARK_URL),
base::Time::Now());
} }
const BookmarkNode* AddFolder(const std::string& name, const BookmarkNode* AddFolder(const std::string& name,
const BookmarkNode* parent) { const BookmarkNode* parent) {
return bookmark_model_->AddFolder(parent, 0, base::ASCIIToUTF16(name)); return model_->AddFolder(parent, 0, base::ASCIIToUTF16(name));
} }
std::string GetVersionForNode(const BookmarkNode* node) { std::string GetVersion(const BookmarkNode* node) {
std::string version; return GetMetaInfoField(node, "stars.version");
if (!node->GetMetaInfo("stars.version", &version)) }
std::string GetId(const BookmarkNode* node) {
return GetMetaInfoField(node, "stars.id");
}
std::string GetOldId(const BookmarkNode* node) {
return GetMetaInfoField(node, "stars.oldId");
}
std::string GetMetaInfoField(const BookmarkNode* node,
const std::string& name) {
std::string value;
if (!node->GetMetaInfo(name, &value))
return std::string(); return std::string();
return version; return value;
} }
scoped_ptr<base::MessageLoop> message_loop_;
scoped_ptr<bookmarks::TestBookmarkClient> bookmark_client_;
scoped_ptr<BookmarkModel> bookmark_model_; scoped_ptr<BookmarkModel> bookmark_model_;
scoped_ptr<enhanced_bookmarks::EnhancedBookmarkModel> model_; scoped_ptr<EnhancedBookmarkModel> model_;
// EnhancedBookmarkModelObserver implementation:
virtual void EnhancedBookmarkModelLoaded() OVERRIDE { loaded_calls_++; }
virtual void EnhancedBookmarkModelShuttingDown() OVERRIDE {
shutting_down_calls_++;
}
virtual void EnhancedBookmarkAdded(const BookmarkNode* node) OVERRIDE {
added_calls_++;
last_added_ = node;
}
virtual void EnhancedBookmarkRemoved(const BookmarkNode* node) OVERRIDE {
removed_calls_++;
last_removed_ = node;
}
virtual void EnhancedBookmarkAllUserNodesRemoved() OVERRIDE {
all_user_nodes_removed_calls_++;
}
virtual void EnhancedBookmarkRemoteIdChanged(
const BookmarkNode* node,
const std::string& old_remote_id,
const std::string& remote_id) OVERRIDE {
remote_id_changed_calls_++;
last_remote_id_node_ = node;
last_old_remote_id_ = old_remote_id;
last_remote_id_ = remote_id;
}
// Observer call counters:
int loaded_calls_;
int shutting_down_calls_;
int added_calls_;
int removed_calls_;
int all_user_nodes_removed_calls_;
int remote_id_changed_calls_;
// Observer parameter cache:
const BookmarkNode* last_added_;
const BookmarkNode* last_removed_;
const BookmarkNode* last_remote_id_node_;
std::string last_old_remote_id_;
std::string last_remote_id_;
private: private:
DISALLOW_COPY_AND_ASSIGN(EnhancedBookmarkModelTest); DISALLOW_COPY_AND_ASSIGN(EnhancedBookmarkModelTest);
...@@ -253,7 +331,7 @@ TEST_F(EnhancedBookmarkModelTest, TestEncodeDecode) { ...@@ -253,7 +331,7 @@ TEST_F(EnhancedBookmarkModelTest, TestEncodeDecode) {
EXPECT_EQ(url, GURL("http://example.com/i.jpg")); EXPECT_EQ(url, GURL("http://example.com/i.jpg"));
EXPECT_EQ(width, 22); EXPECT_EQ(width, 22);
EXPECT_EQ(height, 33); EXPECT_EQ(height, 33);
EXPECT_EQ("v1.0", GetVersionForNode(node)); EXPECT_EQ("v1.0", GetVersion(node));
} }
TEST_F(EnhancedBookmarkModelTest, TestDoubleEncodeDecode) { TEST_F(EnhancedBookmarkModelTest, TestDoubleEncodeDecode) {
...@@ -276,25 +354,26 @@ TEST_F(EnhancedBookmarkModelTest, TestDoubleEncodeDecode) { ...@@ -276,25 +354,26 @@ TEST_F(EnhancedBookmarkModelTest, TestDoubleEncodeDecode) {
EXPECT_EQ(url, GURL("http://example.com/i.jpg")); EXPECT_EQ(url, GURL("http://example.com/i.jpg"));
EXPECT_EQ(width, 33); EXPECT_EQ(width, 33);
EXPECT_EQ(height, 44); EXPECT_EQ(height, 44);
EXPECT_EQ("v1.0", GetVersionForNode(node)); EXPECT_EQ("v1.0", GetVersion(node));
} }
TEST_F(EnhancedBookmarkModelTest, TestRemoteId) { TEST_F(EnhancedBookmarkModelTest, TestRemoteId) {
const BookmarkNode* node = AddBookmark(); const BookmarkNode* node = AddBookmark();
const BookmarkNode* folder_node = AddFolder();
std::string remote_id = model_->GetRemoteId(node);
// First call creates the UUID, second call should return the same.
EXPECT_EQ(remote_id, model_->GetRemoteId(node));
// Verify that the remote id starts with the correct prefix. // Verify that the remote id starts with the correct prefix.
EXPECT_TRUE(StartsWithASCII(remote_id, "ebc_", true)); EXPECT_TRUE(StartsWithASCII(model_->GetRemoteId(node), "ebc_", true));
std::string folder_remote_id = model_->GetRemoteId(folder_node);
EXPECT_TRUE(StartsWithASCII(folder_remote_id, "ebf_", true)); // Getting the remote id for nodes that don't have them should return the
// empty string.
// Verifiy version field was set. const BookmarkNode* existing_node =
EXPECT_EQ("v1.0", GetVersionForNode(node)); bookmark_model_->AddURL(bookmark_model_->other_node(),
EXPECT_EQ("v1.0", GetVersionForNode(folder_node)); 0,
base::ASCIIToUTF16("Title"),
GURL(GURL(BOOKMARK_URL)));
EXPECT_TRUE(model_->GetRemoteId(existing_node).empty());
// Folder nodes should not have a remote id set on creation.
const BookmarkNode* folder_node = AddFolder();
EXPECT_TRUE(model_->GetRemoteId(folder_node).empty());
} }
TEST_F(EnhancedBookmarkModelTest, TestEmptyDescription) { TEST_F(EnhancedBookmarkModelTest, TestEmptyDescription) {
...@@ -313,7 +392,7 @@ TEST_F(EnhancedBookmarkModelTest, TestDescription) { ...@@ -313,7 +392,7 @@ TEST_F(EnhancedBookmarkModelTest, TestDescription) {
// Check the description is the one that was set. // Check the description is the one that was set.
EXPECT_EQ(model_->GetDescription(node), description); EXPECT_EQ(model_->GetDescription(node), description);
EXPECT_EQ("v1.0", GetVersionForNode(node)); EXPECT_EQ("v1.0", GetVersion(node));
} }
// If there is no notes field, the description should fall back on the snippet. // If there is no notes field, the description should fall back on the snippet.
...@@ -349,10 +428,10 @@ TEST_F(EnhancedBookmarkModelTest, TestDescriptionFallback) { ...@@ -349,10 +428,10 @@ TEST_F(EnhancedBookmarkModelTest, TestDescriptionFallback) {
// EnhancedBookmarkModel makes a change to a node. // EnhancedBookmarkModel makes a change to a node.
TEST_F(EnhancedBookmarkModelTest, TestVersionField) { TEST_F(EnhancedBookmarkModelTest, TestVersionField) {
const BookmarkNode* node = AddBookmark(); const BookmarkNode* node = AddBookmark();
EXPECT_EQ("", GetVersionForNode(node)); EXPECT_EQ("", GetVersion(node));
model_->SetDescription(node, "foo"); model_->SetDescription(node, "foo");
EXPECT_EQ("v1.0", GetVersionForNode(node)); EXPECT_EQ("v1.0", GetVersion(node));
// Add a suffix to the version to set. // Add a suffix to the version to set.
model_->SetVersionSuffix("alpha"); model_->SetVersionSuffix("alpha");
...@@ -360,21 +439,213 @@ TEST_F(EnhancedBookmarkModelTest, TestVersionField) { ...@@ -360,21 +439,213 @@ TEST_F(EnhancedBookmarkModelTest, TestVersionField) {
model_->SetDescription(node, "foo"); model_->SetDescription(node, "foo");
// Since the description didn't actually change, the version field should // Since the description didn't actually change, the version field should
// not either. // not either.
EXPECT_EQ("v1.0", GetVersionForNode(node)); EXPECT_EQ("v1.0", GetVersion(node));
model_->SetDescription(node, "bar"); model_->SetDescription(node, "bar");
EXPECT_EQ("v1.0/alpha", GetVersionForNode(node)); EXPECT_EQ("v1.0/alpha", GetVersion(node));
}
// Verifies that duplicate nodes are reset when the model is created.
TEST_F(EnhancedBookmarkModelTest, ResetDuplicateNodesOnInitialization) {
model_->ShutDown();
const BookmarkNode* parent = bookmark_model_->other_node();
const BookmarkNode* node1 = bookmark_model_->AddURL(
parent, 0, base::ASCIIToUTF16("Some title"), GURL(BOOKMARK_URL));
const BookmarkNode* node2 = bookmark_model_->AddURL(
parent, 0, base::ASCIIToUTF16("Some title"), GURL(BOOKMARK_URL));
const BookmarkNode* node3 = bookmark_model_->AddURL(
parent, 0, base::ASCIIToUTF16("Some title"), GURL(BOOKMARK_URL));
const BookmarkNode* node4 = bookmark_model_->AddURL(
parent, 0, base::ASCIIToUTF16("Some title"), GURL(BOOKMARK_URL));
bookmark_model_->SetNodeMetaInfo(node1, "stars.id", "c_1");
bookmark_model_->SetNodeMetaInfo(node2, "stars.id", "c_2");
bookmark_model_->SetNodeMetaInfo(node3, "stars.id", "c_1");
bookmark_model_->SetNodeMetaInfo(node4, "stars.id", "c_1");
EXPECT_EQ("c_1", GetId(node1));
EXPECT_EQ("c_2", GetId(node2));
EXPECT_EQ("c_1", GetId(node3));
EXPECT_EQ("c_1", GetId(node4));
model_.reset(new EnhancedBookmarkModel(bookmark_model_.get(), "v2.0"));
base::RunLoop().RunUntilIdle();
EXPECT_EQ("c_2", GetId(node2));
EXPECT_EQ("", GetId(node1));
EXPECT_EQ("", GetId(node3));
EXPECT_EQ("", GetId(node4));
EXPECT_EQ("c_1", GetOldId(node1));
EXPECT_EQ("c_1", GetOldId(node3));
EXPECT_EQ("c_1", GetOldId(node4));
EXPECT_EQ("v2.0", GetVersion(node1));
EXPECT_EQ("v2.0", GetVersion(node3));
EXPECT_EQ("v2.0", GetVersion(node4));
}
// Verifies that duplicate nodes are reset if one is created.
TEST_F(EnhancedBookmarkModelTest, ResetDuplicateAddedNodes) {
BookmarkNode::MetaInfoMap meta_info;
meta_info["stars.id"] = "c_1";
const BookmarkNode* parent = bookmark_model_->other_node();
const BookmarkNode* node1 =
bookmark_model_->AddURLWithCreationTimeAndMetaInfo(
parent,
0,
base::ASCIIToUTF16("Some title"),
GURL(BOOKMARK_URL),
base::Time::Now(),
&meta_info);
EXPECT_EQ("c_1", GetId(node1));
const BookmarkNode* node2 =
bookmark_model_->AddURLWithCreationTimeAndMetaInfo(
parent,
0,
base::ASCIIToUTF16("Some title"),
GURL(BOOKMARK_URL),
base::Time::Now(),
&meta_info);
base::RunLoop().RunUntilIdle();
EXPECT_EQ("", GetId(node1));
EXPECT_EQ("", GetId(node2));
EXPECT_EQ("c_1", GetOldId(node1));
EXPECT_EQ("c_1", GetOldId(node2));
EXPECT_EQ("v1.0", GetVersion(node1));
EXPECT_EQ("v1.0", GetVersion(node2));
} }
// Verifies that the stars.userEdit field is set appropriately when editing a // Verifies that duplicate nodes are reset if an id is changed to a duplicate
// node. // value.
TEST_F(EnhancedBookmarkModelTest, TestUserEdit) { TEST_F(EnhancedBookmarkModelTest, ResetDuplicateChangedNodes) {
const BookmarkNode* node1 = AddBookmark();
const BookmarkNode* node2 = AddBookmark();
bookmark_model_->SetNodeMetaInfo(node1, "stars.id", "c_1");
EXPECT_EQ("c_1", GetId(node1));
bookmark_model_->SetNodeMetaInfo(node2, "stars.id", "c_1");
base::RunLoop().RunUntilIdle();
EXPECT_EQ("", GetId(node1));
EXPECT_EQ("", GetId(node2));
EXPECT_EQ("c_1", GetOldId(node1));
EXPECT_EQ("c_1", GetOldId(node2));
EXPECT_EQ("v1.0", GetVersion(node1));
EXPECT_EQ("v1.0", GetVersion(node2));
}
TEST_F(EnhancedBookmarkModelTest, SetMultipleMetaInfo) {
const BookmarkNode* node = AddBookmark(); const BookmarkNode* node = AddBookmark();
BookmarkNode::MetaInfoMap meta_info;
meta_info["a"] = "aa";
meta_info["b"] = "bb";
model_->SetVersionSuffix("1");
model_->SetMultipleMetaInfo(node, meta_info);
EXPECT_EQ("aa", GetMetaInfoField(node, "a"));
EXPECT_EQ("bb", GetMetaInfoField(node, "b"));
EXPECT_EQ("v1.0/1", GetVersion(node));
// Not present fields does not erase the fields already set on the node.
meta_info["a"] = "aaa";
model_->SetVersionSuffix("2");
model_->SetMultipleMetaInfo(node, meta_info);
EXPECT_EQ("aaa", GetMetaInfoField(node, "a"));
EXPECT_EQ("bb", GetMetaInfoField(node, "b"));
EXPECT_EQ("v1.0/2", GetVersion(node));
// Not actually changing any values should not set the version field.
model_->SetVersionSuffix("3");
model_->SetMultipleMetaInfo(node, meta_info);
EXPECT_EQ("v1.0/2", GetVersion(node));
}
model_->SetDescription(node, "foo"); TEST_F(EnhancedBookmarkModelTest, ObserverShuttingDownEvent) {
std::string user_edit; EXPECT_EQ(0, shutting_down_calls_);
ASSERT_TRUE(node->GetMetaInfo("stars.userEdit", &user_edit)); model_->ShutDown();
EXPECT_EQ("true", user_edit); EXPECT_EQ(1, shutting_down_calls_);
model_.reset();
} }
} // namespace TEST_F(EnhancedBookmarkModelTest, ObserverNodeAddedEvent) {
EXPECT_EQ(0, added_calls_);
const BookmarkNode* node = AddBookmark();
EXPECT_EQ(1, added_calls_);
EXPECT_EQ(node, last_added_);
const BookmarkNode* folder = AddFolder();
EXPECT_EQ(2, added_calls_);
EXPECT_EQ(folder, last_added_);
}
TEST_F(EnhancedBookmarkModelTest, ObserverNodeRemovedEvent) {
const BookmarkNode* node = AddBookmark();
const BookmarkNode* folder = AddFolder();
EXPECT_EQ(0, removed_calls_);
bookmark_model_->Remove(node->parent(), node->parent()->GetIndexOf(node));
EXPECT_EQ(1, removed_calls_);
EXPECT_EQ(node, last_removed_);
bookmark_model_->Remove(folder->parent(),
folder->parent()->GetIndexOf(folder));
EXPECT_EQ(2, removed_calls_);
EXPECT_EQ(folder, last_removed_);
}
TEST_F(EnhancedBookmarkModelTest, ObserverAllUserNodesRemovedEvent) {
AddBookmark();
AddFolder();
EXPECT_EQ(0, all_user_nodes_removed_calls_);
bookmark_model_->RemoveAllUserBookmarks();
EXPECT_EQ(0, removed_calls_);
EXPECT_EQ(1, all_user_nodes_removed_calls_);
}
TEST_F(EnhancedBookmarkModelTest, ObserverRemoteIdChangedEvent) {
const BookmarkNode* node1 = AddFolder();
const BookmarkNode* node2 = AddFolder();
EXPECT_EQ(0, remote_id_changed_calls_);
bookmark_model_->SetNodeMetaInfo(node1, "stars.id", "c_1");
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, remote_id_changed_calls_);
EXPECT_EQ(node1, last_remote_id_node_);
EXPECT_EQ("", last_old_remote_id_);
EXPECT_EQ("c_1", last_remote_id_);
bookmark_model_->SetNodeMetaInfo(node2, "stars.id", "c_2");
base::RunLoop().RunUntilIdle();
EXPECT_EQ(2, remote_id_changed_calls_);
EXPECT_EQ(node2, last_remote_id_node_);
EXPECT_EQ("", last_old_remote_id_);
EXPECT_EQ("c_2", last_remote_id_);
bookmark_model_->SetNodeMetaInfo(node1, "stars.id", "c_3");
base::RunLoop().RunUntilIdle();
EXPECT_EQ(3, remote_id_changed_calls_);
EXPECT_EQ(node1, last_remote_id_node_);
EXPECT_EQ("c_1", last_old_remote_id_);
EXPECT_EQ("c_3", last_remote_id_);
// Set to duplicate ids.
bookmark_model_->SetNodeMetaInfo(node2, "stars.id", "c_3");
EXPECT_EQ(4, remote_id_changed_calls_);
EXPECT_EQ(node2, last_remote_id_node_);
EXPECT_EQ("c_2", last_old_remote_id_);
EXPECT_EQ("c_3", last_remote_id_);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(6, remote_id_changed_calls_);
EXPECT_EQ("", last_remote_id_);
}
TEST_F(EnhancedBookmarkModelTest, ShutDownWhileResetDuplicationScheduled) {
const BookmarkNode* node1 = AddBookmark();
const BookmarkNode* node2 = AddBookmark();
bookmark_model_->SetNodeMetaInfo(node1, "stars.id", "c_1");
bookmark_model_->SetNodeMetaInfo(node2, "stars.id", "c_1");
model_->ShutDown();
model_.reset();
base::RunLoop().RunUntilIdle();
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment