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