OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/test/live_sync/bookmarks_helper.h" | 5 #include "chrome/test/live_sync/bookmarks_helper.h" |
6 | 6 |
7 #include "base/rand_util.h" | 7 #include "base/rand_util.h" |
8 #include "base/string_number_conversions.h" | 8 #include "base/string_number_conversions.h" |
9 #include "base/stringprintf.h" | 9 #include "base/stringprintf.h" |
10 #include "base/utf_string_conversions.h" | 10 #include "base/utf_string_conversions.h" |
11 #include "chrome/browser/bookmarks/bookmark_model.h" | 11 #include "chrome/browser/bookmarks/bookmark_model.h" |
12 #include "chrome/browser/bookmarks/bookmark_model_observer.h" | 12 #include "chrome/browser/bookmarks/bookmark_model_observer.h" |
13 #include "chrome/browser/bookmarks/bookmark_utils.h" | 13 #include "chrome/browser/bookmarks/bookmark_utils.h" |
14 #include "chrome/browser/profiles/profile.h" | 14 #include "chrome/browser/profiles/profile.h" |
15 #include "chrome/browser/sync/glue/bookmark_change_processor.h" | 15 #include "chrome/browser/sync/glue/bookmark_change_processor.h" |
16 #include "chrome/browser/sync/profile_sync_service_harness.h" | 16 #include "chrome/browser/sync/profile_sync_service_harness.h" |
17 #include "chrome/test/base/ui_test_utils.h" | 17 #include "chrome/test/base/ui_test_utils.h" |
18 #include "chrome/test/live_sync/live_sync_test.h" | 18 #include "chrome/test/live_sync/live_sync_test.h" |
| 19 #include "chrome/test/live_sync/sync_datatype_helper.h" |
19 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
20 #include "third_party/skia/include/core/SkBitmap.h" | 21 #include "third_party/skia/include/core/SkBitmap.h" |
21 #include "ui/base/models/tree_node_iterator.h" | 22 #include "ui/base/models/tree_node_iterator.h" |
22 #include "ui/gfx/codec/png_codec.h" | 23 #include "ui/gfx/codec/png_codec.h" |
23 | 24 |
| 25 using sync_datatype_helper::test; |
| 26 |
24 namespace { | 27 namespace { |
25 | 28 |
26 // Helper class used to wait for changes to take effect on the favicon of a | 29 // Helper class used to wait for changes to take effect on the favicon of a |
27 // particular bookmark node in a particular bookmark model. | 30 // particular bookmark node in a particular bookmark model. |
28 class FaviconChangeObserver : public BookmarkModelObserver { | 31 class FaviconChangeObserver : public BookmarkModelObserver { |
29 public: | 32 public: |
30 FaviconChangeObserver(BookmarkModel* model, const BookmarkNode* node) | 33 FaviconChangeObserver(BookmarkModel* model, const BookmarkNode* node) |
31 : model_(model), | 34 : model_(model), |
32 node_(node), | 35 node_(node), |
33 wait_for_load_(false) { | 36 wait_for_load_(false) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 } | 78 } |
76 } | 79 } |
77 | 80 |
78 private: | 81 private: |
79 BookmarkModel* model_; | 82 BookmarkModel* model_; |
80 const BookmarkNode* node_; | 83 const BookmarkNode* node_; |
81 bool wait_for_load_; | 84 bool wait_for_load_; |
82 DISALLOW_COPY_AND_ASSIGN(FaviconChangeObserver); | 85 DISALLOW_COPY_AND_ASSIGN(FaviconChangeObserver); |
83 }; | 86 }; |
84 | 87 |
| 88 // A collection of URLs for which we have added favicons. Since loading a |
| 89 // favicon is an asynchronous operation and doesn't necessarily invoke a |
| 90 // callback, this collection is used to determine if we must wait for a URL's |
| 91 // favicon to load or not. |
| 92 std::set<GURL>* urls_with_favicons_ = NULL; |
| 93 |
| 94 // Returns the number of nodes of node type |node_type| in |model| whose |
| 95 // titles match the string |title|. |
| 96 int CountNodesWithTitlesMatching(BookmarkModel* model, |
| 97 BookmarkNode::Type node_type, |
| 98 const string16& title) { |
| 99 ui::TreeNodeIterator<const BookmarkNode> iterator(model->root_node()); |
| 100 // Walk through the model tree looking for bookmark nodes of node type |
| 101 // |node_type| whose titles match |title|. |
| 102 int count = 0; |
| 103 while (iterator.has_next()) { |
| 104 const BookmarkNode* node = iterator.Next(); |
| 105 if ((node->type() == node_type) && (node->GetTitle() == title)) |
| 106 ++count; |
| 107 } |
| 108 return count; |
| 109 } |
| 110 |
| 111 // Checks if the favicon data in |bitmap_a| and |bitmap_b| are equivalent. |
| 112 // Returns true if they match. |
| 113 bool FaviconBitmapsMatch(const SkBitmap& bitmap_a, const SkBitmap& bitmap_b) { |
| 114 if (bitmap_a.getSize() == 0U && bitmap_a.getSize() == 0U) |
| 115 return true; |
| 116 if ((bitmap_a.getSize() != bitmap_b.getSize()) || |
| 117 (bitmap_a.width() != bitmap_b.width()) || |
| 118 (bitmap_a.height() != bitmap_b.height())) { |
| 119 LOG(ERROR) << "Favicon size mismatch: " << bitmap_a.getSize() << " (" |
| 120 << bitmap_a.width() << "x" << bitmap_a.height() << ") vs. " |
| 121 << bitmap_b.getSize() << " (" << bitmap_b.width() << "x" |
| 122 << bitmap_b.height() << ")"; |
| 123 return false; |
| 124 } |
| 125 SkAutoLockPixels bitmap_lock_a(bitmap_a); |
| 126 SkAutoLockPixels bitmap_lock_b(bitmap_b); |
| 127 void* node_pixel_addr_a = bitmap_a.getPixels(); |
| 128 EXPECT_TRUE(node_pixel_addr_a); |
| 129 void* node_pixel_addr_b = bitmap_b.getPixels(); |
| 130 EXPECT_TRUE(node_pixel_addr_b); |
| 131 if (memcmp(node_pixel_addr_a, node_pixel_addr_b, bitmap_a.getSize()) != 0) { |
| 132 LOG(ERROR) << "Favicon bitmap mismatch"; |
| 133 return false; |
| 134 } else { |
| 135 return true; |
| 136 } |
| 137 } |
| 138 |
| 139 // Gets the favicon associated with |node| in |model|. |
| 140 const SkBitmap& GetFavicon(BookmarkModel* model, const BookmarkNode* node) { |
| 141 // If a favicon wasn't explicitly set for a particular URL, simply return its |
| 142 // blank favicon. |
| 143 if (!urls_with_favicons_ || |
| 144 urls_with_favicons_->find(node->url()) == urls_with_favicons_->end()) { |
| 145 return node->favicon(); |
| 146 } |
| 147 // If a favicon was explicitly set, we may need to wait for it to be loaded |
| 148 // via BookmarkModel::GetFavIcon(), which is an asynchronous operation. |
| 149 if (!node->is_favicon_loaded()) { |
| 150 FaviconChangeObserver observer(model, node); |
| 151 model->GetFavicon(node); |
| 152 observer.WaitForGetFavicon(); |
| 153 } |
| 154 EXPECT_TRUE(node->is_favicon_loaded()); |
| 155 return node->favicon(); |
| 156 } |
| 157 |
| 158 // Checks if the favicon in |node_a| from |model_a| matches that of |node_b| |
| 159 // from |model_b|. Returns true if they match. |
| 160 bool FaviconsMatch(BookmarkModel* model_a, |
| 161 BookmarkModel* model_b, |
| 162 const BookmarkNode* node_a, |
| 163 const BookmarkNode* node_b) { |
| 164 const SkBitmap& bitmap_a = GetFavicon(model_a, node_a); |
| 165 const SkBitmap& bitmap_b = GetFavicon(model_b, node_b); |
| 166 return FaviconBitmapsMatch(bitmap_a, bitmap_b); |
| 167 } |
| 168 |
| 169 // Does a deep comparison of BookmarkNode fields in |model_a| and |model_b|. |
| 170 // Returns true if they are all equal. |
| 171 bool NodesMatch(const BookmarkNode* node_a, const BookmarkNode* node_b) { |
| 172 if (node_a == NULL || node_b == NULL) |
| 173 return node_a == node_b; |
| 174 if (node_a->is_folder() != node_b->is_folder()) { |
| 175 LOG(ERROR) << "Cannot compare folder with bookmark"; |
| 176 return false; |
| 177 } |
| 178 if (node_a->GetTitle() != node_b->GetTitle()) { |
| 179 LOG(ERROR) << "Title mismatch: " << node_a->GetTitle() << " vs. " |
| 180 << node_b->GetTitle(); |
| 181 return false; |
| 182 } |
| 183 if (node_a->url() != node_b->url()) { |
| 184 LOG(ERROR) << "URL mismatch: " << node_a->url() << " vs. " |
| 185 << node_b->url(); |
| 186 return false; |
| 187 } |
| 188 if (node_a->parent()->GetIndexOf(node_a) != |
| 189 node_b->parent()->GetIndexOf(node_b)) { |
| 190 LOG(ERROR) << "Index mismatch: " |
| 191 << node_a->parent()->GetIndexOf(node_a) << " vs. " |
| 192 << node_b->parent()->GetIndexOf(node_b); |
| 193 return false; |
| 194 } |
| 195 return true; |
| 196 } |
| 197 |
| 198 // Checks if the hierarchies in |model_a| and |model_b| are equivalent in |
| 199 // terms of the data model and favicon. Returns true if they both match. |
| 200 // Note: Some peripheral fields like creation times are allowed to mismatch. |
| 201 bool BookmarkModelsMatch(BookmarkModel* model_a, BookmarkModel* model_b) { |
| 202 bool ret_val = true; |
| 203 ui::TreeNodeIterator<const BookmarkNode> iterator_a(model_a->root_node()); |
| 204 ui::TreeNodeIterator<const BookmarkNode> iterator_b(model_b->root_node()); |
| 205 while (iterator_a.has_next()) { |
| 206 const BookmarkNode* node_a = iterator_a.Next(); |
| 207 if (!iterator_b.has_next()) { |
| 208 LOG(ERROR) << "Models do not match."; |
| 209 return false; |
| 210 } |
| 211 const BookmarkNode* node_b = iterator_b.Next(); |
| 212 ret_val = ret_val && NodesMatch(node_a, node_b); |
| 213 if (node_a->is_folder() || node_b->is_folder()) |
| 214 continue; |
| 215 ret_val = ret_val && FaviconsMatch(model_a, model_b, node_a, node_b); |
| 216 } |
| 217 ret_val = ret_val && (!iterator_b.has_next()); |
| 218 return ret_val; |
| 219 } |
| 220 |
| 221 // Finds the node in the verifier bookmark model that corresponds to |
| 222 // |foreign_node| in |foreign_model| and stores its address in |result|. |
| 223 void FindNodeInVerifier(BookmarkModel* foreign_model, |
| 224 const BookmarkNode* foreign_node, |
| 225 const BookmarkNode** result) { |
| 226 // Climb the tree. |
| 227 std::stack<int> path; |
| 228 const BookmarkNode* walker = foreign_node; |
| 229 while (walker != foreign_model->root_node()) { |
| 230 path.push(walker->parent()->GetIndexOf(walker)); |
| 231 walker = walker->parent(); |
| 232 } |
| 233 |
| 234 // Swing over to the other tree. |
| 235 walker = bookmarks_helper::GetVerifierBookmarkModel()->root_node(); |
| 236 |
| 237 // Climb down. |
| 238 while (!path.empty()) { |
| 239 ASSERT_TRUE(walker->is_folder()); |
| 240 ASSERT_LT(path.top(), walker->child_count()); |
| 241 walker = walker->GetChild(path.top()); |
| 242 path.pop(); |
| 243 } |
| 244 |
| 245 ASSERT_TRUE(NodesMatch(foreign_node, walker)); |
| 246 *result = walker; |
| 247 } |
| 248 |
85 } // namespace | 249 } // namespace |
86 | 250 |
87 BookmarksHelper::BookmarksHelper() {} | 251 |
88 | 252 namespace bookmarks_helper { |
89 BookmarksHelper::~BookmarksHelper() {} | 253 |
90 | 254 BookmarkModel* GetBookmarkModel(int index) { |
91 // static | |
92 BookmarkModel* BookmarksHelper::GetBookmarkModel(int index) { | |
93 return test()->GetProfile(index)->GetBookmarkModel(); | 255 return test()->GetProfile(index)->GetBookmarkModel(); |
94 } | 256 } |
95 | 257 |
96 // static | 258 const BookmarkNode* GetBookmarkBarNode(int index) { |
97 const BookmarkNode* BookmarksHelper::GetBookmarkBarNode(int index) { | |
98 return GetBookmarkModel(index)->bookmark_bar_node(); | 259 return GetBookmarkModel(index)->bookmark_bar_node(); |
99 } | 260 } |
100 | 261 |
101 // static | 262 const BookmarkNode* GetOtherNode(int index) { |
102 const BookmarkNode* BookmarksHelper::GetOtherNode(int index) { | |
103 return GetBookmarkModel(index)->other_node(); | 263 return GetBookmarkModel(index)->other_node(); |
104 } | 264 } |
105 | 265 |
106 // static | 266 BookmarkModel* GetVerifierBookmarkModel() { |
107 BookmarkModel* BookmarksHelper::GetVerifierBookmarkModel() { | |
108 return test()->verifier()->GetBookmarkModel(); | 267 return test()->verifier()->GetBookmarkModel(); |
109 } | 268 } |
110 | 269 |
111 // static | 270 bool EnableEncryption(int index) { |
112 bool BookmarksHelper::EnableEncryption(int index) { | |
113 return test()->GetClient(index)->EnableEncryptionForType(syncable::BOOKMARKS); | 271 return test()->GetClient(index)->EnableEncryptionForType(syncable::BOOKMARKS); |
114 } | 272 } |
115 | 273 |
116 // static | 274 bool IsEncrypted(int index) { |
117 bool BookmarksHelper::IsEncrypted(int index) { | |
118 return test()->GetClient(index)->IsTypeEncrypted(syncable::BOOKMARKS); | 275 return test()->GetClient(index)->IsTypeEncrypted(syncable::BOOKMARKS); |
119 } | 276 } |
120 | 277 |
121 // static | 278 const BookmarkNode* AddURL(int profile, |
122 const BookmarkNode* BookmarksHelper::AddURL(int profile, | 279 const std::wstring& title, |
123 const std::wstring& title, | 280 const GURL& url) { |
124 const GURL& url) { | |
125 return AddURL(profile, GetBookmarkBarNode(profile), 0, title, url); | 281 return AddURL(profile, GetBookmarkBarNode(profile), 0, title, url); |
126 } | 282 } |
127 | 283 |
128 // static | 284 const BookmarkNode* AddURL(int profile, |
129 const BookmarkNode* BookmarksHelper::AddURL(int profile, | 285 int index, |
130 int index, | 286 const std::wstring& title, |
131 const std::wstring& title, | 287 const GURL& url) { |
132 const GURL& url) { | |
133 return AddURL(profile, GetBookmarkBarNode(profile), index, title, url); | 288 return AddURL(profile, GetBookmarkBarNode(profile), index, title, url); |
134 } | 289 } |
135 | 290 |
136 // static | 291 const BookmarkNode* AddURL(int profile, |
137 const BookmarkNode* BookmarksHelper::AddURL(int profile, | 292 const BookmarkNode* parent, |
138 const BookmarkNode* parent, | 293 int index, |
139 int index, | 294 const std::wstring& title, |
140 const std::wstring& title, | 295 const GURL& url) { |
141 const GURL& url) { | |
142 if (GetBookmarkModel(profile)->GetNodeByID(parent->id()) != parent) { | 296 if (GetBookmarkModel(profile)->GetNodeByID(parent->id()) != parent) { |
143 LOG(ERROR) << "Node " << parent->GetTitle() << " does not belong to " | 297 LOG(ERROR) << "Node " << parent->GetTitle() << " does not belong to " |
144 << "Profile " << profile; | 298 << "Profile " << profile; |
145 return NULL; | 299 return NULL; |
146 } | 300 } |
147 const BookmarkNode* result = GetBookmarkModel(profile)-> | 301 const BookmarkNode* result = GetBookmarkModel(profile)-> |
148 AddURL(parent, index, WideToUTF16(title), url); | 302 AddURL(parent, index, WideToUTF16(title), url); |
149 if (!result) { | 303 if (!result) { |
150 LOG(ERROR) << "Could not add bookmark " << title << " to Profile " | 304 LOG(ERROR) << "Could not add bookmark " << title << " to Profile " |
151 << profile; | 305 << profile; |
152 return NULL; | 306 return NULL; |
153 } | 307 } |
154 if (test()->use_verifier()) { | 308 if (test()->use_verifier()) { |
155 const BookmarkNode* v_parent = NULL; | 309 const BookmarkNode* v_parent = NULL; |
156 FindNodeInVerifier(GetBookmarkModel(profile), parent, &v_parent); | 310 FindNodeInVerifier(GetBookmarkModel(profile), parent, &v_parent); |
157 const BookmarkNode* v_node = GetVerifierBookmarkModel()-> | 311 const BookmarkNode* v_node = GetVerifierBookmarkModel()-> |
158 AddURL(v_parent, index, WideToUTF16(title), url); | 312 AddURL(v_parent, index, WideToUTF16(title), url); |
159 if (!v_node) { | 313 if (!v_node) { |
160 LOG(ERROR) << "Could not add bookmark " << title << " to the verifier"; | 314 LOG(ERROR) << "Could not add bookmark " << title << " to the verifier"; |
161 return NULL; | 315 return NULL; |
162 } | 316 } |
163 EXPECT_TRUE(NodesMatch(v_node, result)); | 317 EXPECT_TRUE(NodesMatch(v_node, result)); |
164 } | 318 } |
165 return result; | 319 return result; |
166 } | 320 } |
167 | 321 |
168 // static | 322 const BookmarkNode* AddFolder(int profile, |
169 const BookmarkNode* BookmarksHelper::AddFolder(int profile, | 323 const std::wstring& title) { |
170 const std::wstring& title) { | |
171 return AddFolder(profile, GetBookmarkBarNode(profile), 0, title); | 324 return AddFolder(profile, GetBookmarkBarNode(profile), 0, title); |
172 } | 325 } |
173 | 326 |
174 // static | 327 const BookmarkNode* AddFolder(int profile, |
175 const BookmarkNode* BookmarksHelper::AddFolder(int profile, | 328 int index, |
176 int index, | 329 const std::wstring& title) { |
177 const std::wstring& title) { | |
178 return AddFolder(profile, GetBookmarkBarNode(profile), index, title); | 330 return AddFolder(profile, GetBookmarkBarNode(profile), index, title); |
179 } | 331 } |
180 | 332 |
181 // static | 333 const BookmarkNode* AddFolder(int profile, |
182 const BookmarkNode* BookmarksHelper::AddFolder(int profile, | 334 const BookmarkNode* parent, |
183 const BookmarkNode* parent, | 335 int index, |
184 int index, | 336 const std::wstring& title) { |
185 const std::wstring& title) { | |
186 if (GetBookmarkModel(profile)->GetNodeByID(parent->id()) != parent) { | 337 if (GetBookmarkModel(profile)->GetNodeByID(parent->id()) != parent) { |
187 LOG(ERROR) << "Node " << parent->GetTitle() << " does not belong to " | 338 LOG(ERROR) << "Node " << parent->GetTitle() << " does not belong to " |
188 << "Profile " << profile; | 339 << "Profile " << profile; |
189 return NULL; | 340 return NULL; |
190 } | 341 } |
191 const BookmarkNode* result = | 342 const BookmarkNode* result = |
192 GetBookmarkModel(profile)->AddFolder(parent, index, WideToUTF16(title)); | 343 GetBookmarkModel(profile)->AddFolder(parent, index, WideToUTF16(title)); |
193 EXPECT_TRUE(result); | 344 EXPECT_TRUE(result); |
194 if (!result) { | 345 if (!result) { |
195 LOG(ERROR) << "Could not add folder " << title << " to Profile " | 346 LOG(ERROR) << "Could not add folder " << title << " to Profile " |
196 << profile; | 347 << profile; |
197 return NULL; | 348 return NULL; |
198 } | 349 } |
199 if (test()->use_verifier()) { | 350 if (test()->use_verifier()) { |
200 const BookmarkNode* v_parent = NULL; | 351 const BookmarkNode* v_parent = NULL; |
201 FindNodeInVerifier(GetBookmarkModel(profile), parent, &v_parent); | 352 FindNodeInVerifier(GetBookmarkModel(profile), parent, &v_parent); |
202 const BookmarkNode* v_node = GetVerifierBookmarkModel()->AddFolder( | 353 const BookmarkNode* v_node = GetVerifierBookmarkModel()->AddFolder( |
203 v_parent, index, WideToUTF16(title)); | 354 v_parent, index, WideToUTF16(title)); |
204 if (!v_node) { | 355 if (!v_node) { |
205 LOG(ERROR) << "Could not add folder " << title << " to the verifier"; | 356 LOG(ERROR) << "Could not add folder " << title << " to the verifier"; |
206 return NULL; | 357 return NULL; |
207 } | 358 } |
208 EXPECT_TRUE(NodesMatch(v_node, result)); | 359 EXPECT_TRUE(NodesMatch(v_node, result)); |
209 } | 360 } |
210 return result; | 361 return result; |
211 } | 362 } |
212 | 363 |
213 // static | 364 void SetTitle(int profile, |
214 void BookmarksHelper::SetTitle(int profile, | 365 const BookmarkNode* node, |
215 const BookmarkNode* node, | 366 const std::wstring& new_title) { |
216 const std::wstring& new_title) { | |
217 ASSERT_EQ(GetBookmarkModel(profile)->GetNodeByID(node->id()), node) | 367 ASSERT_EQ(GetBookmarkModel(profile)->GetNodeByID(node->id()), node) |
218 << "Node " << node->GetTitle() << " does not belong to " | 368 << "Node " << node->GetTitle() << " does not belong to " |
219 << "Profile " << profile; | 369 << "Profile " << profile; |
220 if (test()->use_verifier()) { | 370 if (test()->use_verifier()) { |
221 const BookmarkNode* v_node = NULL; | 371 const BookmarkNode* v_node = NULL; |
222 FindNodeInVerifier(GetBookmarkModel(profile), node, &v_node); | 372 FindNodeInVerifier(GetBookmarkModel(profile), node, &v_node); |
223 GetVerifierBookmarkModel()->SetTitle(v_node, WideToUTF16(new_title)); | 373 GetVerifierBookmarkModel()->SetTitle(v_node, WideToUTF16(new_title)); |
224 } | 374 } |
225 GetBookmarkModel(profile)->SetTitle(node, WideToUTF16(new_title)); | 375 GetBookmarkModel(profile)->SetTitle(node, WideToUTF16(new_title)); |
226 } | 376 } |
227 | 377 |
228 // static | 378 void SetFavicon(int profile, |
229 void BookmarksHelper::SetFavicon( | 379 const BookmarkNode* node, |
230 int profile, | 380 const std::vector<unsigned char>& icon_bytes_vector) { |
231 const BookmarkNode* node, | |
232 const std::vector<unsigned char>& icon_bytes_vector) { | |
233 ASSERT_EQ(GetBookmarkModel(profile)->GetNodeByID(node->id()), node) | 381 ASSERT_EQ(GetBookmarkModel(profile)->GetNodeByID(node->id()), node) |
234 << "Node " << node->GetTitle() << " does not belong to " | 382 << "Node " << node->GetTitle() << " does not belong to " |
235 << "Profile " << profile; | 383 << "Profile " << profile; |
236 ASSERT_EQ(BookmarkNode::URL, node->type()) | 384 ASSERT_EQ(BookmarkNode::URL, node->type()) |
237 << "Node " << node->GetTitle() << " must be a url."; | 385 << "Node " << node->GetTitle() << " must be a url."; |
238 if (urls_with_favicons_ == NULL) | 386 if (urls_with_favicons_ == NULL) |
239 urls_with_favicons_ = new std::set<GURL>(); | 387 urls_with_favicons_ = new std::set<GURL>(); |
240 urls_with_favicons_->insert(node->url()); | 388 urls_with_favicons_->insert(node->url()); |
241 if (test()->use_verifier()) { | 389 if (test()->use_verifier()) { |
242 const BookmarkNode* v_node = NULL; | 390 const BookmarkNode* v_node = NULL; |
243 FindNodeInVerifier(GetBookmarkModel(profile), node, &v_node); | 391 FindNodeInVerifier(GetBookmarkModel(profile), node, &v_node); |
244 FaviconChangeObserver v_observer(GetVerifierBookmarkModel(), v_node); | 392 FaviconChangeObserver v_observer(GetVerifierBookmarkModel(), v_node); |
245 browser_sync::BookmarkChangeProcessor::ApplyBookmarkFavicon( | 393 browser_sync::BookmarkChangeProcessor::ApplyBookmarkFavicon( |
246 v_node, test()->verifier(), icon_bytes_vector); | 394 v_node, test()->verifier(), icon_bytes_vector); |
247 v_observer.WaitForSetFavicon(); | 395 v_observer.WaitForSetFavicon(); |
248 } | 396 } |
249 FaviconChangeObserver observer(GetBookmarkModel(profile), node); | 397 FaviconChangeObserver observer(GetBookmarkModel(profile), node); |
250 browser_sync::BookmarkChangeProcessor::ApplyBookmarkFavicon( | 398 browser_sync::BookmarkChangeProcessor::ApplyBookmarkFavicon( |
251 node, test()->GetProfile(profile), icon_bytes_vector); | 399 node, test()->GetProfile(profile), icon_bytes_vector); |
252 observer.WaitForSetFavicon(); | 400 observer.WaitForSetFavicon(); |
253 } | 401 } |
254 | 402 |
255 // static | 403 const BookmarkNode* SetURL(int profile, |
256 const BookmarkNode* BookmarksHelper::SetURL(int profile, | 404 const BookmarkNode* node, |
257 const BookmarkNode* node, | 405 const GURL& new_url) { |
258 const GURL& new_url) { | |
259 if (GetBookmarkModel(profile)->GetNodeByID(node->id()) != node) { | 406 if (GetBookmarkModel(profile)->GetNodeByID(node->id()) != node) { |
260 LOG(ERROR) << "Node " << node->GetTitle() << " does not belong to " | 407 LOG(ERROR) << "Node " << node->GetTitle() << " does not belong to " |
261 << "Profile " << profile; | 408 << "Profile " << profile; |
262 return NULL; | 409 return NULL; |
263 } | 410 } |
264 if (test()->use_verifier()) { | 411 if (test()->use_verifier()) { |
265 const BookmarkNode* v_node = NULL; | 412 const BookmarkNode* v_node = NULL; |
266 FindNodeInVerifier(GetBookmarkModel(profile), node, &v_node); | 413 FindNodeInVerifier(GetBookmarkModel(profile), node, &v_node); |
267 bookmark_utils::ApplyEditsWithNoFolderChange( | 414 bookmark_utils::ApplyEditsWithNoFolderChange( |
268 GetVerifierBookmarkModel(), | 415 GetVerifierBookmarkModel(), |
269 v_node->parent(), | 416 v_node->parent(), |
270 BookmarkEditor::EditDetails(v_node), | 417 BookmarkEditor::EditDetails(v_node), |
271 v_node->GetTitle(), | 418 v_node->GetTitle(), |
272 new_url); | 419 new_url); |
273 } | 420 } |
274 return bookmark_utils::ApplyEditsWithNoFolderChange( | 421 return bookmark_utils::ApplyEditsWithNoFolderChange( |
275 GetBookmarkModel(profile), | 422 GetBookmarkModel(profile), |
276 node->parent(), | 423 node->parent(), |
277 BookmarkEditor::EditDetails(node), | 424 BookmarkEditor::EditDetails(node), |
278 node->GetTitle(), | 425 node->GetTitle(), |
279 new_url); | 426 new_url); |
280 } | 427 } |
281 | 428 |
282 // static | 429 void Move(int profile, |
283 void BookmarksHelper::Move(int profile, | 430 const BookmarkNode* node, |
284 const BookmarkNode* node, | 431 const BookmarkNode* new_parent, |
285 const BookmarkNode* new_parent, | 432 int index) { |
286 int index) { | |
287 ASSERT_EQ(GetBookmarkModel(profile)->GetNodeByID(node->id()), node) | 433 ASSERT_EQ(GetBookmarkModel(profile)->GetNodeByID(node->id()), node) |
288 << "Node " << node->GetTitle() << " does not belong to " | 434 << "Node " << node->GetTitle() << " does not belong to " |
289 << "Profile " << profile; | 435 << "Profile " << profile; |
290 if (test()->use_verifier()) { | 436 if (test()->use_verifier()) { |
291 const BookmarkNode* v_new_parent = NULL; | 437 const BookmarkNode* v_new_parent = NULL; |
292 const BookmarkNode* v_node = NULL; | 438 const BookmarkNode* v_node = NULL; |
293 FindNodeInVerifier(GetBookmarkModel(profile), new_parent, &v_new_parent); | 439 FindNodeInVerifier(GetBookmarkModel(profile), new_parent, &v_new_parent); |
294 FindNodeInVerifier(GetBookmarkModel(profile), node, &v_node); | 440 FindNodeInVerifier(GetBookmarkModel(profile), node, &v_node); |
295 GetVerifierBookmarkModel()->Move(v_node, v_new_parent, index); | 441 GetVerifierBookmarkModel()->Move(v_node, v_new_parent, index); |
296 } | 442 } |
297 GetBookmarkModel(profile)->Move(node, new_parent, index); | 443 GetBookmarkModel(profile)->Move(node, new_parent, index); |
298 } | 444 } |
299 | 445 |
300 // static | 446 void Remove(int profile, |
301 void BookmarksHelper::Remove(int profile, | 447 const BookmarkNode* parent, |
302 const BookmarkNode* parent, | 448 int index) { |
303 int index) { | |
304 ASSERT_EQ(GetBookmarkModel(profile)->GetNodeByID(parent->id()), parent) | 449 ASSERT_EQ(GetBookmarkModel(profile)->GetNodeByID(parent->id()), parent) |
305 << "Node " << parent->GetTitle() << " does not belong to " | 450 << "Node " << parent->GetTitle() << " does not belong to " |
306 << "Profile " << profile; | 451 << "Profile " << profile; |
307 if (test()->use_verifier()) { | 452 if (test()->use_verifier()) { |
308 const BookmarkNode* v_parent = NULL; | 453 const BookmarkNode* v_parent = NULL; |
309 FindNodeInVerifier(GetBookmarkModel(profile), parent, &v_parent); | 454 FindNodeInVerifier(GetBookmarkModel(profile), parent, &v_parent); |
310 ASSERT_TRUE(NodesMatch(parent->GetChild(index), v_parent->GetChild(index))); | 455 ASSERT_TRUE(NodesMatch(parent->GetChild(index), v_parent->GetChild(index))); |
311 GetVerifierBookmarkModel()->Remove(v_parent, index); | 456 GetVerifierBookmarkModel()->Remove(v_parent, index); |
312 } | 457 } |
313 GetBookmarkModel(profile)->Remove(parent, index); | 458 GetBookmarkModel(profile)->Remove(parent, index); |
314 } | 459 } |
315 | 460 |
316 // static | 461 void SortChildren(int profile, const BookmarkNode* parent) { |
317 void BookmarksHelper::SortChildren(int profile, | |
318 const BookmarkNode* parent) { | |
319 ASSERT_EQ(GetBookmarkModel(profile)->GetNodeByID(parent->id()), parent) | 462 ASSERT_EQ(GetBookmarkModel(profile)->GetNodeByID(parent->id()), parent) |
320 << "Node " << parent->GetTitle() << " does not belong to " | 463 << "Node " << parent->GetTitle() << " does not belong to " |
321 << "Profile " << profile; | 464 << "Profile " << profile; |
322 if (test()->use_verifier()) { | 465 if (test()->use_verifier()) { |
323 const BookmarkNode* v_parent = NULL; | 466 const BookmarkNode* v_parent = NULL; |
324 FindNodeInVerifier(GetBookmarkModel(profile), parent, &v_parent); | 467 FindNodeInVerifier(GetBookmarkModel(profile), parent, &v_parent); |
325 GetVerifierBookmarkModel()->SortChildren(v_parent); | 468 GetVerifierBookmarkModel()->SortChildren(v_parent); |
326 } | 469 } |
327 GetBookmarkModel(profile)->SortChildren(parent); | 470 GetBookmarkModel(profile)->SortChildren(parent); |
328 } | 471 } |
329 | 472 |
330 // static | 473 void ReverseChildOrder(int profile, const BookmarkNode* parent) { |
331 void BookmarksHelper::ReverseChildOrder(int profile, | |
332 const BookmarkNode* parent) { | |
333 ASSERT_EQ(GetBookmarkModel(profile)->GetNodeByID(parent->id()), parent) | 474 ASSERT_EQ(GetBookmarkModel(profile)->GetNodeByID(parent->id()), parent) |
334 << "Node " << parent->GetTitle() << " does not belong to " | 475 << "Node " << parent->GetTitle() << " does not belong to " |
335 << "Profile " << profile; | 476 << "Profile " << profile; |
336 int child_count = parent->child_count(); | 477 int child_count = parent->child_count(); |
337 if (child_count <= 0) | 478 if (child_count <= 0) |
338 return; | 479 return; |
339 for (int index = 0; index < child_count; ++index) { | 480 for (int index = 0; index < child_count; ++index) { |
340 Move(profile, parent->GetChild(index), parent, child_count - index); | 481 Move(profile, parent->GetChild(index), parent, child_count - index); |
341 } | 482 } |
342 } | 483 } |
343 | 484 |
344 // static | 485 bool ModelMatchesVerifier(int profile) { |
345 bool BookmarksHelper::ModelMatchesVerifier(int profile) { | |
346 if (!test()->use_verifier()) { | 486 if (!test()->use_verifier()) { |
347 LOG(ERROR) << "Illegal to call ModelMatchesVerifier() after " | 487 LOG(ERROR) << "Illegal to call ModelMatchesVerifier() after " |
348 << "DisableVerifier(). Use ModelsMatch() instead."; | 488 << "DisableVerifier(). Use ModelsMatch() instead."; |
349 return false; | 489 return false; |
350 } | 490 } |
351 return BookmarkModelsMatch(GetVerifierBookmarkModel(), | 491 return BookmarkModelsMatch(GetVerifierBookmarkModel(), |
352 GetBookmarkModel(profile)); | 492 GetBookmarkModel(profile)); |
353 } | 493 } |
354 | 494 |
355 // static | 495 bool AllModelsMatchVerifier() { |
356 bool BookmarksHelper::AllModelsMatchVerifier() { | |
357 for (int i = 0; i < test()->num_clients(); ++i) { | 496 for (int i = 0; i < test()->num_clients(); ++i) { |
358 if (!ModelMatchesVerifier(i)) { | 497 if (!ModelMatchesVerifier(i)) { |
359 LOG(ERROR) << "Model " << i << " does not match the verifier."; | 498 LOG(ERROR) << "Model " << i << " does not match the verifier."; |
360 return false; | 499 return false; |
361 } | 500 } |
362 } | 501 } |
363 return true; | 502 return true; |
364 } | 503 } |
365 | 504 |
366 // static | 505 bool ModelsMatch(int profile_a, int profile_b) { |
367 bool BookmarksHelper::ModelsMatch(int profile_a, int profile_b) { | |
368 return BookmarkModelsMatch(GetBookmarkModel(profile_a), | 506 return BookmarkModelsMatch(GetBookmarkModel(profile_a), |
369 GetBookmarkModel(profile_b)); | 507 GetBookmarkModel(profile_b)); |
370 } | 508 } |
371 | 509 |
372 // static | 510 bool AllModelsMatch() { |
373 bool BookmarksHelper::AllModelsMatch() { | |
374 for (int i = 1; i < test()->num_clients(); ++i) { | 511 for (int i = 1; i < test()->num_clients(); ++i) { |
375 if (!ModelsMatch(0, i)) { | 512 if (!ModelsMatch(0, i)) { |
376 LOG(ERROR) << "Model " << i << " does not match Model 0."; | 513 LOG(ERROR) << "Model " << i << " does not match Model 0."; |
377 return false; | 514 return false; |
378 } | 515 } |
379 } | 516 } |
380 return true; | 517 return true; |
381 } | 518 } |
382 | 519 |
383 // static | 520 bool ContainsDuplicateBookmarks(int profile) { |
384 bool BookmarksHelper::ContainsDuplicateBookmarks(int profile) { | |
385 ui::TreeNodeIterator<const BookmarkNode> iterator( | 521 ui::TreeNodeIterator<const BookmarkNode> iterator( |
386 GetBookmarkModel(profile)->root_node()); | 522 GetBookmarkModel(profile)->root_node()); |
387 while (iterator.has_next()) { | 523 while (iterator.has_next()) { |
388 const BookmarkNode* node = iterator.Next(); | 524 const BookmarkNode* node = iterator.Next(); |
389 if (node->is_folder()) | 525 if (node->is_folder()) |
390 continue; | 526 continue; |
391 std::vector<const BookmarkNode*> nodes; | 527 std::vector<const BookmarkNode*> nodes; |
392 GetBookmarkModel(profile)->GetNodesByURL(node->url(), &nodes); | 528 GetBookmarkModel(profile)->GetNodesByURL(node->url(), &nodes); |
393 EXPECT_TRUE(nodes.size() >= 1); | 529 EXPECT_TRUE(nodes.size() >= 1); |
394 for (std::vector<const BookmarkNode*>::const_iterator it = nodes.begin(); | 530 for (std::vector<const BookmarkNode*>::const_iterator it = nodes.begin(); |
395 it != nodes.end(); ++it) { | 531 it != nodes.end(); ++it) { |
396 if (node->id() != (*it)->id() && | 532 if (node->id() != (*it)->id() && |
397 node->parent() == (*it)->parent() && | 533 node->parent() == (*it)->parent() && |
398 node->GetTitle() == (*it)->GetTitle()){ | 534 node->GetTitle() == (*it)->GetTitle()){ |
399 return true; | 535 return true; |
400 } | 536 } |
401 } | 537 } |
402 } | 538 } |
403 return false; | 539 return false; |
404 } | 540 } |
405 | 541 |
406 // static | 542 const BookmarkNode* GetUniqueNodeByURL(int profile, const GURL& url) { |
407 const BookmarkNode* BookmarksHelper::GetUniqueNodeByURL(int profile, | |
408 const GURL& url) { | |
409 std::vector<const BookmarkNode*> nodes; | 543 std::vector<const BookmarkNode*> nodes; |
410 GetBookmarkModel(profile)->GetNodesByURL(url, &nodes); | 544 GetBookmarkModel(profile)->GetNodesByURL(url, &nodes); |
411 EXPECT_EQ(1U, nodes.size()); | 545 EXPECT_EQ(1U, nodes.size()); |
412 if (nodes.empty()) | 546 if (nodes.empty()) |
413 return NULL; | 547 return NULL; |
414 return nodes[0]; | 548 return nodes[0]; |
415 } | 549 } |
416 | 550 |
417 // static | 551 int CountBookmarksWithTitlesMatching(int profile, const std::wstring& title) { |
418 int BookmarksHelper::CountBookmarksWithTitlesMatching( | |
419 int profile, | |
420 const std::wstring& title) { | |
421 return CountNodesWithTitlesMatching(GetBookmarkModel(profile), | 552 return CountNodesWithTitlesMatching(GetBookmarkModel(profile), |
422 BookmarkNode::URL, | 553 BookmarkNode::URL, |
423 WideToUTF16(title)); | 554 WideToUTF16(title)); |
424 } | 555 } |
425 | 556 |
426 // static | 557 int CountFoldersWithTitlesMatching(int profile, const std::wstring& title) { |
427 int BookmarksHelper::CountFoldersWithTitlesMatching( | |
428 int profile, | |
429 const std::wstring& title) { | |
430 return CountNodesWithTitlesMatching(GetBookmarkModel(profile), | 558 return CountNodesWithTitlesMatching(GetBookmarkModel(profile), |
431 BookmarkNode::FOLDER, | 559 BookmarkNode::FOLDER, |
432 WideToUTF16(title)); | 560 WideToUTF16(title)); |
433 } | 561 } |
434 | 562 |
435 // static | 563 std::vector<unsigned char> CreateFavicon(int seed) { |
436 int BookmarksHelper::CountNodesWithTitlesMatching( | |
437 BookmarkModel* model, | |
438 BookmarkNode::Type node_type, | |
439 const string16& title) { | |
440 ui::TreeNodeIterator<const BookmarkNode> iterator(model->root_node()); | |
441 // Walk through the model tree looking for bookmark nodes of node type | |
442 // |node_type| whose titles match |title|. | |
443 int count = 0; | |
444 while (iterator.has_next()) { | |
445 const BookmarkNode* node = iterator.Next(); | |
446 if ((node->type() == node_type) && (node->GetTitle() == title)) | |
447 ++count; | |
448 } | |
449 return count; | |
450 } | |
451 | |
452 // static | |
453 std::vector<unsigned char> BookmarksHelper::CreateFavicon(int seed) { | |
454 const int w = 16; | 564 const int w = 16; |
455 const int h = 16; | 565 const int h = 16; |
456 SkBitmap bmp; | 566 SkBitmap bmp; |
457 bmp.setConfig(SkBitmap::kARGB_8888_Config, w, h); | 567 bmp.setConfig(SkBitmap::kARGB_8888_Config, w, h); |
458 bmp.allocPixels(); | 568 bmp.allocPixels(); |
459 uint32_t* src_data = bmp.getAddr32(0, 0); | 569 uint32_t* src_data = bmp.getAddr32(0, 0); |
460 for (int i = 0; i < w * h; ++i) { | 570 for (int i = 0; i < w * h; ++i) { |
461 src_data[i] = SkPreMultiplyARGB((seed + i) % 255, | 571 src_data[i] = SkPreMultiplyARGB((seed + i) % 255, |
462 (seed + i) % 250, | 572 (seed + i) % 250, |
463 (seed + i) % 245, | 573 (seed + i) % 245, |
464 (seed + i) % 240); | 574 (seed + i) % 240); |
465 } | 575 } |
466 std::vector<unsigned char> favicon; | 576 std::vector<unsigned char> favicon; |
467 gfx::PNGCodec::EncodeBGRASkBitmap(bmp, false, &favicon); | 577 gfx::PNGCodec::EncodeBGRASkBitmap(bmp, false, &favicon); |
468 return favicon; | 578 return favicon; |
469 } | 579 } |
470 | 580 |
471 // static | 581 std::string IndexedURL(int i) { |
472 std::string BookmarksHelper::IndexedURL(int i) { | |
473 return StringPrintf("http://www.host.ext:1234/path/filename/%d", i); | 582 return StringPrintf("http://www.host.ext:1234/path/filename/%d", i); |
474 } | 583 } |
475 | 584 |
476 // static | 585 std::wstring IndexedURLTitle(int i) { |
477 std::wstring BookmarksHelper::IndexedURLTitle(int i) { | |
478 return StringPrintf(L"URL Title %d", i); | 586 return StringPrintf(L"URL Title %d", i); |
479 } | 587 } |
480 | 588 |
481 // static | 589 std::wstring IndexedFolderName(int i) { |
482 std::wstring BookmarksHelper::IndexedFolderName(int i) { | |
483 return StringPrintf(L"Folder Name %d", i); | 590 return StringPrintf(L"Folder Name %d", i); |
484 } | 591 } |
485 | 592 |
486 // static | 593 std::wstring IndexedSubfolderName(int i) { |
487 std::wstring BookmarksHelper::IndexedSubfolderName(int i) { | |
488 return StringPrintf(L"Subfolder Name %d", i); | 594 return StringPrintf(L"Subfolder Name %d", i); |
489 } | 595 } |
490 | 596 |
491 // static | 597 std::wstring IndexedSubsubfolderName(int i) { |
492 std::wstring BookmarksHelper::IndexedSubsubfolderName(int i) { | |
493 return StringPrintf(L"Subsubfolder Name %d", i); | 598 return StringPrintf(L"Subsubfolder Name %d", i); |
494 } | 599 } |
495 | 600 |
496 // static | 601 } // namespace bookmarks_helper |
497 void BookmarksHelper::FindNodeInVerifier(BookmarkModel* foreign_model, | |
498 const BookmarkNode* foreign_node, | |
499 const BookmarkNode** result) { | |
500 // Climb the tree. | |
501 std::stack<int> path; | |
502 const BookmarkNode* walker = foreign_node; | |
503 while (walker != foreign_model->root_node()) { | |
504 path.push(walker->parent()->GetIndexOf(walker)); | |
505 walker = walker->parent(); | |
506 } | |
507 | |
508 // Swing over to the other tree. | |
509 walker = GetVerifierBookmarkModel()->root_node(); | |
510 | |
511 // Climb down. | |
512 while (!path.empty()) { | |
513 ASSERT_TRUE(walker->is_folder()); | |
514 ASSERT_LT(path.top(), walker->child_count()); | |
515 walker = walker->GetChild(path.top()); | |
516 path.pop(); | |
517 } | |
518 | |
519 ASSERT_TRUE(NodesMatch(foreign_node, walker)); | |
520 *result = walker; | |
521 } | |
522 | |
523 // static | |
524 bool BookmarksHelper::BookmarkModelsMatch(BookmarkModel* model_a, | |
525 BookmarkModel* model_b) { | |
526 bool ret_val = true; | |
527 ui::TreeNodeIterator<const BookmarkNode> iterator_a(model_a->root_node()); | |
528 ui::TreeNodeIterator<const BookmarkNode> iterator_b(model_b->root_node()); | |
529 while (iterator_a.has_next()) { | |
530 const BookmarkNode* node_a = iterator_a.Next(); | |
531 if (!iterator_b.has_next()) { | |
532 LOG(ERROR) << "Models do not match."; | |
533 return false; | |
534 } | |
535 const BookmarkNode* node_b = iterator_b.Next(); | |
536 ret_val = ret_val && NodesMatch(node_a, node_b); | |
537 if (node_a->is_folder() || node_b->is_folder()) | |
538 continue; | |
539 ret_val = ret_val && FaviconsMatch(model_a, model_b, node_a, node_b); | |
540 } | |
541 ret_val = ret_val && (!iterator_b.has_next()); | |
542 return ret_val; | |
543 } | |
544 | |
545 // static | |
546 bool BookmarksHelper::NodesMatch(const BookmarkNode* node_a, | |
547 const BookmarkNode* node_b) { | |
548 if (node_a == NULL || node_b == NULL) | |
549 return node_a == node_b; | |
550 if (node_a->is_folder() != node_b->is_folder()) { | |
551 LOG(ERROR) << "Cannot compare folder with bookmark"; | |
552 return false; | |
553 } | |
554 if (node_a->GetTitle() != node_b->GetTitle()) { | |
555 LOG(ERROR) << "Title mismatch: " << node_a->GetTitle() << " vs. " | |
556 << node_b->GetTitle(); | |
557 return false; | |
558 } | |
559 if (node_a->url() != node_b->url()) { | |
560 LOG(ERROR) << "URL mismatch: " << node_a->url() << " vs. " | |
561 << node_b->url(); | |
562 return false; | |
563 } | |
564 if (node_a->parent()->GetIndexOf(node_a) != | |
565 node_b->parent()->GetIndexOf(node_b)) { | |
566 LOG(ERROR) << "Index mismatch: " | |
567 << node_a->parent()->GetIndexOf(node_a) << " vs. " | |
568 << node_b->parent()->GetIndexOf(node_b); | |
569 return false; | |
570 } | |
571 return true; | |
572 } | |
573 | |
574 // static | |
575 bool BookmarksHelper::FaviconsMatch(BookmarkModel* model_a, | |
576 BookmarkModel* model_b, | |
577 const BookmarkNode* node_a, | |
578 const BookmarkNode* node_b) { | |
579 const SkBitmap& bitmap_a = GetFavicon(model_a, node_a); | |
580 const SkBitmap& bitmap_b = GetFavicon(model_b, node_b); | |
581 return FaviconBitmapsMatch(bitmap_a, bitmap_b); | |
582 } | |
583 | |
584 // static | |
585 const SkBitmap& BookmarksHelper::GetFavicon(BookmarkModel* model, | |
586 const BookmarkNode* node) { | |
587 // If a favicon wasn't explicitly set for a particular URL, simply return its | |
588 // blank favicon. | |
589 if (!urls_with_favicons_ || | |
590 urls_with_favicons_->find(node->url()) == urls_with_favicons_->end()) { | |
591 return node->favicon(); | |
592 } | |
593 // If a favicon was explicitly set, we may need to wait for it to be loaded | |
594 // via BookmarkModel::GetFavIcon(), which is an asynchronous operation. | |
595 if (!node->is_favicon_loaded()) { | |
596 FaviconChangeObserver observer(model, node); | |
597 model->GetFavicon(node); | |
598 observer.WaitForGetFavicon(); | |
599 } | |
600 EXPECT_TRUE(node->is_favicon_loaded()); | |
601 return node->favicon(); | |
602 } | |
603 | |
604 // static | |
605 bool BookmarksHelper::FaviconBitmapsMatch(const SkBitmap& bitmap_a, | |
606 const SkBitmap& bitmap_b) { | |
607 if (bitmap_a.getSize() == 0U && bitmap_a.getSize() == 0U) | |
608 return true; | |
609 if ((bitmap_a.getSize() != bitmap_b.getSize()) || | |
610 (bitmap_a.width() != bitmap_b.width()) || | |
611 (bitmap_a.height() != bitmap_b.height())) { | |
612 LOG(ERROR) << "Favicon size mismatch: " << bitmap_a.getSize() << " (" | |
613 << bitmap_a.width() << "x" << bitmap_a.height() << ") vs. " | |
614 << bitmap_b.getSize() << " (" << bitmap_b.width() << "x" | |
615 << bitmap_b.height() << ")"; | |
616 return false; | |
617 } | |
618 SkAutoLockPixels bitmap_lock_a(bitmap_a); | |
619 SkAutoLockPixels bitmap_lock_b(bitmap_b); | |
620 void* node_pixel_addr_a = bitmap_a.getPixels(); | |
621 EXPECT_TRUE(node_pixel_addr_a); | |
622 void* node_pixel_addr_b = bitmap_b.getPixels(); | |
623 EXPECT_TRUE(node_pixel_addr_b); | |
624 if (memcmp(node_pixel_addr_a, node_pixel_addr_b, bitmap_a.getSize()) != 0) { | |
625 LOG(ERROR) << "Favicon bitmap mismatch"; | |
626 return false; | |
627 } else { | |
628 return true; | |
629 } | |
630 } | |
631 | |
632 // static | |
633 std::set<GURL>* BookmarksHelper::urls_with_favicons_ = NULL; | |
OLD | NEW |