Commit 692e82ab authored by Mikel Astiz's avatar Mikel Astiz Committed by Commit Bot

Avoid weird nested runloops while verifying model in sync tests

The use of WaitForGetFavicon() is unnecessary and misleading because
it introduces a nested runloop where many things can happen, including
model changes that call
BookmarksMatchVerifierChecker::IsExitConditionSatisfied() and hence
make it reentrant.

It is unnecessary because, starting with
55b3fe20, a loading favicon is
guaranteed to ultimately notify a model change, which will trigger
MultiClientStatusChangeChecker::OnStateChanged() and hence
IsExitConditionSatisfied().

Bug: 783774
Change-Id: I02c7623e3bb173b25b9c715b7bdf9c646300e3ee
Reviewed-on: https://chromium-review.googlesource.com/785091
Commit-Queue: Mikel Astiz <mastiz@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarPavel Yatsuk <pavely@chromium.org>
Cr-Commit-Position: refs/heads/master@{#522089}
parent 093acc6f
...@@ -80,21 +80,12 @@ class SignalEventTask : public history::HistoryDBTask { ...@@ -80,21 +80,12 @@ class SignalEventTask : public history::HistoryDBTask {
class FaviconChangeObserver : public bookmarks::BookmarkModelObserver { class FaviconChangeObserver : public bookmarks::BookmarkModelObserver {
public: public:
FaviconChangeObserver(BookmarkModel* model, const BookmarkNode* node) FaviconChangeObserver(BookmarkModel* model, const BookmarkNode* node)
: model_(model), : model_(model), node_(node) {
node_(node),
wait_for_load_(false) {
model->AddObserver(this); model->AddObserver(this);
} }
~FaviconChangeObserver() override { model_->RemoveObserver(this); } ~FaviconChangeObserver() override { model_->RemoveObserver(this); }
void WaitForGetFavicon() {
DCHECK(!run_loop_.running());
wait_for_load_ = true;
content::RunThisRunLoop(&run_loop_);
ASSERT_TRUE(node_->is_favicon_loaded());
}
void WaitForSetFavicon() { void WaitForSetFavicon() {
DCHECK(!run_loop_.running()); DCHECK(!run_loop_.running());
wait_for_load_ = false;
content::RunThisRunLoop(&run_loop_); content::RunThisRunLoop(&run_loop_);
} }
...@@ -127,16 +118,13 @@ class FaviconChangeObserver : public bookmarks::BookmarkModelObserver { ...@@ -127,16 +118,13 @@ class FaviconChangeObserver : public bookmarks::BookmarkModelObserver {
const BookmarkNode* node) override {} const BookmarkNode* node) override {}
void BookmarkNodeFaviconChanged(BookmarkModel* model, void BookmarkNodeFaviconChanged(BookmarkModel* model,
const BookmarkNode* node) override { const BookmarkNode* node) override {
if (model == model_ && node == node_ && run_loop_.running()) { if (model == model_ && node == node_)
if (!wait_for_load_ || (wait_for_load_ && node->is_favicon_loaded())) run_loop_.Quit();
run_loop_.Quit();
}
} }
private: private:
BookmarkModel* model_; BookmarkModel* model_;
const BookmarkNode* node_; const BookmarkNode* node_;
bool wait_for_load_;
base::RunLoop run_loop_; base::RunLoop run_loop_;
DISALLOW_COPY_AND_ASSIGN(FaviconChangeObserver); DISALLOW_COPY_AND_ASSIGN(FaviconChangeObserver);
}; };
...@@ -221,9 +209,10 @@ struct FaviconData { ...@@ -221,9 +209,10 @@ struct FaviconData {
GURL icon_url; GURL icon_url;
}; };
// Gets the favicon and icon URL associated with |node| in |model|. // Gets the favicon and icon URL associated with |node| in |model|. Returns
FaviconData GetFaviconData(BookmarkModel* model, // nullopt if the favicon is still loading.
const BookmarkNode* node) { base::Optional<FaviconData> GetFaviconData(BookmarkModel* model,
const BookmarkNode* node) {
// If a favicon wasn't explicitly set for a particular URL, simply return its // If a favicon wasn't explicitly set for a particular URL, simply return its
// blank favicon. // blank favicon.
if (!urls_with_favicons_ || if (!urls_with_favicons_ ||
...@@ -233,10 +222,12 @@ FaviconData GetFaviconData(BookmarkModel* model, ...@@ -233,10 +222,12 @@ FaviconData GetFaviconData(BookmarkModel* model,
// If a favicon was explicitly set, we may need to wait for it to be loaded // If a favicon was explicitly set, we may need to wait for it to be loaded
// via BookmarkModel::GetFavicon(), which is an asynchronous operation. // via BookmarkModel::GetFavicon(), which is an asynchronous operation.
if (!node->is_favicon_loaded()) { if (!node->is_favicon_loaded()) {
FaviconChangeObserver observer(model, node);
model->GetFavicon(node); model->GetFavicon(node);
observer.WaitForGetFavicon(); // Favicon still loading, no data available just yet.
return base::nullopt;
} }
// Favicon loaded: return actual image.
return FaviconData(model->GetFavicon(node), return FaviconData(model->GetFavicon(node),
node->icon_url() ? *node->icon_url() : GURL()); node->icon_url() ? *node->icon_url() : GURL());
} }
...@@ -266,9 +257,7 @@ void SetFaviconImpl(Profile* profile, ...@@ -266,9 +257,7 @@ void SetFaviconImpl(Profile* profile,
// Wait for the favicon for |node| to be invalidated. // Wait for the favicon for |node| to be invalidated.
observer.WaitForSetFavicon(); observer.WaitForSetFavicon();
// Wait for the BookmarkModel to fetch the updated favicon and for the new model->GetFavicon(node);
// favicon to be sent to BookmarkChangeProcessor.
GetFaviconData(model, node);
} }
// Expires the favicon for |profile| and |node|. |profile| may be // Expires the favicon for |profile| and |node|. |profile| may be
...@@ -315,9 +304,7 @@ void DeleteFaviconMappingsImpl(Profile* profile, ...@@ -315,9 +304,7 @@ void DeleteFaviconMappingsImpl(Profile* profile,
// Wait for the favicon for |node| to be invalidated. // Wait for the favicon for |node| to be invalidated.
observer.WaitForSetFavicon(); observer.WaitForSetFavicon();
// Wait for the BookmarkModel to fetch the updated favicon and for the new model->GetFavicon(node);
// 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
...@@ -360,14 +347,19 @@ bool FaviconsMatch(BookmarkModel* model_a, ...@@ -360,14 +347,19 @@ bool FaviconsMatch(BookmarkModel* model_a,
BookmarkModel* model_b, BookmarkModel* model_b,
const BookmarkNode* node_a, const BookmarkNode* node_a,
const BookmarkNode* node_b) { const BookmarkNode* node_b) {
FaviconData favicon_data_a = GetFaviconData(model_a, node_a); base::Optional<FaviconData> favicon_data_a = GetFaviconData(model_a, node_a);
FaviconData favicon_data_b = GetFaviconData(model_b, node_b); base::Optional<FaviconData> favicon_data_b = GetFaviconData(model_b, node_b);
// If either of the two favicons is still loading, let's return false now
// because observers will get notified when the load completes.
if (!favicon_data_a.has_value() || !favicon_data_b.has_value())
return false;
if (favicon_data_a.icon_url != favicon_data_b.icon_url) if (favicon_data_a->icon_url != favicon_data_b->icon_url)
return false; return false;
gfx::Image image_a = favicon_data_a.image; gfx::Image image_a = favicon_data_a->image;
gfx::Image image_b = favicon_data_b.image; gfx::Image image_b = favicon_data_b->image;
if (image_a.IsEmpty() && image_b.IsEmpty()) if (image_a.IsEmpty() && image_b.IsEmpty())
return true; // Two empty images are equivalent. return true; // Two empty images are equivalent.
......
...@@ -147,8 +147,11 @@ class BookmarkModel : public BookmarkUndoProvider, ...@@ -147,8 +147,11 @@ class BookmarkModel : public BookmarkUndoProvider,
const BookmarkNode* new_parent, const BookmarkNode* new_parent,
int index); int index);
// Returns the favicon for |node|. If the favicon has not yet been // Returns the favicon for |node|. If the favicon has not yet been loaded,
// loaded it is loaded and the observer of the model notified when done. // a load will be triggered and the observer of the model notified when done.
// This also means that, on return, the node's state is guaranteed to be
// either LOADED_FAVICON (if it was already loaded prior to the call) or
// LOADING_FAVICON (with the exception of folders, where the call is a no-op).
const gfx::Image& GetFavicon(const BookmarkNode* node); const gfx::Image& GetFavicon(const BookmarkNode* node);
// Returns the type of the favicon for |node|. If the favicon has not yet // Returns the type of the favicon for |node|. If the favicon has not yet
......
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