bookmarks_helper.cc revision 5c02ac1a9c1b504631c0a3d2b6e737b5d738bae1
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/test/integration/bookmarks_helper.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/file_util.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/path_service.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/rand_util.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h" 14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/waitable_event.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/bookmarks/bookmark_model_factory.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/favicon/favicon_service_factory.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/favicon/favicon_util.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/history_db_task.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/history_service_factory.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/history_types.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync/glue/bookmark_change_processor.h" 24a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "chrome/browser/sync/test/integration/multi_client_status_change_checker.h" 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/sync/test/integration/profile_sync_service_harness.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/test/integration/sync_datatype_helper.h" 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sync/test/integration/sync_test.h" 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/chrome_paths.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/ui_test_utils.h" 305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "components/bookmarks/core/browser/bookmark_model.h" 315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "components/bookmarks/core/browser/bookmark_model_observer.h" 325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "components/bookmarks/core/browser/bookmark_utils.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/models/tree_node_iterator.h" 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/image/image_skia.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// History task which runs all pending tasks on the history thread and 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// signals when the tasks have completed. 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class HistoryEmptyTask : public history::HistoryDBTask { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit HistoryEmptyTask(base::WaitableEvent* done) : done_(done) {} 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual bool RunOnDBThread(history::HistoryBackend* backend, 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) history::HistoryDatabase* db) OVERRIDE { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RunAllPendingInMessageLoop(); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done_->Signal(); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void DoneRunOnMainThread() OVERRIDE {} 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~HistoryEmptyTask() {} 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::WaitableEvent* done_; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper class used to wait for changes to take effect on the favicon of a 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// particular bookmark node in a particular bookmark model. 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class FaviconChangeObserver : public BookmarkModelObserver { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FaviconChangeObserver(BookmarkModel* model, const BookmarkNode* node) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : model_(model), 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node_(node), 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wait_for_load_(false) { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model->AddObserver(this); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~FaviconChangeObserver() { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->RemoveObserver(this); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void WaitForGetFavicon() { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wait_for_load_ = true; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RunMessageLoop(); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(node_->is_favicon_loaded()); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_FALSE(model_->GetFavicon(node_).IsEmpty()); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void WaitForSetFavicon() { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wait_for_load_ = false; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RunMessageLoop(); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void BookmarkModelLoaded(BookmarkModel* model, 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool ids_reassigned) OVERRIDE {} 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void BookmarkNodeMoved(BookmarkModel* model, 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* old_parent, 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int old_index, 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* new_parent, 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int new_index) OVERRIDE {} 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void BookmarkNodeAdded(BookmarkModel* model, 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* parent, 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index) OVERRIDE {} 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void BookmarkNodeRemoved(BookmarkModel* model, 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* parent, 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int old_index, 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node) OVERRIDE {} 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual void BookmarkAllNodesRemoved(BookmarkModel* model) OVERRIDE {} 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void BookmarkNodeChanged(BookmarkModel* model, 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node) OVERRIDE { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (model == model_ && node == node_) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model->GetFavicon(node); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void BookmarkNodeChildrenReordered( 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkModel* model, 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node) OVERRIDE {} 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void BookmarkNodeFaviconChanged( 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkModel* model, 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node) OVERRIDE { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (model == model_ && node == node_) { 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!wait_for_load_ || (wait_for_load_ && node->is_favicon_loaded())) 11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::MessageLoopForUI::current()->Quit(); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkModel* model_; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node_; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool wait_for_load_; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(FaviconChangeObserver); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A collection of URLs for which we have added favicons. Since loading a 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// favicon is an asynchronous operation and doesn't necessarily invoke a 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// callback, this collection is used to determine if we must wait for a URL's 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// favicon to load or not. 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::set<GURL>* urls_with_favicons_ = NULL; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the number of nodes of node type |node_type| in |model| whose 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// titles match the string |title|. 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CountNodesWithTitlesMatching(BookmarkModel* model, 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode::Type node_type, 134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& title) { 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::TreeNodeIterator<const BookmarkNode> iterator(model->root_node()); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Walk through the model tree looking for bookmark nodes of node type 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |node_type| whose titles match |title|. 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count = 0; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (iterator.has_next()) { 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node = iterator.Next(); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((node->type() == node_type) && (node->GetTitle() == title)) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++count; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return count; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Checks if the favicon data in |bitmap_a| and |bitmap_b| are equivalent. 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if they match. 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FaviconBitmapsMatch(const SkBitmap& bitmap_a, const SkBitmap& bitmap_b) { 15058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (bitmap_a.getSize() == 0U && bitmap_b.getSize() == 0U) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((bitmap_a.getSize() != bitmap_b.getSize()) || 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (bitmap_a.width() != bitmap_b.width()) || 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (bitmap_a.height() != bitmap_b.height())) { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Favicon size mismatch: " << bitmap_a.getSize() << " (" 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << bitmap_a.width() << "x" << bitmap_a.height() << ") vs. " 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << bitmap_b.getSize() << " (" << bitmap_b.width() << "x" 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << bitmap_b.height() << ")"; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkAutoLockPixels bitmap_lock_a(bitmap_a); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkAutoLockPixels bitmap_lock_b(bitmap_b); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* node_pixel_addr_a = bitmap_a.getPixels(); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(node_pixel_addr_a); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* node_pixel_addr_b = bitmap_b.getPixels(); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(node_pixel_addr_b); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (memcmp(node_pixel_addr_a, node_pixel_addr_b, bitmap_a.getSize()) != 0) { 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Favicon bitmap mismatch"; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Represents a favicon image and the icon URL associated with it. 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct FaviconData { 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FaviconData() { 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FaviconData(const gfx::Image& favicon_image, 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& favicon_url) 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : image(favicon_image), 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_url(favicon_url) { 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ~FaviconData() { 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Image image; 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GURL icon_url; 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Gets the favicon and icon URL associated with |node| in |model|. 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FaviconData GetFaviconData(BookmarkModel* model, 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const BookmarkNode* node) { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If a favicon wasn't explicitly set for a particular URL, simply return its 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // blank favicon. 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!urls_with_favicons_ || 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) urls_with_favicons_->find(node->url()) == urls_with_favicons_->end()) { 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return FaviconData(); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If a favicon was explicitly set, we may need to wait for it to be loaded 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // via BookmarkModel::GetFavicon(), which is an asynchronous operation. 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!node->is_favicon_loaded()) { 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FaviconChangeObserver observer(model, node); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model->GetFavicon(node); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observer.WaitForGetFavicon(); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(node->is_favicon_loaded()); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(model->GetFavicon(node).IsEmpty()); 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return FaviconData(model->GetFavicon(node), node->icon_url()); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Sets the favicon for |profile| and |node|. |profile| may be 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |test()->verifier()|. 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetFaviconImpl(Profile* profile, 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node, 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& icon_url, 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Image& image, 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bookmarks_helper::FaviconSource favicon_source) { 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkModel* model = BookmarkModelFactory::GetForProfile(profile); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FaviconChangeObserver observer(model, node); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FaviconService* favicon_service = 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FaviconServiceFactory::GetForProfile(profile, 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile::EXPLICIT_ACCESS); 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_source == bookmarks_helper::FROM_UI) { 2280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch favicon_service->SetFavicons( 2290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch node->url(), icon_url, favicon_base::FAVICON, image); 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) browser_sync::BookmarkChangeProcessor::ApplyBookmarkFavicon( 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) node, profile, icon_url, image.As1xPNGBytes()); 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Wait for the favicon for |node| to be invalidated. 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observer.WaitForSetFavicon(); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Wait for the BookmarkModel to fetch the updated favicon and for the new 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // favicon to be sent to BookmarkChangeProcessor. 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetFaviconData(model, node); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Wait for all currently scheduled tasks on the history thread for all 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// profiles to complete and any notifications sent to the UI thread to have 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// finished processing. 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WaitForHistoryToProcessPendingTasks() { 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Skip waiting for history to complete for tests without favicons. 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!urls_with_favicons_) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<Profile*> profiles_which_need_to_wait; 2515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (sync_datatype_helper::test()->use_verifier()) 2525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu profiles_which_need_to_wait.push_back( 2535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu sync_datatype_helper::test()->verifier()); 2545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (int i = 0; i < sync_datatype_helper::test()->num_clients(); ++i) 2555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu profiles_which_need_to_wait.push_back( 2565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu sync_datatype_helper::test()->GetProfile(i)); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < profiles_which_need_to_wait.size(); ++i) { 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile = profiles_which_need_to_wait[i]; 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HistoryService* history_service = 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HistoryServiceFactory::GetForProfileWithoutCreating(profile); 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::WaitableEvent done(false, false); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelableRequestConsumer request_consumer; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) history_service->ScheduleDBTask(new HistoryEmptyTask(&done), 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &request_consumer); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) done.Wait(); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Wait such that any notifications broadcast from one of the history threads 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to the UI thread are processed. 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RunAllPendingInMessageLoop(); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Checks if the favicon in |node_a| from |model_a| matches that of |node_b| 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from |model_b|. Returns true if they match. 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FaviconsMatch(BookmarkModel* model_a, 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkModel* model_b, 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node_a, 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node_b) { 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FaviconData favicon_data_a = GetFaviconData(model_a, node_a); 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FaviconData favicon_data_b = GetFaviconData(model_b, node_b); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (favicon_data_a.icon_url != favicon_data_b.icon_url) 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Image image_a = favicon_data_a.image; 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Image image_b = favicon_data_b.image; 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (image_a.IsEmpty() && image_b.IsEmpty()) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; // Two empty images are equivalent. 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (image_a.IsEmpty() != image_b.IsEmpty()) 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Compare only the 1x bitmaps as only those are synced. 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SkBitmap bitmap_a = image_a.AsImageSkia().GetRepresentation( 29668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 1.0f).sk_bitmap(); 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SkBitmap bitmap_b = image_b.AsImageSkia().GetRepresentation( 29868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 1.0f).sk_bitmap(); 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return FaviconBitmapsMatch(bitmap_a, bitmap_b); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Does a deep comparison of BookmarkNode fields in |model_a| and |model_b|. 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if they are all equal. 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NodesMatch(const BookmarkNode* node_a, const BookmarkNode* node_b) { 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (node_a == NULL || node_b == NULL) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return node_a == node_b; 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (node_a->is_folder() != node_b->is_folder()) { 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Cannot compare folder with bookmark"; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (node_a->GetTitle() != node_b->GetTitle()) { 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Title mismatch: " << node_a->GetTitle() << " vs. " 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << node_b->GetTitle(); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (node_a->url() != node_b->url()) { 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "URL mismatch: " << node_a->url() << " vs. " 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << node_b->url(); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (node_a->parent()->GetIndexOf(node_a) != 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node_b->parent()->GetIndexOf(node_b)) { 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Index mismatch: " 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << node_a->parent()->GetIndexOf(node_a) << " vs. " 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << node_b->parent()->GetIndexOf(node_b); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Checks if the hierarchies in |model_a| and |model_b| are equivalent in 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// terms of the data model and favicon. Returns true if they both match. 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note: Some peripheral fields like creation times are allowed to mismatch. 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BookmarkModelsMatch(BookmarkModel* model_a, BookmarkModel* model_b) { 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ret_val = true; 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::TreeNodeIterator<const BookmarkNode> iterator_a(model_a->root_node()); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::TreeNodeIterator<const BookmarkNode> iterator_b(model_b->root_node()); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (iterator_a.has_next()) { 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node_a = iterator_a.Next(); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!iterator_b.has_next()) { 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Models do not match."; 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node_b = iterator_b.Next(); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret_val = ret_val && NodesMatch(node_a, node_b); 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (node_a->is_folder() || node_b->is_folder()) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret_val = ret_val && FaviconsMatch(model_a, model_b, node_a, node_b); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret_val = ret_val && (!iterator_b.has_next()); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret_val; 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Finds the node in the verifier bookmark model that corresponds to 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |foreign_node| in |foreign_model| and stores its address in |result|. 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FindNodeInVerifier(BookmarkModel* foreign_model, 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* foreign_node, 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode** result) { 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Climb the tree. 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::stack<int> path; 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* walker = foreign_node; 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (walker != foreign_model->root_node()) { 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path.push(walker->parent()->GetIndexOf(walker)); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) walker = walker->parent(); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Swing over to the other tree. 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) walker = bookmarks_helper::GetVerifierBookmarkModel()->root_node(); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Climb down. 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!path.empty()) { 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(walker->is_folder()); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_LT(path.top(), walker->child_count()); 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) walker = walker->GetChild(path.top()); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path.pop(); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(NodesMatch(foreign_node, walker)); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *result = walker; 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace bookmarks_helper { 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BookmarkModel* GetBookmarkModel(int index) { 3885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return BookmarkModelFactory::GetForProfile( 3895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu sync_datatype_helper::test()->GetProfile(index)); 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BookmarkNode* GetBookmarkBarNode(int index) { 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetBookmarkModel(index)->bookmark_bar_node(); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BookmarkNode* GetOtherNode(int index) { 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetBookmarkModel(index)->other_node(); 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BookmarkNode* GetSyncedBookmarksNode(int index) { 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetBookmarkModel(index)->mobile_node(); 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BookmarkModel* GetVerifierBookmarkModel() { 4055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return BookmarkModelFactory::GetForProfile( 4065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu sync_datatype_helper::test()->verifier()); 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BookmarkNode* AddURL(int profile, 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::wstring& title, 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url) { 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return AddURL(profile, GetBookmarkBarNode(profile), 0, title, url); 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BookmarkNode* AddURL(int profile, 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index, 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::wstring& title, 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url) { 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return AddURL(profile, GetBookmarkBarNode(profile), index, title, url); 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BookmarkNode* AddURL(int profile, 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* parent, 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index, 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::wstring& title, 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url) { 4270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch BookmarkModel* model = GetBookmarkModel(profile); 4280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (GetBookmarkNodeByID(model, parent->id()) != parent) { 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Node " << parent->GetTitle() << " does not belong to " 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Profile " << profile; 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const BookmarkNode* result = 4340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch model->AddURL(parent, index, base::WideToUTF16(title), url); 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!result) { 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Could not add bookmark " << title << " to Profile " 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << profile; 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (sync_datatype_helper::test()->use_verifier()) { 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* v_parent = NULL; 4420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch FindNodeInVerifier(model, parent, &v_parent); 4430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const BookmarkNode* v_node = GetVerifierBookmarkModel()->AddURL( 4440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch v_parent, index, base::WideToUTF16(title), url); 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!v_node) { 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Could not add bookmark " << title << " to the verifier"; 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(NodesMatch(v_node, result)); 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BookmarkNode* AddFolder(int profile, 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::wstring& title) { 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return AddFolder(profile, GetBookmarkBarNode(profile), 0, title); 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BookmarkNode* AddFolder(int profile, 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index, 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::wstring& title) { 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return AddFolder(profile, GetBookmarkBarNode(profile), index, title); 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BookmarkNode* AddFolder(int profile, 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* parent, 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index, 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::wstring& title) { 4690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch BookmarkModel* model = GetBookmarkModel(profile); 4700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (GetBookmarkNodeByID(model, parent->id()) != parent) { 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Node " << parent->GetTitle() << " does not belong to " 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Profile " << profile; 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const BookmarkNode* result = 4760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch model->AddFolder(parent, index, base::WideToUTF16(title)); 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(result); 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!result) { 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Could not add folder " << title << " to Profile " 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << profile; 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (sync_datatype_helper::test()->use_verifier()) { 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* v_parent = NULL; 4850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch FindNodeInVerifier(model, parent, &v_parent); 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* v_node = GetVerifierBookmarkModel()->AddFolder( 4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v_parent, index, base::WideToUTF16(title)); 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!v_node) { 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Could not add folder " << title << " to the verifier"; 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(NodesMatch(v_node, result)); 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetTitle(int profile, 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node, 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::wstring& new_title) { 5000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch BookmarkModel* model = GetBookmarkModel(profile); 5010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_EQ(GetBookmarkNodeByID(model, node->id()), node) 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Node " << node->GetTitle() << " does not belong to " 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Profile " << profile; 5045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (sync_datatype_helper::test()->use_verifier()) { 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* v_node = NULL; 5060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch FindNodeInVerifier(model, node, &v_node); 5075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetVerifierBookmarkModel()->SetTitle(v_node, base::WideToUTF16(new_title)); 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch model->SetTitle(node, base::WideToUTF16(new_title)); 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetFavicon(int profile, 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node, 5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& icon_url, 5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Image& image, 5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FaviconSource favicon_source) { 5170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch BookmarkModel* model = GetBookmarkModel(profile); 5180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_EQ(GetBookmarkNodeByID(model, node->id()), node) 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Node " << node->GetTitle() << " does not belong to " 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Profile " << profile; 5210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_EQ(BookmarkNode::URL, node->type()) << "Node " << node->GetTitle() 5220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch << " must be a url."; 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (urls_with_favicons_ == NULL) 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) urls_with_favicons_ = new std::set<GURL>(); 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) urls_with_favicons_->insert(node->url()); 5265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (sync_datatype_helper::test()->use_verifier()) { 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* v_node = NULL; 5280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch FindNodeInVerifier(model, node, &v_node); 5295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SetFaviconImpl(sync_datatype_helper::test()->verifier(), 5305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu v_node, 5315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu icon_url, 5325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu image, 5335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu favicon_source); 5345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 5355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SetFaviconImpl(sync_datatype_helper::test()->GetProfile(profile), 5365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu node, 5375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu icon_url, 5385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu image, 5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) favicon_source); 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BookmarkNode* SetURL(int profile, 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node, 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& new_url) { 5450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch BookmarkModel* model = GetBookmarkModel(profile); 5460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (GetBookmarkNodeByID(model, node->id()) != node) { 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Node " << node->GetTitle() << " does not belong to " 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Profile " << profile; 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (sync_datatype_helper::test()->use_verifier()) { 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* v_node = NULL; 5530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch FindNodeInVerifier(model, node, &v_node); 554868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (v_node->is_url()) 555868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) GetVerifierBookmarkModel()->SetURL(v_node, new_url); 556868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 557868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (node->is_url()) 5580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch model->SetURL(node, new_url); 559868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return node; 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Move(int profile, 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node, 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* new_parent, 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index) { 5660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch BookmarkModel* model = GetBookmarkModel(profile); 5670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_EQ(GetBookmarkNodeByID(model, node->id()), node) 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Node " << node->GetTitle() << " does not belong to " 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Profile " << profile; 5705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (sync_datatype_helper::test()->use_verifier()) { 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* v_new_parent = NULL; 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* v_node = NULL; 5730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch FindNodeInVerifier(model, new_parent, &v_new_parent); 5740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch FindNodeInVerifier(model, node, &v_node); 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetVerifierBookmarkModel()->Move(v_node, v_new_parent, index); 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch model->Move(node, new_parent, index); 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid Remove(int profile, const BookmarkNode* parent, int index) { 5810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch BookmarkModel* model = GetBookmarkModel(profile); 5820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_EQ(GetBookmarkNodeByID(model, parent->id()), parent) 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Node " << parent->GetTitle() << " does not belong to " 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Profile " << profile; 5855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (sync_datatype_helper::test()->use_verifier()) { 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* v_parent = NULL; 5870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch FindNodeInVerifier(model, parent, &v_parent); 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(NodesMatch(parent->GetChild(index), v_parent->GetChild(index))); 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetVerifierBookmarkModel()->Remove(v_parent, index); 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5910529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch model->Remove(parent, index); 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 594c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RemoveAll(int profile) { 5955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (sync_datatype_helper::test()->use_verifier()) { 596c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const BookmarkNode* root_node = GetVerifierBookmarkModel()->root_node(); 597c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (int i = 0; i < root_node->child_count(); ++i) { 598c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const BookmarkNode* permanent_node = root_node->GetChild(i); 599c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (int j = permanent_node->child_count() - 1; j >= 0; --j) { 600c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GetVerifierBookmarkModel()->Remove(permanent_node, j); 601c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 602c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 603c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 604c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GetBookmarkModel(profile)->RemoveAll(); 605c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 606c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SortChildren(int profile, const BookmarkNode* parent) { 6080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch BookmarkModel* model = GetBookmarkModel(profile); 6090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_EQ(GetBookmarkNodeByID(model, parent->id()), parent) 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Node " << parent->GetTitle() << " does not belong to " 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Profile " << profile; 6125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (sync_datatype_helper::test()->use_verifier()) { 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* v_parent = NULL; 6140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch FindNodeInVerifier(model, parent, &v_parent); 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetVerifierBookmarkModel()->SortChildren(v_parent); 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch model->SortChildren(parent); 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ReverseChildOrder(int profile, const BookmarkNode* parent) { 6210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ASSERT_EQ(GetBookmarkNodeByID(GetBookmarkModel(profile), parent->id()), 6220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch parent) 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Node " << parent->GetTitle() << " does not belong to " 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Profile " << profile; 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int child_count = parent->child_count(); 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (child_count <= 0) 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int index = 0; index < child_count; ++index) { 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Move(profile, parent->GetChild(index), parent, child_count - index); 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ModelMatchesVerifier(int profile) { 6345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!sync_datatype_helper::test()->use_verifier()) { 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Illegal to call ModelMatchesVerifier() after " 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "DisableVerifier(). Use ModelsMatch() instead."; 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return BookmarkModelsMatch(GetVerifierBookmarkModel(), 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetBookmarkModel(profile)); 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AllModelsMatchVerifier() { 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ensure that all tasks have finished processing on the history thread 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and that any notifications the history thread may have sent have been 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // processed before comparing models. 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WaitForHistoryToProcessPendingTasks(); 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (int i = 0; i < sync_datatype_helper::test()->num_clients(); ++i) { 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ModelMatchesVerifier(i)) { 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Model " << i << " does not match the verifier."; 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ModelsMatch(int profile_a, int profile_b) { 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return BookmarkModelsMatch(GetBookmarkModel(profile_a), 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetBookmarkModel(profile_b)); 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AllModelsMatch() { 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ensure that all tasks have finished processing on the history thread 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and that any notifications the history thread may have sent have been 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // processed before comparing models. 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WaitForHistoryToProcessPendingTasks(); 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (int i = 1; i < sync_datatype_helper::test()->num_clients(); ++i) { 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ModelsMatch(0, i)) { 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Model " << i << " does not match Model 0."; 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 678a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochnamespace { 679a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 680a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// Helper class used in the implementation of AwaitAllModelsMatch. 681a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochclass AllModelsMatchChecker : public MultiClientStatusChangeChecker { 682a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch public: 683a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch AllModelsMatchChecker(); 684a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch virtual ~AllModelsMatchChecker(); 685a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 686a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch virtual bool IsExitConditionSatisfied() OVERRIDE; 687a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch virtual std::string GetDebugMessage() const OVERRIDE; 688a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}; 689a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 690a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochAllModelsMatchChecker::AllModelsMatchChecker() 691a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch : MultiClientStatusChangeChecker( 692a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch sync_datatype_helper::test()->GetSyncServices()) {} 693a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 694a02191e04bc25c4935f804f2c080ae28663d096dBen MurdochAllModelsMatchChecker::~AllModelsMatchChecker() {} 695a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 696a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochbool AllModelsMatchChecker::IsExitConditionSatisfied() { 697a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return AllModelsMatch(); 698a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch} 699a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 700a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochstd::string AllModelsMatchChecker::GetDebugMessage() const { 701a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return "Waiting for matching models"; 702a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch} 703a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 704a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch} // namespace 705a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 706a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochbool AwaitAllModelsMatch() { 707a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch AllModelsMatchChecker checker; 708a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch checker.Wait(); 709a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return !checker.TimedOut(); 710a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch} 711a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 712a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ContainsDuplicateBookmarks(int profile) { 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::TreeNodeIterator<const BookmarkNode> iterator( 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetBookmarkModel(profile)->root_node()); 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (iterator.has_next()) { 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BookmarkNode* node = iterator.Next(); 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (node->is_folder()) 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<const BookmarkNode*> nodes; 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetBookmarkModel(profile)->GetNodesByURL(node->url(), &nodes); 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(nodes.size() >= 1); 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<const BookmarkNode*>::const_iterator it = nodes.begin(); 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != nodes.end(); ++it) { 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (node->id() != (*it)->id() && 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node->parent() == (*it)->parent() && 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node->GetTitle() == (*it)->GetTitle()){ 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HasNodeWithURL(int profile, const GURL& url) { 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<const BookmarkNode*> nodes; 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetBookmarkModel(profile)->GetNodesByURL(url, &nodes); 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !nodes.empty(); 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BookmarkNode* GetUniqueNodeByURL(int profile, const GURL& url) { 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<const BookmarkNode*> nodes; 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetBookmarkModel(profile)->GetNodesByURL(url, &nodes); 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1U, nodes.size()); 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (nodes.empty()) 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return nodes[0]; 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CountBookmarksWithTitlesMatching(int profile, const std::wstring& title) { 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CountNodesWithTitlesMatching(GetBookmarkModel(profile), 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode::URL, 7535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::WideToUTF16(title)); 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CountFoldersWithTitlesMatching(int profile, const std::wstring& title) { 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CountNodesWithTitlesMatching(GetBookmarkModel(profile), 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BookmarkNode::FOLDER, 7595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::WideToUTF16(title)); 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::Image CreateFavicon(SkColor color) { 7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int dip_width = 16; 7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int dip_height = 16; 7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<ui::ScaleFactor> favicon_scale_factors = 7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FaviconUtil::GetFaviconScaleFactors(); 7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::ImageSkia favicon; 7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < favicon_scale_factors.size(); ++i) { 76968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) float scale = ui::GetImageScale(favicon_scale_factors[i]); 7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int pixel_width = dip_width * scale; 7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int pixel_height = dip_height * scale; 7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SkBitmap bmp; 7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bmp.setConfig(SkBitmap::kARGB_8888_Config, pixel_width, pixel_height); 7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bmp.allocPixels(); 7752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bmp.eraseColor(color); 77668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) favicon.AddRepresentation( 77768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) gfx::ImageSkiaRep(bmp, 77868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ui::GetImageScale(favicon_scale_factors[i]))); 7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return gfx::Image(favicon); 7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::Image Create1xFaviconFromPNGFile(const std::string& path) { 7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char* kPNGExtension = ".png"; 7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!EndsWith(path, kPNGExtension, false)) 7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return gfx::Image(); 7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath full_path; 7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!PathService::Get(chrome::DIR_TEST_DATA, &full_path)) 7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return gfx::Image(); 7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) full_path = full_path.AppendASCII("sync").AppendASCII(path); 7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string contents; 79458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::ReadFileToString(full_path, &contents); 7952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return gfx::Image::CreateFrom1xPNGBytes( 7965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::RefCountedString::TakeString(&contents)); 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string IndexedURL(int i) { 8002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return base::StringPrintf("http://www.host.ext:1234/path/filename/%d", i); 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::wstring IndexedURLTitle(int i) { 8042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return base::StringPrintf(L"URL Title %d", i); 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::wstring IndexedFolderName(int i) { 8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return base::StringPrintf(L"Folder Name %d", i); 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::wstring IndexedSubfolderName(int i) { 8122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return base::StringPrintf(L"Subfolder Name %d", i); 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::wstring IndexedSubsubfolderName(int i) { 8162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return base::StringPrintf(L"Subsubfolder Name %d", i); 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace bookmarks_helper 820