OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/test/live_sync/bookmarks_helper.h" | |
6 | |
7 #include "base/rand_util.h" | |
8 #include "base/string_number_conversions.h" | |
9 #include "base/stringprintf.h" | |
10 #include "base/utf_string_conversions.h" | |
11 #include "chrome/browser/bookmarks/bookmark_model.h" | |
12 #include "chrome/browser/bookmarks/bookmark_model_observer.h" | |
13 #include "chrome/browser/bookmarks/bookmark_utils.h" | |
14 #include "chrome/browser/profiles/profile.h" | |
15 #include "chrome/browser/sync/glue/bookmark_change_processor.h" | |
16 #include "chrome/browser/sync/profile_sync_service_harness.h" | |
17 #include "chrome/test/base/ui_test_utils.h" | |
18 #include "chrome/test/live_sync/live_sync_test.h" | |
19 #include "chrome/test/live_sync/sync_datatype_helper.h" | |
20 #include "testing/gtest/include/gtest/gtest.h" | |
21 #include "third_party/skia/include/core/SkBitmap.h" | |
22 #include "ui/base/models/tree_node_iterator.h" | |
23 #include "ui/gfx/codec/png_codec.h" | |
24 | |
25 using sync_datatype_helper::test; | |
26 | |
27 namespace { | |
28 | |
29 // Helper class used to wait for changes to take effect on the favicon of a | |
30 // particular bookmark node in a particular bookmark model. | |
31 class FaviconChangeObserver : public BookmarkModelObserver { | |
32 public: | |
33 FaviconChangeObserver(BookmarkModel* model, const BookmarkNode* node) | |
34 : model_(model), | |
35 node_(node), | |
36 wait_for_load_(false) { | |
37 model->AddObserver(this); | |
38 } | |
39 virtual ~FaviconChangeObserver() { | |
40 model_->RemoveObserver(this); | |
41 } | |
42 void WaitForGetFavicon() { | |
43 wait_for_load_ = true; | |
44 ui_test_utils::RunMessageLoop(); | |
45 ASSERT_TRUE(node_->is_favicon_loaded()); | |
46 } | |
47 void WaitForSetFavicon() { | |
48 wait_for_load_ = false; | |
49 ui_test_utils::RunMessageLoop(); | |
50 } | |
51 virtual void Loaded(BookmarkModel* model, bool ids_reassigned) OVERRIDE {} | |
52 virtual void BookmarkNodeMoved(BookmarkModel* model, | |
53 const BookmarkNode* old_parent, | |
54 int old_index, | |
55 const BookmarkNode* new_parent, | |
56 int new_index) OVERRIDE {} | |
57 virtual void BookmarkNodeAdded(BookmarkModel* model, | |
58 const BookmarkNode* parent, | |
59 int index) OVERRIDE {} | |
60 virtual void BookmarkNodeRemoved(BookmarkModel* model, | |
61 const BookmarkNode* parent, | |
62 int old_index, | |
63 const BookmarkNode* node) OVERRIDE {} | |
64 virtual void BookmarkNodeChanged(BookmarkModel* model, | |
65 const BookmarkNode* node) OVERRIDE { | |
66 if (model == model_ && node == node_) | |
67 model->GetFavicon(node); | |
68 } | |
69 virtual void BookmarkNodeChildrenReordered( | |
70 BookmarkModel* model, | |
71 const BookmarkNode* node) OVERRIDE {} | |
72 virtual void BookmarkNodeFaviconChanged( | |
73 BookmarkModel* model, | |
74 const BookmarkNode* node) OVERRIDE { | |
75 if (model == model_ && node == node_) { | |
76 if (!wait_for_load_ || (wait_for_load_ && node->is_favicon_loaded())) | |
77 MessageLoopForUI::current()->Quit(); | |
78 } | |
79 } | |
80 | |
81 private: | |
82 BookmarkModel* model_; | |
83 const BookmarkNode* node_; | |
84 bool wait_for_load_; | |
85 DISALLOW_COPY_AND_ASSIGN(FaviconChangeObserver); | |
86 }; | |
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 | |
249 } // namespace | |
250 | |
251 | |
252 namespace bookmarks_helper { | |
253 | |
254 BookmarkModel* GetBookmarkModel(int index) { | |
255 return test()->GetProfile(index)->GetBookmarkModel(); | |
256 } | |
257 | |
258 const BookmarkNode* GetBookmarkBarNode(int index) { | |
259 return GetBookmarkModel(index)->bookmark_bar_node(); | |
260 } | |
261 | |
262 const BookmarkNode* GetOtherNode(int index) { | |
263 return GetBookmarkModel(index)->other_node(); | |
264 } | |
265 | |
266 BookmarkModel* GetVerifierBookmarkModel() { | |
267 return test()->verifier()->GetBookmarkModel(); | |
268 } | |
269 | |
270 const BookmarkNode* AddURL(int profile, | |
271 const std::wstring& title, | |
272 const GURL& url) { | |
273 return AddURL(profile, GetBookmarkBarNode(profile), 0, title, url); | |
274 } | |
275 | |
276 const BookmarkNode* AddURL(int profile, | |
277 int index, | |
278 const std::wstring& title, | |
279 const GURL& url) { | |
280 return AddURL(profile, GetBookmarkBarNode(profile), index, title, url); | |
281 } | |
282 | |
283 const BookmarkNode* AddURL(int profile, | |
284 const BookmarkNode* parent, | |
285 int index, | |
286 const std::wstring& title, | |
287 const GURL& url) { | |
288 if (GetBookmarkModel(profile)->GetNodeByID(parent->id()) != parent) { | |
289 LOG(ERROR) << "Node " << parent->GetTitle() << " does not belong to " | |
290 << "Profile " << profile; | |
291 return NULL; | |
292 } | |
293 const BookmarkNode* result = GetBookmarkModel(profile)-> | |
294 AddURL(parent, index, WideToUTF16(title), url); | |
295 if (!result) { | |
296 LOG(ERROR) << "Could not add bookmark " << title << " to Profile " | |
297 << profile; | |
298 return NULL; | |
299 } | |
300 if (test()->use_verifier()) { | |
301 const BookmarkNode* v_parent = NULL; | |
302 FindNodeInVerifier(GetBookmarkModel(profile), parent, &v_parent); | |
303 const BookmarkNode* v_node = GetVerifierBookmarkModel()-> | |
304 AddURL(v_parent, index, WideToUTF16(title), url); | |
305 if (!v_node) { | |
306 LOG(ERROR) << "Could not add bookmark " << title << " to the verifier"; | |
307 return NULL; | |
308 } | |
309 EXPECT_TRUE(NodesMatch(v_node, result)); | |
310 } | |
311 return result; | |
312 } | |
313 | |
314 const BookmarkNode* AddFolder(int profile, | |
315 const std::wstring& title) { | |
316 return AddFolder(profile, GetBookmarkBarNode(profile), 0, title); | |
317 } | |
318 | |
319 const BookmarkNode* AddFolder(int profile, | |
320 int index, | |
321 const std::wstring& title) { | |
322 return AddFolder(profile, GetBookmarkBarNode(profile), index, title); | |
323 } | |
324 | |
325 const BookmarkNode* AddFolder(int profile, | |
326 const BookmarkNode* parent, | |
327 int index, | |
328 const std::wstring& title) { | |
329 if (GetBookmarkModel(profile)->GetNodeByID(parent->id()) != parent) { | |
330 LOG(ERROR) << "Node " << parent->GetTitle() << " does not belong to " | |
331 << "Profile " << profile; | |
332 return NULL; | |
333 } | |
334 const BookmarkNode* result = | |
335 GetBookmarkModel(profile)->AddFolder(parent, index, WideToUTF16(title)); | |
336 EXPECT_TRUE(result); | |
337 if (!result) { | |
338 LOG(ERROR) << "Could not add folder " << title << " to Profile " | |
339 << profile; | |
340 return NULL; | |
341 } | |
342 if (test()->use_verifier()) { | |
343 const BookmarkNode* v_parent = NULL; | |
344 FindNodeInVerifier(GetBookmarkModel(profile), parent, &v_parent); | |
345 const BookmarkNode* v_node = GetVerifierBookmarkModel()->AddFolder( | |
346 v_parent, index, WideToUTF16(title)); | |
347 if (!v_node) { | |
348 LOG(ERROR) << "Could not add folder " << title << " to the verifier"; | |
349 return NULL; | |
350 } | |
351 EXPECT_TRUE(NodesMatch(v_node, result)); | |
352 } | |
353 return result; | |
354 } | |
355 | |
356 void SetTitle(int profile, | |
357 const BookmarkNode* node, | |
358 const std::wstring& new_title) { | |
359 ASSERT_EQ(GetBookmarkModel(profile)->GetNodeByID(node->id()), node) | |
360 << "Node " << node->GetTitle() << " does not belong to " | |
361 << "Profile " << profile; | |
362 if (test()->use_verifier()) { | |
363 const BookmarkNode* v_node = NULL; | |
364 FindNodeInVerifier(GetBookmarkModel(profile), node, &v_node); | |
365 GetVerifierBookmarkModel()->SetTitle(v_node, WideToUTF16(new_title)); | |
366 } | |
367 GetBookmarkModel(profile)->SetTitle(node, WideToUTF16(new_title)); | |
368 } | |
369 | |
370 void SetFavicon(int profile, | |
371 const BookmarkNode* node, | |
372 const std::vector<unsigned char>& icon_bytes_vector) { | |
373 ASSERT_EQ(GetBookmarkModel(profile)->GetNodeByID(node->id()), node) | |
374 << "Node " << node->GetTitle() << " does not belong to " | |
375 << "Profile " << profile; | |
376 ASSERT_EQ(BookmarkNode::URL, node->type()) | |
377 << "Node " << node->GetTitle() << " must be a url."; | |
378 if (urls_with_favicons_ == NULL) | |
379 urls_with_favicons_ = new std::set<GURL>(); | |
380 urls_with_favicons_->insert(node->url()); | |
381 if (test()->use_verifier()) { | |
382 const BookmarkNode* v_node = NULL; | |
383 FindNodeInVerifier(GetBookmarkModel(profile), node, &v_node); | |
384 FaviconChangeObserver v_observer(GetVerifierBookmarkModel(), v_node); | |
385 browser_sync::BookmarkChangeProcessor::ApplyBookmarkFavicon( | |
386 v_node, test()->verifier(), icon_bytes_vector); | |
387 v_observer.WaitForSetFavicon(); | |
388 } | |
389 FaviconChangeObserver observer(GetBookmarkModel(profile), node); | |
390 browser_sync::BookmarkChangeProcessor::ApplyBookmarkFavicon( | |
391 node, test()->GetProfile(profile), icon_bytes_vector); | |
392 observer.WaitForSetFavicon(); | |
393 } | |
394 | |
395 const BookmarkNode* SetURL(int profile, | |
396 const BookmarkNode* node, | |
397 const GURL& new_url) { | |
398 if (GetBookmarkModel(profile)->GetNodeByID(node->id()) != node) { | |
399 LOG(ERROR) << "Node " << node->GetTitle() << " does not belong to " | |
400 << "Profile " << profile; | |
401 return NULL; | |
402 } | |
403 if (test()->use_verifier()) { | |
404 const BookmarkNode* v_node = NULL; | |
405 FindNodeInVerifier(GetBookmarkModel(profile), node, &v_node); | |
406 bookmark_utils::ApplyEditsWithNoFolderChange( | |
407 GetVerifierBookmarkModel(), | |
408 v_node->parent(), | |
409 BookmarkEditor::EditDetails(v_node), | |
410 v_node->GetTitle(), | |
411 new_url); | |
412 } | |
413 return bookmark_utils::ApplyEditsWithNoFolderChange( | |
414 GetBookmarkModel(profile), | |
415 node->parent(), | |
416 BookmarkEditor::EditDetails(node), | |
417 node->GetTitle(), | |
418 new_url); | |
419 } | |
420 | |
421 void Move(int profile, | |
422 const BookmarkNode* node, | |
423 const BookmarkNode* new_parent, | |
424 int index) { | |
425 ASSERT_EQ(GetBookmarkModel(profile)->GetNodeByID(node->id()), node) | |
426 << "Node " << node->GetTitle() << " does not belong to " | |
427 << "Profile " << profile; | |
428 if (test()->use_verifier()) { | |
429 const BookmarkNode* v_new_parent = NULL; | |
430 const BookmarkNode* v_node = NULL; | |
431 FindNodeInVerifier(GetBookmarkModel(profile), new_parent, &v_new_parent); | |
432 FindNodeInVerifier(GetBookmarkModel(profile), node, &v_node); | |
433 GetVerifierBookmarkModel()->Move(v_node, v_new_parent, index); | |
434 } | |
435 GetBookmarkModel(profile)->Move(node, new_parent, index); | |
436 } | |
437 | |
438 void Remove(int profile, | |
439 const BookmarkNode* parent, | |
440 int index) { | |
441 ASSERT_EQ(GetBookmarkModel(profile)->GetNodeByID(parent->id()), parent) | |
442 << "Node " << parent->GetTitle() << " does not belong to " | |
443 << "Profile " << profile; | |
444 if (test()->use_verifier()) { | |
445 const BookmarkNode* v_parent = NULL; | |
446 FindNodeInVerifier(GetBookmarkModel(profile), parent, &v_parent); | |
447 ASSERT_TRUE(NodesMatch(parent->GetChild(index), v_parent->GetChild(index))); | |
448 GetVerifierBookmarkModel()->Remove(v_parent, index); | |
449 } | |
450 GetBookmarkModel(profile)->Remove(parent, index); | |
451 } | |
452 | |
453 void SortChildren(int profile, const BookmarkNode* parent) { | |
454 ASSERT_EQ(GetBookmarkModel(profile)->GetNodeByID(parent->id()), parent) | |
455 << "Node " << parent->GetTitle() << " does not belong to " | |
456 << "Profile " << profile; | |
457 if (test()->use_verifier()) { | |
458 const BookmarkNode* v_parent = NULL; | |
459 FindNodeInVerifier(GetBookmarkModel(profile), parent, &v_parent); | |
460 GetVerifierBookmarkModel()->SortChildren(v_parent); | |
461 } | |
462 GetBookmarkModel(profile)->SortChildren(parent); | |
463 } | |
464 | |
465 void ReverseChildOrder(int profile, const BookmarkNode* parent) { | |
466 ASSERT_EQ(GetBookmarkModel(profile)->GetNodeByID(parent->id()), parent) | |
467 << "Node " << parent->GetTitle() << " does not belong to " | |
468 << "Profile " << profile; | |
469 int child_count = parent->child_count(); | |
470 if (child_count <= 0) | |
471 return; | |
472 for (int index = 0; index < child_count; ++index) { | |
473 Move(profile, parent->GetChild(index), parent, child_count - index); | |
474 } | |
475 } | |
476 | |
477 bool ModelMatchesVerifier(int profile) { | |
478 if (!test()->use_verifier()) { | |
479 LOG(ERROR) << "Illegal to call ModelMatchesVerifier() after " | |
480 << "DisableVerifier(). Use ModelsMatch() instead."; | |
481 return false; | |
482 } | |
483 return BookmarkModelsMatch(GetVerifierBookmarkModel(), | |
484 GetBookmarkModel(profile)); | |
485 } | |
486 | |
487 bool AllModelsMatchVerifier() { | |
488 for (int i = 0; i < test()->num_clients(); ++i) { | |
489 if (!ModelMatchesVerifier(i)) { | |
490 LOG(ERROR) << "Model " << i << " does not match the verifier."; | |
491 return false; | |
492 } | |
493 } | |
494 return true; | |
495 } | |
496 | |
497 bool ModelsMatch(int profile_a, int profile_b) { | |
498 return BookmarkModelsMatch(GetBookmarkModel(profile_a), | |
499 GetBookmarkModel(profile_b)); | |
500 } | |
501 | |
502 bool AllModelsMatch() { | |
503 for (int i = 1; i < test()->num_clients(); ++i) { | |
504 if (!ModelsMatch(0, i)) { | |
505 LOG(ERROR) << "Model " << i << " does not match Model 0."; | |
506 return false; | |
507 } | |
508 } | |
509 return true; | |
510 } | |
511 | |
512 bool ContainsDuplicateBookmarks(int profile) { | |
513 ui::TreeNodeIterator<const BookmarkNode> iterator( | |
514 GetBookmarkModel(profile)->root_node()); | |
515 while (iterator.has_next()) { | |
516 const BookmarkNode* node = iterator.Next(); | |
517 if (node->is_folder()) | |
518 continue; | |
519 std::vector<const BookmarkNode*> nodes; | |
520 GetBookmarkModel(profile)->GetNodesByURL(node->url(), &nodes); | |
521 EXPECT_TRUE(nodes.size() >= 1); | |
522 for (std::vector<const BookmarkNode*>::const_iterator it = nodes.begin(); | |
523 it != nodes.end(); ++it) { | |
524 if (node->id() != (*it)->id() && | |
525 node->parent() == (*it)->parent() && | |
526 node->GetTitle() == (*it)->GetTitle()){ | |
527 return true; | |
528 } | |
529 } | |
530 } | |
531 return false; | |
532 } | |
533 | |
534 const BookmarkNode* GetUniqueNodeByURL(int profile, const GURL& url) { | |
535 std::vector<const BookmarkNode*> nodes; | |
536 GetBookmarkModel(profile)->GetNodesByURL(url, &nodes); | |
537 EXPECT_EQ(1U, nodes.size()); | |
538 if (nodes.empty()) | |
539 return NULL; | |
540 return nodes[0]; | |
541 } | |
542 | |
543 int CountBookmarksWithTitlesMatching(int profile, const std::wstring& title) { | |
544 return CountNodesWithTitlesMatching(GetBookmarkModel(profile), | |
545 BookmarkNode::URL, | |
546 WideToUTF16(title)); | |
547 } | |
548 | |
549 int CountFoldersWithTitlesMatching(int profile, const std::wstring& title) { | |
550 return CountNodesWithTitlesMatching(GetBookmarkModel(profile), | |
551 BookmarkNode::FOLDER, | |
552 WideToUTF16(title)); | |
553 } | |
554 | |
555 std::vector<unsigned char> CreateFavicon(int seed) { | |
556 const int w = 16; | |
557 const int h = 16; | |
558 SkBitmap bmp; | |
559 bmp.setConfig(SkBitmap::kARGB_8888_Config, w, h); | |
560 bmp.allocPixels(); | |
561 uint32_t* src_data = bmp.getAddr32(0, 0); | |
562 for (int i = 0; i < w * h; ++i) { | |
563 src_data[i] = SkPreMultiplyARGB((seed + i) % 255, | |
564 (seed + i) % 250, | |
565 (seed + i) % 245, | |
566 (seed + i) % 240); | |
567 } | |
568 std::vector<unsigned char> favicon; | |
569 gfx::PNGCodec::EncodeBGRASkBitmap(bmp, false, &favicon); | |
570 return favicon; | |
571 } | |
572 | |
573 std::string IndexedURL(int i) { | |
574 return StringPrintf("http://www.host.ext:1234/path/filename/%d", i); | |
575 } | |
576 | |
577 std::wstring IndexedURLTitle(int i) { | |
578 return StringPrintf(L"URL Title %d", i); | |
579 } | |
580 | |
581 std::wstring IndexedFolderName(int i) { | |
582 return StringPrintf(L"Folder Name %d", i); | |
583 } | |
584 | |
585 std::wstring IndexedSubfolderName(int i) { | |
586 return StringPrintf(L"Subfolder Name %d", i); | |
587 } | |
588 | |
589 std::wstring IndexedSubsubfolderName(int i) { | |
590 return StringPrintf(L"Subsubfolder Name %d", i); | |
591 } | |
592 | |
593 } // namespace bookmarks_helper | |
OLD | NEW |