Commit 55b3fe20 authored by Mikel Astiz's avatar Mikel Astiz Committed by Commit Bot

Reland "Extend bookmark sync code with support for favicon deletion"

This is a reland of d63652c8

The new version reverts a change in tests (removal of
urls_with_favicons_) which presumably introduces flakiness on Mac.
My hypothesis is that using urls_with_favicons_ hides a race
condition that predates my patch, because the failing test is
unrelated to favicons, TwoClientBookmarksSyncTest.Sanity, and the
failing logs surface title mismatches as well:
[...:bookmarks_helper.cc(377)] Title mismatch: Yahoo vs. Google

Original change's description:
> Extend bookmark sync code with support for favicon deletion
> 
> Recent patches have introduced new favicon scenarios by handling cases
> where a site's content changes to not contain favicons.
> 
> Updating sync code to handle these events is needed to prevent sync
> from resurrecting the favicon, due to not knowing about the deletion
> and hence sync-ing it back to the local cache.
> 
> One notable change is that the new logic will introduce the concept of
> sync-ed bookmark protos having neither an icon URL (field |icon_url|)
> nor favicon image data (field |favicon|). Ancient versions of chrome
> (prior to M25) didn't sync these fields and would be incompatible
> (although not really badly) but too old for us to care.
> 
> Manually tested sync-ing across two patched instances of Chrome desktop
> (Linux):
> - Propagate deletions of bookmark favicons (after page content changes).
> - Restoring deleted bookmark favicons (after page content changes).
> 
> Bug: 85806
> Change-Id: Ia3534c6094983658f59f973777b5ed649c8769e8
> Reviewed-on: https://chromium-review.googlesource.com/704737
> Commit-Queue: Mikel Astiz <mastiz@chromium.org>
> Reviewed-by: Scott Violet <sky@chromium.org>
> Reviewed-by: Nicolas Zea <zea@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#514424}

Bug: 85806
Change-Id: If4d05da9e13c1d9d5abb19fd8a7c1d463af609a4
Reviewed-on: https://chromium-review.googlesource.com/757516Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarNicolas Zea <zea@chromium.org>
Commit-Queue: Mikel Astiz <mastiz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#514934}
parent 3bc820ae
...@@ -90,7 +90,6 @@ class FaviconChangeObserver : public bookmarks::BookmarkModelObserver { ...@@ -90,7 +90,6 @@ class FaviconChangeObserver : public bookmarks::BookmarkModelObserver {
wait_for_load_ = true; wait_for_load_ = true;
content::RunMessageLoop(); content::RunMessageLoop();
ASSERT_TRUE(node_->is_favicon_loaded()); ASSERT_TRUE(node_->is_favicon_loaded());
ASSERT_FALSE(model_->GetFavicon(node_).IsEmpty());
} }
void WaitForSetFavicon() { void WaitForSetFavicon() {
wait_for_load_ = false; wait_for_load_ = false;
...@@ -278,16 +277,46 @@ void ExpireFaviconImpl(Profile* profile, const BookmarkNode* node) { ...@@ -278,16 +277,46 @@ void ExpireFaviconImpl(Profile* profile, const BookmarkNode* node) {
favicon_service->SetFaviconOutOfDateForPage(node->url()); favicon_service->SetFaviconOutOfDateForPage(node->url());
} }
// Called asynchronously from CheckFaviconExpired() with the favicon data from // Used to call FaviconService APIs synchronously by making |callback| quit a
// the database. // RunLoop.
void OnGotFaviconForExpiryCheck( void OnGotFaviconData(
const base::Closure& callback, const base::Closure& callback,
favicon_base::FaviconRawBitmapResult* output_bitmap_result,
const favicon_base::FaviconRawBitmapResult& bitmap_result) { const favicon_base::FaviconRawBitmapResult& bitmap_result) {
ASSERT_TRUE(bitmap_result.is_valid()); *output_bitmap_result = bitmap_result;
ASSERT_TRUE(bitmap_result.expired);
callback.Run(); callback.Run();
} }
// Deletes favicon mappings for |profile| and |node|. |profile| may be
// |test()->verifier()|.
void DeleteFaviconMappingsImpl(Profile* profile,
const BookmarkNode* node,
bookmarks_helper::FaviconSource favicon_source) {
BookmarkModel* model = BookmarkModelFactory::GetForBrowserContext(profile);
FaviconChangeObserver observer(model, node);
favicon::FaviconService* favicon_service =
FaviconServiceFactory::GetForProfile(profile,
ServiceAccessType::EXPLICIT_ACCESS);
if (favicon_source == bookmarks_helper::FROM_UI) {
favicon_service->DeleteFaviconMappings({node->url()},
favicon_base::IconType::kFavicon);
} else {
browser_sync::ProfileSyncService* pss =
ProfileSyncServiceFactory::GetForProfile(profile);
sync_bookmarks::BookmarkChangeProcessor::ApplyBookmarkFavicon(
node, pss->GetSyncClient(), /*icon_url=*/GURL(),
scoped_refptr<base::RefCountedString>(new base::RefCountedString()));
}
// Wait for the favicon for |node| to be invalidated.
observer.WaitForSetFavicon();
// Wait for the BookmarkModel to fetch the updated favicon and for the new
// favicon to be sent to BookmarkChangeProcessor.
GetFaviconData(model, node);
}
// Wait for all currently scheduled tasks on the history thread for all // Wait for all currently scheduled tasks on the history thread for all
// profiles to complete and any notifications sent to the UI thread to have // profiles to complete and any notifications sent to the UI thread to have
// finished processing. // finished processing.
...@@ -633,12 +662,55 @@ void CheckFaviconExpired(int profile, const GURL& icon_url) { ...@@ -633,12 +662,55 @@ void CheckFaviconExpired(int profile, const GURL& icon_url) {
sync_datatype_helper::test()->GetProfile(profile), sync_datatype_helper::test()->GetProfile(profile),
ServiceAccessType::EXPLICIT_ACCESS); ServiceAccessType::EXPLICIT_ACCESS);
base::CancelableTaskTracker task_tracker; base::CancelableTaskTracker task_tracker;
favicon_base::FaviconRawBitmapResult bitmap_result;
favicon_service->GetRawFavicon( favicon_service->GetRawFavicon(
icon_url, favicon_base::IconType::kFavicon, 0, icon_url, favicon_base::IconType::kFavicon, 0,
base::Bind(&OnGotFaviconForExpiryCheck, run_loop.QuitClosure()), base::Bind(&OnGotFaviconData, run_loop.QuitClosure(), &bitmap_result),
&task_tracker); &task_tracker);
run_loop.Run();
ASSERT_TRUE(bitmap_result.is_valid());
ASSERT_TRUE(bitmap_result.expired);
}
void CheckHasNoFavicon(int profile, const GURL& page_url) {
base::RunLoop run_loop;
favicon::FaviconService* favicon_service =
FaviconServiceFactory::GetForProfile(
sync_datatype_helper::test()->GetProfile(profile),
ServiceAccessType::EXPLICIT_ACCESS);
base::CancelableTaskTracker task_tracker;
favicon_base::FaviconRawBitmapResult bitmap_result;
favicon_service->GetRawFaviconForPageURL(
page_url, {favicon_base::IconType::kFavicon}, 0,
base::Bind(&OnGotFaviconData, run_loop.QuitClosure(), &bitmap_result),
&task_tracker);
run_loop.Run(); run_loop.Run();
ASSERT_FALSE(bitmap_result.is_valid());
}
void DeleteFaviconMappings(int profile,
const BookmarkNode* node,
FaviconSource favicon_source) {
BookmarkModel* model = GetBookmarkModel(profile);
ASSERT_EQ(bookmarks::GetBookmarkNodeByID(model, node->id()), node)
<< "Node " << node->GetTitle() << " does not belong to "
<< "Profile " << profile;
ASSERT_EQ(BookmarkNode::URL, node->type())
<< "Node " << node->GetTitle() << " must be a url.";
if (sync_datatype_helper::test()->use_verifier()) {
const BookmarkNode* v_node = nullptr;
FindNodeInVerifier(model, node, &v_node);
DeleteFaviconMappingsImpl(sync_datatype_helper::test()->verifier(), v_node,
favicon_source);
}
DeleteFaviconMappingsImpl(sync_datatype_helper::test()->GetProfile(profile),
node, favicon_source);
WaitForHistoryToProcessPendingTasks();
} }
const BookmarkNode* SetURL(int profile, const BookmarkNode* SetURL(int profile,
......
...@@ -115,6 +115,14 @@ void ExpireFavicon(int profile, const bookmarks::BookmarkNode* node); ...@@ -115,6 +115,14 @@ void ExpireFavicon(int profile, const bookmarks::BookmarkNode* node);
// Checks whether the favicon at |icon_url| for |profile| is expired; // Checks whether the favicon at |icon_url| for |profile| is expired;
void CheckFaviconExpired(int profile, const GURL& icon_url); void CheckFaviconExpired(int profile, const GURL& icon_url);
// Deletes the favicon mappings for |node| in the bookmark model for |profile|.
void DeleteFaviconMappings(int profile,
const bookmarks::BookmarkNode* node,
FaviconSource favicon_source);
// Checks whether |page_url| for |profile| has no favicon mappings.
void CheckHasNoFavicon(int profile, const GURL& page_url);
// Changes the url of the node |node| in the bookmark model of profile // Changes the url of the node |node| in the bookmark model of profile
// |profile| to |new_url|. Returns a pointer to the node with the changed url. // |profile| to |new_url|. Returns a pointer to the node with the changed url.
const bookmarks::BookmarkNode* SetURL(int profile, const bookmarks::BookmarkNode* SetURL(int profile,
......
...@@ -22,10 +22,12 @@ using bookmarks::BookmarkModel; ...@@ -22,10 +22,12 @@ using bookmarks::BookmarkModel;
using bookmarks::BookmarkNode; using bookmarks::BookmarkNode;
using bookmarks_helper::AddFolder; using bookmarks_helper::AddFolder;
using bookmarks_helper::AddURL; using bookmarks_helper::AddURL;
using bookmarks_helper::CheckHasNoFavicon;
using bookmarks_helper::CountBookmarksWithTitlesMatching; using bookmarks_helper::CountBookmarksWithTitlesMatching;
using bookmarks_helper::CountBookmarksWithUrlsMatching; using bookmarks_helper::CountBookmarksWithUrlsMatching;
using bookmarks_helper::CountFoldersWithTitlesMatching; using bookmarks_helper::CountFoldersWithTitlesMatching;
using bookmarks_helper::Create1xFaviconFromPNGFile; using bookmarks_helper::Create1xFaviconFromPNGFile;
using bookmarks_helper::CreateFavicon;
using bookmarks_helper::GetBookmarkBarNode; using bookmarks_helper::GetBookmarkBarNode;
using bookmarks_helper::GetBookmarkModel; using bookmarks_helper::GetBookmarkModel;
using bookmarks_helper::GetOtherNode; using bookmarks_helper::GetOtherNode;
...@@ -267,6 +269,34 @@ IN_PROC_BROWSER_TEST_F(SingleClientBookmarksSyncTest, ...@@ -267,6 +269,34 @@ IN_PROC_BROWSER_TEST_F(SingleClientBookmarksSyncTest,
EXPECT_TRUE(original_favicon_bytes->Equals(final_favicon_bytes)); EXPECT_TRUE(original_favicon_bytes->Equals(final_favicon_bytes));
} }
// Test that a client deletes favicons from sync when they have been removed
// from the local database.
IN_PROC_BROWSER_TEST_F(SingleClientBookmarksSyncTest, DeleteFaviconFromSync) {
ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
ASSERT_TRUE(ModelMatchesVerifier(kSingleProfileIndex));
const GURL page_url("http://www.google.com");
const GURL icon_url("http://www.google.com/favicon.ico");
const BookmarkNode* bookmark = AddURL(kSingleProfileIndex, "title", page_url);
SetFavicon(0, bookmark, icon_url, CreateFavicon(SK_ColorWHITE),
bookmarks_helper::FROM_UI);
ASSERT_TRUE(
UpdatedProgressMarkerChecker(GetSyncService(kSingleProfileIndex)).Wait());
ASSERT_TRUE(ModelMatchesVerifier(kSingleProfileIndex));
// Simulate receiving a favicon deletion from sync.
DeleteFaviconMappings(kSingleProfileIndex, bookmark,
bookmarks_helper::FROM_SYNC);
ASSERT_TRUE(
UpdatedProgressMarkerChecker(GetSyncService(kSingleProfileIndex)).Wait());
ASSERT_TRUE(ModelMatchesVerifier(kSingleProfileIndex));
CheckHasNoFavicon(kSingleProfileIndex, page_url);
EXPECT_TRUE(
GetBookmarkModel(kSingleProfileIndex)->GetFavicon(bookmark).IsEmpty());
}
IN_PROC_BROWSER_TEST_F(SingleClientBookmarksSyncTest, IN_PROC_BROWSER_TEST_F(SingleClientBookmarksSyncTest,
BookmarkAllNodesRemovedEvent) { BookmarkAllNodesRemovedEvent) {
ASSERT_TRUE(SetupClients()) << "SetupClients() failed."; ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
......
...@@ -37,12 +37,14 @@ using bookmarks_helper::AddURL; ...@@ -37,12 +37,14 @@ using bookmarks_helper::AddURL;
using bookmarks_helper::AllModelsMatch; using bookmarks_helper::AllModelsMatch;
using bookmarks_helper::AllModelsMatchVerifier; using bookmarks_helper::AllModelsMatchVerifier;
using bookmarks_helper::CheckFaviconExpired; using bookmarks_helper::CheckFaviconExpired;
using bookmarks_helper::CheckHasNoFavicon;
using bookmarks_helper::ContainsDuplicateBookmarks; using bookmarks_helper::ContainsDuplicateBookmarks;
using bookmarks_helper::CountAllBookmarks; using bookmarks_helper::CountAllBookmarks;
using bookmarks_helper::CountBookmarksWithTitlesMatching; using bookmarks_helper::CountBookmarksWithTitlesMatching;
using bookmarks_helper::CountBookmarksWithUrlsMatching; using bookmarks_helper::CountBookmarksWithUrlsMatching;
using bookmarks_helper::CountFoldersWithTitlesMatching; using bookmarks_helper::CountFoldersWithTitlesMatching;
using bookmarks_helper::CreateFavicon; using bookmarks_helper::CreateFavicon;
using bookmarks_helper::DeleteFaviconMappings;
using bookmarks_helper::ExpireFavicon; using bookmarks_helper::ExpireFavicon;
using bookmarks_helper::GetBookmarkBarNode; using bookmarks_helper::GetBookmarkBarNode;
using bookmarks_helper::GetManagedNode; using bookmarks_helper::GetManagedNode;
...@@ -306,6 +308,35 @@ IN_PROC_BROWSER_TEST_F(TwoClientBookmarksSyncTest, ...@@ -306,6 +308,35 @@ IN_PROC_BROWSER_TEST_F(TwoClientBookmarksSyncTest,
ASSERT_TRUE(BookmarksMatchVerifierChecker().Wait()); ASSERT_TRUE(BookmarksMatchVerifierChecker().Wait());
} }
IN_PROC_BROWSER_TEST_F(TwoClientBookmarksSyncTest, SC_DeleteFavicon) {
const GURL page_url("http://www.google.com/a");
const GURL icon_url("http://www.google.com/favicon.ico");
ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
ASSERT_TRUE(AllModelsMatchVerifier());
const BookmarkNode* bookmark0 = AddURL(0, kGenericURLTitle, page_url);
ASSERT_NE(nullptr, bookmark0);
SetFavicon(0, bookmark0, icon_url, CreateFavicon(SK_ColorWHITE),
bookmarks_helper::FROM_UI);
ASSERT_TRUE(BookmarksMatchVerifierChecker().Wait());
DeleteFaviconMappings(0, bookmark0, bookmarks_helper::FROM_UI);
ASSERT_TRUE(BookmarksMatchVerifierChecker().Wait());
// Set the title for |page_url|. This should not revert the deletion of
// favicon mappings.
const char kNewTitle[] = "New Title";
ASSERT_STRNE(kGenericURLTitle, kNewTitle);
const BookmarkNode* bookmark1 = GetUniqueNodeByURL(1, page_url);
SetTitle(1, bookmark1, std::string(kNewTitle));
ASSERT_TRUE(BookmarksMatchVerifierChecker().Wait());
// |page_url| should still have no mapping.
CheckHasNoFavicon(0, page_url);
}
IN_PROC_BROWSER_TEST_F(TwoClientBookmarksSyncTest, SC_AddNonHTTPBMs) { IN_PROC_BROWSER_TEST_F(TwoClientBookmarksSyncTest, SC_AddNonHTTPBMs) {
ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
ASSERT_TRUE(AllModelsMatchVerifier()); ASSERT_TRUE(AllModelsMatchVerifier());
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <algorithm> #include <algorithm>
#include <functional> #include <functional>
#include <string>
#include <utility> #include <utility>
#include "base/bind.h" #include "base/bind.h"
...@@ -1025,6 +1026,9 @@ void BookmarkModel::OnFaviconDataAvailable( ...@@ -1025,6 +1026,9 @@ void BookmarkModel::OnFaviconDataAvailable(
// Couldn't load the touch icon, fallback to the regular favicon. // Couldn't load the touch icon, fallback to the regular favicon.
DCHECK(client_->PreferTouchIcon()); DCHECK(client_->PreferTouchIcon());
LoadFavicon(node, favicon_base::IconType::kFavicon); LoadFavicon(node, favicon_base::IconType::kFavicon);
} else {
// No favicon available, but we still notify observers.
FaviconLoaded(node);
} }
} }
......
...@@ -449,10 +449,10 @@ void BookmarkChangeProcessor::BookmarkNodeFaviconChanged( ...@@ -449,10 +449,10 @@ void BookmarkChangeProcessor::BookmarkNodeFaviconChanged(
return; return;
} }
// Ignore changes with empty images. This can happen if the favicon is // Ignore favicons that are being loaded.
// still being loaded. if (!node->is_favicon_loaded()) {
const gfx::Image& favicon = model->GetFavicon(node); // Sutble way to trigger a load of the favicon.
if (favicon.IsEmpty()) { model->GetFavicon(node);
return; return;
} }
...@@ -844,7 +844,7 @@ const BookmarkNode* BookmarkChangeProcessor::CreateBookmarkNode( ...@@ -844,7 +844,7 @@ const BookmarkNode* BookmarkChangeProcessor::CreateBookmarkNode(
// static // static
// Sets the favicon of the given bookmark node from the given sync node. // Sets the favicon of the given bookmark node from the given sync node.
bool BookmarkChangeProcessor::SetBookmarkFavicon( void BookmarkChangeProcessor::SetBookmarkFavicon(
const syncer::BaseNode* sync_node, const syncer::BaseNode* sync_node,
const BookmarkNode* bookmark_node, const BookmarkNode* bookmark_node,
BookmarkModel* bookmark_model, BookmarkModel* bookmark_model,
...@@ -852,23 +852,12 @@ bool BookmarkChangeProcessor::SetBookmarkFavicon( ...@@ -852,23 +852,12 @@ bool BookmarkChangeProcessor::SetBookmarkFavicon(
const sync_pb::BookmarkSpecifics& specifics = const sync_pb::BookmarkSpecifics& specifics =
sync_node->GetBookmarkSpecifics(); sync_node->GetBookmarkSpecifics();
const std::string& icon_bytes_str = specifics.favicon(); const std::string& icon_bytes_str = specifics.favicon();
if (icon_bytes_str.empty())
return false;
scoped_refptr<base::RefCountedString> icon_bytes( scoped_refptr<base::RefCountedString> icon_bytes(
new base::RefCountedString()); new base::RefCountedString());
icon_bytes->data().assign(icon_bytes_str); icon_bytes->data().assign(icon_bytes_str);
GURL icon_url(specifics.icon_url());
// Old clients may not be syncing the favicon URL. If the icon URL is not
// synced, use the page URL as a fake icon URL as it is guaranteed to be
// unique.
if (icon_url.is_empty())
icon_url = bookmark_node->url();
ApplyBookmarkFavicon(bookmark_node, sync_client, icon_url, icon_bytes);
return true; ApplyBookmarkFavicon(bookmark_node, sync_client, GURL(specifics.icon_url()),
icon_bytes);
} }
// static // static
...@@ -943,14 +932,36 @@ void BookmarkChangeProcessor::ApplyBookmarkFavicon( ...@@ -943,14 +932,36 @@ void BookmarkChangeProcessor::ApplyBookmarkFavicon(
history::HistoryService* history = sync_client->GetHistoryService(); history::HistoryService* history = sync_client->GetHistoryService();
favicon::FaviconService* favicon_service = sync_client->GetFaviconService(); favicon::FaviconService* favicon_service = sync_client->GetFaviconService();
// Some tests (that use FakeSyncClient) use no services.
if (history == nullptr)
return;
DCHECK(favicon_service);
history->AddPageNoVisitForBookmark(bookmark_node->url(), history->AddPageNoVisitForBookmark(bookmark_node->url(),
bookmark_node->GetTitle()); bookmark_node->GetTitle());
GURL icon_url_to_use = icon_url;
if (icon_url.is_empty()) {
if (bitmap_data->size() == 0) {
// Empty icon URL and no bitmap data means no icon mapping.
favicon_service->DeleteFaviconMappings({bookmark_node->url()},
favicon_base::IconType::kFavicon);
return;
} else {
// Ancient clients (prior to M25) may not be syncing the favicon URL. If
// the icon URL is not synced, use the page URL as a fake icon URL as it
// is guaranteed to be unique.
icon_url_to_use = bookmark_node->url();
}
}
// The client may have cached the favicon at 2x. Use MergeFavicon() as not to // The client may have cached the favicon at 2x. Use MergeFavicon() as not to
// overwrite the cached 2x favicon bitmap. Sync favicons are always // overwrite the cached 2x favicon bitmap. Sync favicons are always
// gfx::kFaviconSize in width and height. Store the favicon into history // gfx::kFaviconSize in width and height. Store the favicon into history
// as such. // as such.
gfx::Size pixel_size(gfx::kFaviconSize, gfx::kFaviconSize); gfx::Size pixel_size(gfx::kFaviconSize, gfx::kFaviconSize);
favicon_service->MergeFavicon(bookmark_node->url(), icon_url, favicon_service->MergeFavicon(bookmark_node->url(), icon_url_to_use,
favicon_base::IconType::kFavicon, bitmap_data, favicon_base::IconType::kFavicon, bitmap_data,
pixel_size); pixel_size);
} }
...@@ -962,16 +973,21 @@ void BookmarkChangeProcessor::SetSyncNodeFavicon( ...@@ -962,16 +973,21 @@ void BookmarkChangeProcessor::SetSyncNodeFavicon(
syncer::WriteNode* sync_node) { syncer::WriteNode* sync_node) {
scoped_refptr<base::RefCountedMemory> favicon_bytes(nullptr); scoped_refptr<base::RefCountedMemory> favicon_bytes(nullptr);
EncodeFavicon(bookmark_node, model, &favicon_bytes); EncodeFavicon(bookmark_node, model, &favicon_bytes);
sync_pb::BookmarkSpecifics updated_specifics(
sync_node->GetBookmarkSpecifics());
if (favicon_bytes.get() && favicon_bytes->size()) { if (favicon_bytes.get() && favicon_bytes->size()) {
sync_pb::BookmarkSpecifics updated_specifics(
sync_node->GetBookmarkSpecifics());
updated_specifics.set_favicon(favicon_bytes->front(), updated_specifics.set_favicon(favicon_bytes->front(),
favicon_bytes->size()); favicon_bytes->size());
updated_specifics.set_icon_url(bookmark_node->icon_url() updated_specifics.set_icon_url(bookmark_node->icon_url()
? bookmark_node->icon_url()->spec() ? bookmark_node->icon_url()->spec()
: std::string()); : std::string());
sync_node->SetBookmarkSpecifics(updated_specifics); } else {
updated_specifics.clear_favicon();
updated_specifics.clear_icon_url();
} }
sync_node->SetBookmarkSpecifics(updated_specifics);
} }
bool BookmarkChangeProcessor::CanSyncNode(const BookmarkNode* node) { bool BookmarkChangeProcessor::CanSyncNode(const BookmarkNode* node) {
......
...@@ -119,10 +119,9 @@ class BookmarkChangeProcessor : public bookmarks::BookmarkModelObserver, ...@@ -119,10 +119,9 @@ class BookmarkChangeProcessor : public bookmarks::BookmarkModelObserver,
int index); int index);
// Sets the favicon of the given bookmark node from the given sync node. // Sets the favicon of the given bookmark node from the given sync node.
// Returns whether the favicon was set in the bookmark node.
// |profile| is the profile that contains the HistoryService and BookmarkModel // |profile| is the profile that contains the HistoryService and BookmarkModel
// for the bookmark in question. // for the bookmark in question.
static bool SetBookmarkFavicon(const syncer::BaseNode* sync_node, static void SetBookmarkFavicon(const syncer::BaseNode* sync_node,
const bookmarks::BookmarkNode* bookmark_node, const bookmarks::BookmarkNode* bookmark_node,
bookmarks::BookmarkModel* model, bookmarks::BookmarkModel* model,
syncer::SyncClient* sync_client); syncer::SyncClient* sync_client);
......
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