1 // Copyright (c) 2012 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/history/android/bookmark_model_sql_handler.h" 6 7 #include "base/strings/utf_string_conversions.h" 8 #include "base/synchronization/waitable_event.h" 9 #include "chrome/browser/bookmarks/bookmark_model_factory.h" 10 #include "chrome/browser/history/history_database.h" 11 #include "chrome/browser/profiles/profile_manager.h" 12 #include "chrome/common/chrome_constants.h" 13 #include "chrome/test/base/testing_browser_process.h" 14 #include "chrome/test/base/testing_profile.h" 15 #include "chrome/test/base/testing_profile_manager.h" 16 #include "components/bookmarks/browser/bookmark_model.h" 17 #include "components/bookmarks/test/bookmark_test_helpers.h" 18 #include "content/public/browser/browser_thread.h" 19 #include "content/public/test/test_browser_thread.h" 20 #include "content/public/test/test_utils.h" 21 #include "testing/gtest/include/gtest/gtest.h" 22 23 namespace history { 24 25 using content::BrowserThread; 26 27 class BookmarkModelSQLHandlerTest : public testing::Test { 28 public: 29 BookmarkModelSQLHandlerTest() 30 : profile_manager_( 31 TestingBrowserProcess::GetGlobal()), 32 bookmark_model_(NULL), 33 ui_thread_(BrowserThread::UI, &message_loop_), 34 file_thread_(BrowserThread::FILE, &message_loop_) { 35 } 36 virtual ~BookmarkModelSQLHandlerTest() {} 37 38 protected: 39 virtual void SetUp() OVERRIDE { 40 // Setup the testing profile, so the bookmark_model_sql_handler could 41 // get the bookmark model from it. 42 ASSERT_TRUE(profile_manager_.SetUp()); 43 // It seems that the name has to be chrome::kInitialProfile, so it 44 // could be found by ProfileManager::GetLastUsedProfile(). 45 TestingProfile* testing_profile = profile_manager_.CreateTestingProfile( 46 chrome::kInitialProfile); 47 // Create the BookmarkModel that doesn't need to invoke load(). 48 testing_profile->CreateBookmarkModel(true); 49 bookmark_model_ = BookmarkModelFactory::GetForProfile(testing_profile); 50 test::WaitForBookmarkModelToLoad(bookmark_model_); 51 ASSERT_TRUE(bookmark_model_); 52 // Get the BookmarkModel from LastUsedProfile, this is the same way that 53 // how the BookmarkModelSQLHandler gets the BookmarkModel. 54 Profile* profile = ProfileManager::GetLastUsedProfile(); 55 ASSERT_TRUE(profile); 56 57 // Create the directory for history database. 58 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 59 base::FilePath history_db_name = temp_dir_.path().AppendASCII( 60 chrome::kHistoryFilename); 61 history_db_.Init(history_db_name); 62 } 63 64 // Runs the MessageLoopForUI, and return till all pending messages were 65 // processed. 66 void RunMessageLoopForUI() { 67 content::RunAllPendingInMessageLoop(); 68 } 69 70 TestingProfileManager profile_manager_; 71 BookmarkModel* bookmark_model_; 72 base::MessageLoopForUI message_loop_; 73 content::TestBrowserThread ui_thread_; 74 content::TestBrowserThread file_thread_; 75 base::ScopedTempDir temp_dir_; 76 HistoryDatabase history_db_; 77 }; 78 79 TEST_F(BookmarkModelSQLHandlerTest, InsertIntoMobileFolder) { 80 HistoryAndBookmarkRow row; 81 row.set_raw_url("http://bookmark.com"); 82 row.set_url(GURL("http://bookmark.com")); 83 row.set_title(base::UTF8ToUTF16("Bookmark Title")); 84 row.set_is_bookmark(true); 85 86 BookmarkModelSQLHandler handler(&history_db_); 87 ASSERT_TRUE(handler.Insert(&row)); 88 RunMessageLoopForUI(); 89 std::vector<const BookmarkNode*> nodes; 90 bookmark_model_->GetNodesByURL(row.url(), &nodes); 91 ASSERT_EQ(1u, nodes.size()); 92 EXPECT_EQ(row.title(), nodes[0]->GetTitle()); 93 const BookmarkNode* parent = nodes[0]->parent(); 94 ASSERT_TRUE(parent); 95 EXPECT_EQ(bookmark_model_->mobile_node()->id(), parent->id()); 96 } 97 98 TEST_F(BookmarkModelSQLHandlerTest, InsertIntoSpecificFolder) { 99 HistoryAndBookmarkRow row; 100 row.set_raw_url("http://bookmark.com"); 101 row.set_url(GURL("http://bookmark.com")); 102 row.set_title(base::UTF8ToUTF16("Bookmark Title")); 103 row.set_is_bookmark(true); 104 // Set other folder as parent. 105 row.set_parent_id(bookmark_model_->other_node()->id()); 106 107 BookmarkModelSQLHandler handler(&history_db_); 108 ASSERT_TRUE(handler.Insert(&row)); 109 RunMessageLoopForUI(); 110 std::vector<const BookmarkNode*> nodes; 111 bookmark_model_->GetNodesByURL(row.url(), &nodes); 112 ASSERT_EQ(1u, nodes.size()); 113 EXPECT_EQ(row.title(), nodes[0]->GetTitle()); 114 const BookmarkNode* parent = nodes[0]->parent(); 115 ASSERT_TRUE(parent); 116 EXPECT_EQ(row.parent_id(), parent->id()); 117 } 118 119 TEST_F(BookmarkModelSQLHandlerTest, UpdateHistoryToBookmark) { 120 // Added a row in url database. 121 URLRow url_row(GURL("http://www.google.com")); 122 url_row.set_title(base::UTF8ToUTF16("Google")); 123 URLID url_id = history_db_.AddURL(url_row); 124 ASSERT_TRUE(url_id); 125 126 // Update the added row as bookmark. 127 HistoryAndBookmarkRow row; 128 row.set_url(url_row.url()); 129 row.set_is_bookmark(true); 130 131 TableIDRow id_row; 132 id_row.url_id = url_id; 133 id_row.url = url_row.url(); 134 TableIDRows id_rows; 135 id_rows.push_back(id_row); 136 137 BookmarkModelSQLHandler handler(&history_db_); 138 ASSERT_TRUE(handler.Update(row, id_rows)); 139 RunMessageLoopForUI(); 140 // Get all bookmarks and verify there is only one. 141 std::vector<BookmarkModel::URLAndTitle> bookmarks; 142 bookmark_model_->GetBookmarks(&bookmarks); 143 ASSERT_EQ(1u, bookmarks.size()); 144 EXPECT_EQ(url_row.url(), bookmarks[0].url); 145 EXPECT_EQ(url_row.title(), bookmarks[0].title); 146 147 // Get the bookmark node. 148 std::vector<const BookmarkNode*> nodes; 149 bookmark_model_->GetNodesByURL(row.url(), &nodes); 150 ASSERT_EQ(1u, nodes.size()); 151 EXPECT_EQ(url_row.title(), nodes[0]->GetTitle()); 152 const BookmarkNode* parent = nodes[0]->parent(); 153 ASSERT_TRUE(parent); 154 EXPECT_EQ(bookmark_model_->mobile_node()->id(), parent->id()); 155 156 // Remove the bookmark 157 row.set_is_bookmark(false); 158 ASSERT_TRUE(handler.Update(row, id_rows)); 159 RunMessageLoopForUI(); 160 bookmarks.clear(); 161 bookmark_model_->GetBookmarks(&bookmarks); 162 EXPECT_TRUE(bookmarks.empty()); 163 164 // Update with the parent id. 165 row.set_parent_id(bookmark_model_->other_node()->id()); 166 row.set_is_bookmark(true); 167 ASSERT_TRUE(handler.Update(row, id_rows)); 168 RunMessageLoopForUI(); 169 // Get all bookmarks and verify there is only one. 170 bookmarks.clear(); 171 bookmark_model_->GetBookmarks(&bookmarks); 172 ASSERT_EQ(1u, bookmarks.size()); 173 EXPECT_EQ(url_row.url(), bookmarks[0].url); 174 EXPECT_EQ(url_row.title(), bookmarks[0].title); 175 // Get the bookmark node. 176 nodes.clear(); 177 bookmark_model_->GetNodesByURL(row.url(), &nodes); 178 ASSERT_EQ(1u, nodes.size()); 179 EXPECT_EQ(url_row.title(), nodes[0]->GetTitle()); 180 const BookmarkNode* parent1 = nodes[0]->parent(); 181 ASSERT_TRUE(parent1); 182 EXPECT_EQ(row.parent_id(), parent1->id()); 183 184 // Only update the title. 185 url_row.set_title(base::UTF8ToUTF16("Google Inc.")); 186 history_db_.UpdateURLRow(url_id, url_row); 187 HistoryAndBookmarkRow update_title; 188 update_title.set_title(url_row.title()); 189 ASSERT_TRUE(handler.Update(update_title, id_rows)); 190 RunMessageLoopForUI(); 191 // Get all bookmarks and verify there is only one. 192 bookmarks.clear(); 193 bookmark_model_->GetBookmarks(&bookmarks); 194 ASSERT_EQ(1u, bookmarks.size()); 195 EXPECT_EQ(url_row.url(), bookmarks[0].url); 196 EXPECT_EQ(url_row.title(), bookmarks[0].title); 197 // Get the bookmark node. 198 nodes.clear(); 199 bookmark_model_->GetNodesByURL(row.url(), &nodes); 200 ASSERT_EQ(1u, nodes.size()); 201 EXPECT_EQ(url_row.title(), nodes[0]->GetTitle()); 202 const BookmarkNode* parent2 = nodes[0]->parent(); 203 ASSERT_TRUE(parent2); 204 // The parent id shouldn't changed. 205 EXPECT_EQ(row.parent_id(), parent2->id()); 206 } 207 208 TEST_F(BookmarkModelSQLHandlerTest, Delete) { 209 // Insert 3 bookmarks, 2 of them have the same URL, but one is in mobile 210 // folder, another is in other folder, The 3rd one has different URL. 211 HistoryAndBookmarkRow row; 212 GURL url1 = GURL("http://bookmark.com"); 213 row.set_raw_url("http://bookmark.com"); 214 row.set_url(url1); 215 row.set_title(base::UTF8ToUTF16("Bookmark Title")); 216 row.set_is_bookmark(true); 217 218 BookmarkModelSQLHandler handler(&history_db_); 219 ASSERT_TRUE(handler.Insert(&row)); 220 221 // Set other folder as parent. 222 row.set_parent_id(bookmark_model_->other_node()->id()); 223 ASSERT_TRUE(handler.Insert(&row)); 224 225 row.set_url(GURL("http://google.com")); 226 ASSERT_TRUE(handler.Insert(&row)); 227 RunMessageLoopForUI(); 228 // Get all bookmarks and verify there are 3 bookmarks. 229 EXPECT_EQ(1, bookmark_model_->mobile_node()->child_count()); 230 EXPECT_EQ(2, bookmark_model_->other_node()->child_count()); 231 232 // Remove the third one. 233 TableIDRow id_row; 234 id_row.url = row.url(); 235 TableIDRows id_rows; 236 id_rows.push_back(id_row); 237 238 ASSERT_TRUE(handler.Delete(id_rows)); 239 RunMessageLoopForUI(); 240 // Verify the first 2 bookmarks still exist. 241 EXPECT_EQ(1, bookmark_model_->mobile_node()->child_count()); 242 EXPECT_EQ(1, bookmark_model_->other_node()->child_count()); 243 244 id_row.url = url1; 245 id_rows.clear(); 246 id_rows.push_back(id_row); 247 ASSERT_TRUE(handler.Delete(id_rows)); 248 RunMessageLoopForUI(); 249 // All bookmarks were deleted. 250 EXPECT_FALSE(bookmark_model_->HasBookmarks()); 251 } 252 253 } // namespace history 254