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