1 // Copyright 2013 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/browser/bookmarks/bookmark_test_helpers.h" 6 7 #include "base/basictypes.h" 8 #include "base/callback.h" 9 #include "base/compiler_specific.h" 10 #include "base/logging.h" 11 #include "base/run_loop.h" 12 #include "base/strings/utf_string_conversions.h" 13 #include "chrome/browser/bookmarks/base_bookmark_model_observer.h" 14 #include "chrome/browser/bookmarks/bookmark_model.h" 15 #include "chrome/browser/bookmarks/bookmark_model_factory.h" 16 #include "content/public/test/test_utils.h" 17 #include "url/gurl.h" 18 19 namespace { 20 21 // BookmarkLoadObserver is used when blocking until the BookmarkModel finishes 22 // loading. As soon as the BookmarkModel finishes loading the message loop is 23 // quit. 24 class BookmarkLoadObserver : public BaseBookmarkModelObserver { 25 public: 26 explicit BookmarkLoadObserver(const base::Closure& quit_task); 27 virtual ~BookmarkLoadObserver(); 28 29 private: 30 // BaseBookmarkModelObserver: 31 virtual void BookmarkModelChanged() OVERRIDE; 32 virtual void Loaded(BookmarkModel* model, bool ids_reassigned) OVERRIDE; 33 34 base::Closure quit_task_; 35 36 DISALLOW_COPY_AND_ASSIGN(BookmarkLoadObserver); 37 }; 38 39 BookmarkLoadObserver::BookmarkLoadObserver(const base::Closure& quit_task) 40 : quit_task_(quit_task) {} 41 42 BookmarkLoadObserver::~BookmarkLoadObserver() {} 43 44 void BookmarkLoadObserver::BookmarkModelChanged() {} 45 46 void BookmarkLoadObserver::Loaded(BookmarkModel* model, bool ids_reassigned) { 47 quit_task_.Run(); 48 } 49 50 // Helper function which does the actual work of creating the nodes for 51 // a particular level in the hierarchy. 52 std::string::size_type AddNodesFromString(BookmarkModel* model, 53 const BookmarkNode* node, 54 const std::string& model_string, 55 std::string::size_type start_pos) { 56 DCHECK(node); 57 int index = node->child_count(); 58 static const std::string folder_tell(":["); 59 std::string::size_type end_pos = model_string.find(' ', start_pos); 60 while (end_pos != std::string::npos) { 61 std::string::size_type part_length = end_pos - start_pos; 62 std::string node_name = model_string.substr(start_pos, part_length); 63 // Are we at the end of a folder group? 64 if (node_name != "]") { 65 // No, is it a folder? 66 std::string tell; 67 if (part_length > 2) 68 tell = node_name.substr(part_length - 2, 2); 69 if (tell == folder_tell) { 70 node_name = node_name.substr(0, part_length - 2); 71 const BookmarkNode* new_node = 72 model->AddFolder(node, index, UTF8ToUTF16(node_name)); 73 end_pos = AddNodesFromString(model, new_node, model_string, 74 end_pos + 1); 75 } else { 76 std::string url_string("http://"); 77 url_string += std::string(node_name.begin(), node_name.end()); 78 url_string += ".com"; 79 model->AddURL(node, index, UTF8ToUTF16(node_name), GURL(url_string)); 80 ++end_pos; 81 } 82 ++index; 83 start_pos = end_pos; 84 end_pos = model_string.find(' ', start_pos); 85 } else { 86 ++end_pos; 87 break; 88 } 89 } 90 return end_pos; 91 } 92 93 } // namespace 94 95 namespace test { 96 97 void WaitForBookmarkModelToLoad(BookmarkModel* model) { 98 if (model->loaded()) 99 return; 100 base::RunLoop run_loop; 101 BookmarkLoadObserver observer(content::GetQuitTaskForRunLoop(&run_loop)); 102 model->AddObserver(&observer); 103 content::RunThisRunLoop(&run_loop); 104 model->RemoveObserver(&observer); 105 DCHECK(model->loaded()); 106 } 107 108 void WaitForBookmarkModelToLoad(Profile* profile) { 109 WaitForBookmarkModelToLoad(BookmarkModelFactory::GetForProfile(profile)); 110 } 111 112 std::string ModelStringFromNode(const BookmarkNode* node) { 113 // Since the children of the node are not available as a vector, 114 // we'll just have to do it the hard way. 115 int child_count = node->child_count(); 116 std::string child_string; 117 for (int i = 0; i < child_count; ++i) { 118 const BookmarkNode* child = node->GetChild(i); 119 if (child->is_folder()) { 120 child_string += UTF16ToUTF8(child->GetTitle()) + ":[ " + 121 ModelStringFromNode(child) + "] "; 122 } else { 123 child_string += UTF16ToUTF8(child->GetTitle()) + " "; 124 } 125 } 126 return child_string; 127 } 128 129 void AddNodesFromModelString(BookmarkModel* model, 130 const BookmarkNode* node, 131 const std::string& model_string) { 132 DCHECK(node); 133 std::string::size_type start_pos = 0; 134 std::string::size_type end_pos = 135 AddNodesFromString(model, node, model_string, start_pos); 136 DCHECK(end_pos == std::string::npos); 137 } 138 139 } // namespace test 140