OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/ntp_snippets/bookmarks/bookmark_last_visit_utils.h" | 5 #include "components/ntp_snippets/bookmarks/bookmark_last_visit_utils.h" |
6 | 6 |
| 7 #include <memory> |
7 #include <string> | 8 #include <string> |
8 | 9 |
| 10 #include "base/callback.h" |
9 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
10 #include "base/strings/stringprintf.h" | 12 #include "base/strings/stringprintf.h" |
11 #include "base/strings/utf_string_conversions.h" | 13 #include "base/strings/utf_string_conversions.h" |
12 #include "components/bookmarks/browser/bookmark_model.h" | 14 #include "components/bookmarks/browser/bookmark_model.h" |
13 #include "components/bookmarks/browser/bookmark_node.h" | 15 #include "components/bookmarks/browser/bookmark_node.h" |
14 #include "components/bookmarks/test/test_bookmark_client.h" | 16 #include "components/bookmarks/test/test_bookmark_client.h" |
15 #include "testing/gmock/include/gmock/gmock.h" | 17 #include "testing/gmock/include/gmock/gmock.h" |
16 #include "testing/gtest/include/gtest/gtest.h" | 18 #include "testing/gtest/include/gtest/gtest.h" |
17 #include "url/gurl.h" | 19 #include "url/gurl.h" |
18 | 20 |
19 using bookmarks::BookmarkModel; | 21 using bookmarks::BookmarkModel; |
20 using bookmarks::BookmarkNode; | 22 using bookmarks::BookmarkNode; |
21 | 23 |
| 24 using testing::Eq; |
22 using testing::IsEmpty; | 25 using testing::IsEmpty; |
23 using testing::SizeIs; | 26 using testing::SizeIs; |
24 | 27 |
25 namespace ntp_snippets { | 28 namespace ntp_snippets { |
26 | 29 |
27 namespace { | 30 namespace { |
28 | 31 |
29 const char kBookmarkLastVisitDateOnMobileKey[] = "last_visited"; | 32 const char kBookmarkLastVisitDateOnMobileKey[] = "last_visited"; |
30 const char kBookmarkLastVisitDateOnDesktopKey[] = "last_visited_desktop"; | 33 const char kBookmarkLastVisitDateOnDesktopKey[] = "last_visited_desktop"; |
31 | 34 |
32 void AddBookmarks(BookmarkModel* model, | 35 void AddBookmarks(BookmarkModel* model, |
33 int num, | 36 int num, |
34 const std::string& meta_key, | 37 const std::string& meta_key, |
35 const std::string& meta_value) { | 38 const std::string& meta_value) { |
36 for (int index = 0; index < num; ++index) { | 39 for (int index = 0; index < num; ++index) { |
37 base::string16 title = base::ASCIIToUTF16( | 40 base::string16 title = base::ASCIIToUTF16( |
38 base::StringPrintf("title%s%d", meta_key.c_str(), index)); | 41 base::StringPrintf("title%s%d", meta_key.c_str(), index)); |
39 GURL url(base::StringPrintf("http://url%s%d.com", meta_key.c_str(), index)); | 42 GURL url(base::StringPrintf("http://url%s%d.com", meta_key.c_str(), index)); |
40 const BookmarkNode* node = | 43 const BookmarkNode* node = |
41 model->AddURL(model->bookmark_bar_node(), 0, title, url); | 44 model->AddURL(model->bookmark_bar_node(), 0, title, url); |
42 | 45 |
43 if (!meta_key.empty()) { | 46 if (!meta_key.empty()) { |
44 model->SetNodeMetaInfo(node, meta_key, meta_value); | 47 model->SetNodeMetaInfo(node, meta_key, meta_value); |
45 } | 48 } |
46 } | 49 } |
47 } | 50 } |
48 | 51 |
49 void AddBookmarksRecentOnMobile(BookmarkModel* model, | 52 void AddBookmarksRecentOnMobile(BookmarkModel* model, |
50 int num, | 53 int num, |
51 const base::Time& threshold_time) { | 54 const base::Time& visit_time) { |
52 base::TimeDelta week = base::TimeDelta::FromDays(7); | |
53 base::Time recent_time = threshold_time + week; | |
54 std::string recent_time_string = | |
55 base::Int64ToString(recent_time.ToInternalValue()); | |
56 | |
57 AddBookmarks(model, num, kBookmarkLastVisitDateOnMobileKey, | 55 AddBookmarks(model, num, kBookmarkLastVisitDateOnMobileKey, |
58 recent_time_string); | 56 base::Int64ToString(visit_time.ToInternalValue())); |
59 } | 57 } |
60 | 58 |
61 void AddBookmarksRecentOnDesktop(BookmarkModel* model, | 59 void AddBookmarksRecentOnDesktop(BookmarkModel* model, |
62 int num, | 60 int num, |
63 const base::Time& threshold_time) { | 61 const base::Time& visit_time) { |
64 base::TimeDelta week = base::TimeDelta::FromDays(7); | |
65 base::Time recent_time = threshold_time + week; | |
66 std::string recent_time_string = | |
67 base::Int64ToString(recent_time.ToInternalValue()); | |
68 | |
69 AddBookmarks(model, num, kBookmarkLastVisitDateOnDesktopKey, | 62 AddBookmarks(model, num, kBookmarkLastVisitDateOnDesktopKey, |
70 recent_time_string); | 63 base::Int64ToString(visit_time.ToInternalValue())); |
71 } | 64 } |
72 | 65 |
73 void AddBookmarksNonVisited(BookmarkModel* model, int num) { | 66 void AddBookmarksNonVisited(BookmarkModel* model, int num) { |
74 AddBookmarks(model, num, std::string(), std::string()); | 67 AddBookmarks(model, num, std::string(), std::string()); |
75 } | 68 } |
76 | 69 |
| 70 const BookmarkNode* AddSingleBookmark(BookmarkModel* model, |
| 71 const std::string& url, |
| 72 const std::string& last_visit_key, |
| 73 const base::Time& visit_time) { |
| 74 base::string16 title = |
| 75 base::ASCIIToUTF16(base::StringPrintf("title-%s", url.c_str())); |
| 76 const BookmarkNode* node = |
| 77 model->AddURL(model->bookmark_bar_node(), 0, title, GURL(url)); |
| 78 model->SetNodeMetaInfo(node, last_visit_key, |
| 79 base::Int64ToString(visit_time.ToInternalValue())); |
| 80 return node; |
| 81 } |
| 82 |
77 } // namespace | 83 } // namespace |
78 | 84 |
79 class GetRecentlyVisitedBookmarksTest : public testing::Test { | 85 class GetRecentlyVisitedBookmarksTest : public testing::Test { |
80 public: | 86 public: |
81 GetRecentlyVisitedBookmarksTest() { | 87 GetRecentlyVisitedBookmarksTest() { |
82 base::TimeDelta week = base::TimeDelta::FromDays(7); | 88 base::TimeDelta week = base::TimeDelta::FromDays(7); |
83 threshold_time_ = base::Time::UnixEpoch() + 52 * week; | 89 threshold_time_ = base::Time::UnixEpoch() + 52 * week; |
84 } | 90 } |
85 | 91 |
86 const base::Time& threshold_time() const { return threshold_time_; } | 92 const base::Time& threshold_time() const { return threshold_time_; } |
87 | 93 |
| 94 base::Time GetRecentTime() const { |
| 95 return threshold_time_ + base::TimeDelta::FromDays(7); |
| 96 } |
| 97 |
88 private: | 98 private: |
89 base::Time threshold_time_; | 99 base::Time threshold_time_; |
90 | 100 |
91 DISALLOW_COPY_AND_ASSIGN(GetRecentlyVisitedBookmarksTest); | 101 DISALLOW_COPY_AND_ASSIGN(GetRecentlyVisitedBookmarksTest); |
92 }; | 102 }; |
93 | 103 |
94 TEST_F(GetRecentlyVisitedBookmarksTest, ShouldNotReturnMissing) { | 104 TEST_F(GetRecentlyVisitedBookmarksTest, ShouldNotReturnMissing) { |
95 const int number_of_bookmarks = 3; | 105 const int number_of_bookmarks = 3; |
96 std::unique_ptr<BookmarkModel> model = | 106 std::unique_ptr<BookmarkModel> model = |
97 bookmarks::TestBookmarkClient::CreateModel(); | 107 bookmarks::TestBookmarkClient::CreateModel(); |
98 AddBookmarksNonVisited(model.get(), number_of_bookmarks); | 108 AddBookmarksNonVisited(model.get(), number_of_bookmarks); |
99 | 109 |
100 std::vector<const bookmarks::BookmarkNode*> result = | 110 std::vector<const bookmarks::BookmarkNode*> result = |
101 GetRecentlyVisitedBookmarks(model.get(), number_of_bookmarks, | 111 GetRecentlyVisitedBookmarks(model.get(), number_of_bookmarks, |
102 threshold_time(), | 112 threshold_time(), |
103 /*consider_visits_from_desktop=*/false); | 113 /*consider_visits_from_desktop=*/false); |
104 EXPECT_THAT(result, IsEmpty()); | 114 EXPECT_THAT(result, IsEmpty()); |
105 } | 115 } |
106 | 116 |
107 TEST_F(GetRecentlyVisitedBookmarksTest, ShouldNotConsiderDesktopVisits) { | 117 TEST_F(GetRecentlyVisitedBookmarksTest, ShouldNotConsiderDesktopVisits) { |
108 const int number_of_bookmarks = 3; | 118 const int number_of_bookmarks = 3; |
109 std::unique_ptr<BookmarkModel> model = | 119 std::unique_ptr<BookmarkModel> model = |
110 bookmarks::TestBookmarkClient::CreateModel(); | 120 bookmarks::TestBookmarkClient::CreateModel(); |
111 AddBookmarksRecentOnDesktop(model.get(), number_of_bookmarks, | 121 AddBookmarksRecentOnDesktop(model.get(), number_of_bookmarks, |
112 threshold_time()); | 122 GetRecentTime()); |
113 | 123 |
114 std::vector<const bookmarks::BookmarkNode*> result = | 124 std::vector<const bookmarks::BookmarkNode*> result = |
115 GetRecentlyVisitedBookmarks(model.get(), number_of_bookmarks, | 125 GetRecentlyVisitedBookmarks(model.get(), number_of_bookmarks, |
116 threshold_time(), | 126 threshold_time(), |
117 /*consider_visits_from_desktop=*/false); | 127 /*consider_visits_from_desktop=*/false); |
118 EXPECT_THAT(result, IsEmpty()); | 128 EXPECT_THAT(result, IsEmpty()); |
119 } | 129 } |
120 | 130 |
121 TEST_F(GetRecentlyVisitedBookmarksTest, ShouldConsiderDesktopVisits) { | 131 TEST_F(GetRecentlyVisitedBookmarksTest, ShouldConsiderDesktopVisits) { |
122 const int number_of_bookmarks = 3; | 132 const int number_of_bookmarks = 3; |
123 const int number_of_recent_desktop = 2; | 133 const int number_of_recent_desktop = 2; |
124 std::unique_ptr<BookmarkModel> model = | 134 std::unique_ptr<BookmarkModel> model = |
125 bookmarks::TestBookmarkClient::CreateModel(); | 135 bookmarks::TestBookmarkClient::CreateModel(); |
126 AddBookmarksRecentOnDesktop(model.get(), number_of_recent_desktop, | 136 AddBookmarksRecentOnDesktop(model.get(), number_of_recent_desktop, |
127 threshold_time()); | 137 GetRecentTime()); |
128 AddBookmarksNonVisited(model.get(), | 138 AddBookmarksNonVisited(model.get(), |
129 number_of_bookmarks - number_of_recent_desktop); | 139 number_of_bookmarks - number_of_recent_desktop); |
130 | 140 |
131 std::vector<const bookmarks::BookmarkNode*> result = | 141 std::vector<const bookmarks::BookmarkNode*> result = |
132 GetRecentlyVisitedBookmarks(model.get(), number_of_bookmarks, | 142 GetRecentlyVisitedBookmarks(model.get(), number_of_bookmarks, |
133 threshold_time(), | 143 threshold_time(), |
134 /*consider_visits_from_desktop=*/true); | 144 /*consider_visits_from_desktop=*/true); |
135 EXPECT_THAT(result, SizeIs(number_of_recent_desktop)); | 145 EXPECT_THAT(result, SizeIs(number_of_recent_desktop)); |
136 } | 146 } |
137 | 147 |
138 TEST_F(GetRecentlyVisitedBookmarksTest, ShouldReturnNotMoreThanMaxCount) { | 148 TEST_F(GetRecentlyVisitedBookmarksTest, ShouldReturnNotMoreThanMaxCount) { |
139 const int number_of_bookmarks = 3; | 149 const int number_of_bookmarks = 3; |
140 std::unique_ptr<BookmarkModel> model = | 150 std::unique_ptr<BookmarkModel> model = |
141 bookmarks::TestBookmarkClient::CreateModel(); | 151 bookmarks::TestBookmarkClient::CreateModel(); |
142 AddBookmarksRecentOnMobile(model.get(), number_of_bookmarks, | 152 AddBookmarksRecentOnMobile(model.get(), number_of_bookmarks, GetRecentTime()); |
143 threshold_time()); | |
144 | 153 |
145 const int max_count = number_of_bookmarks - 1; | 154 const int max_count = number_of_bookmarks - 1; |
146 std::vector<const bookmarks::BookmarkNode*> result = | 155 std::vector<const bookmarks::BookmarkNode*> result = |
147 GetRecentlyVisitedBookmarks(model.get(), max_count, threshold_time(), | 156 GetRecentlyVisitedBookmarks(model.get(), max_count, threshold_time(), |
148 /*consider_visits_from_desktop=*/false); | 157 /*consider_visits_from_desktop=*/false); |
149 EXPECT_THAT(result, SizeIs(max_count)); | 158 EXPECT_THAT(result, SizeIs(max_count)); |
150 } | 159 } |
151 | 160 |
| 161 namespace { |
| 162 |
| 163 base::Callback<bool(const GURL& url)> DeleteAllFilter() { |
| 164 return base::Bind([] (const GURL& url) { return true; }); |
| 165 } |
| 166 |
| 167 base::Callback<bool(const GURL& url)> DeleteOneURLFilter( |
| 168 const GURL& to_delete) { |
| 169 return base::Bind( |
| 170 [](const GURL& to_delete, const GURL& url) { return url == to_delete; }, |
| 171 to_delete); |
| 172 } |
| 173 |
| 174 } // namespace |
| 175 |
| 176 TEST(RemoveLastVisitedDatesBetween, ShouldRemoveTimestampsWithinTimeRange) { |
| 177 const base::Time delete_begin = |
| 178 base::Time::Now() - base::TimeDelta::FromDays(2); |
| 179 const base::Time delete_end = base::Time::Max(); |
| 180 |
| 181 std::unique_ptr<BookmarkModel> model = |
| 182 bookmarks::TestBookmarkClient::CreateModel(); |
| 183 AddSingleBookmark(model.get(), "http://url-1.com", |
| 184 kBookmarkLastVisitDateOnMobileKey, |
| 185 delete_begin + base::TimeDelta::FromSeconds(1)); |
| 186 AddSingleBookmark(model.get(), "http://url-1.com", |
| 187 kBookmarkLastVisitDateOnDesktopKey, |
| 188 delete_begin + base::TimeDelta::FromSeconds(1)); |
| 189 ASSERT_THAT( |
| 190 GetRecentlyVisitedBookmarks(model.get(), 20, base::Time(), |
| 191 /*consider_visits_from_desktop=*/true), |
| 192 SizeIs(1)); |
| 193 |
| 194 RemoveLastVisitedDatesBetween(delete_begin, delete_end, DeleteAllFilter(), |
| 195 model.get()); |
| 196 |
| 197 EXPECT_THAT( |
| 198 GetRecentlyVisitedBookmarks(model.get(), 20, base::Time(), |
| 199 /*consider_visits_from_desktop=*/true), |
| 200 IsEmpty()); |
| 201 // Verify that the bookmark model nodes themselve still exist. |
| 202 std::vector<const BookmarkNode*> remaining_nodes; |
| 203 model->GetNodesByURL(GURL("http://url-1.com"), &remaining_nodes); |
| 204 EXPECT_THAT(remaining_nodes, SizeIs(2)); |
| 205 } |
| 206 |
| 207 TEST(RemoveLastVisitedDatesBetween, |
| 208 ShouldHandleMetadataFromOtherDeviceTypesSeparately) { |
| 209 const base::Time delete_begin = |
| 210 base::Time::Now() - base::TimeDelta::FromDays(2); |
| 211 const base::Time delete_end = base::Time::Max(); |
| 212 |
| 213 std::unique_ptr<BookmarkModel> model = |
| 214 bookmarks::TestBookmarkClient::CreateModel(); |
| 215 // Create a bookmark with last visited times from both, mobile and desktop. |
| 216 // The mobile one is within the deletion interval, the desktop one outside. |
| 217 // Only the mobile one should get deleted. |
| 218 const BookmarkNode* node = AddSingleBookmark( |
| 219 model.get(), "http://url-1.com", kBookmarkLastVisitDateOnMobileKey, |
| 220 delete_begin + base::TimeDelta::FromSeconds(1)); |
| 221 model->SetNodeMetaInfo( |
| 222 node, kBookmarkLastVisitDateOnDesktopKey, |
| 223 base::Int64ToString( |
| 224 (delete_begin - base::TimeDelta::FromSeconds(1)).ToInternalValue())); |
| 225 ASSERT_THAT( |
| 226 GetRecentlyVisitedBookmarks(model.get(), 20, base::Time(), |
| 227 /*consider_visits_from_desktop=*/true), |
| 228 SizeIs(1)); |
| 229 |
| 230 RemoveLastVisitedDatesBetween(delete_begin, delete_end, DeleteAllFilter(), |
| 231 model.get()); |
| 232 |
| 233 EXPECT_THAT( |
| 234 GetRecentlyVisitedBookmarks(model.get(), 20, base::Time(), |
| 235 /*consider_visits_from_desktop=*/false), |
| 236 IsEmpty()); |
| 237 EXPECT_THAT( |
| 238 GetRecentlyVisitedBookmarks(model.get(), 20, base::Time(), |
| 239 /*consider_visits_from_desktop=*/true), |
| 240 SizeIs(1)); |
| 241 } |
| 242 |
| 243 TEST(RemoveLastVisitedDatesBetween, ShouldNotRemoveTimestampsOutsideTimeRange) { |
| 244 const base::Time delete_begin = |
| 245 base::Time::Now() - base::TimeDelta::FromDays(2); |
| 246 const base::Time delete_end = delete_begin + base::TimeDelta::FromDays(5); |
| 247 |
| 248 std::unique_ptr<BookmarkModel> model = |
| 249 bookmarks::TestBookmarkClient::CreateModel(); |
| 250 AddSingleBookmark(model.get(), "http://url-1.com", |
| 251 kBookmarkLastVisitDateOnMobileKey, |
| 252 delete_begin - base::TimeDelta::FromSeconds(1)); |
| 253 AddSingleBookmark(model.get(), "http://url-2.com", |
| 254 kBookmarkLastVisitDateOnDesktopKey, |
| 255 delete_end + base::TimeDelta::FromSeconds(1)); |
| 256 ASSERT_THAT( |
| 257 GetRecentlyVisitedBookmarks(model.get(), 20, base::Time(), |
| 258 /*consider_visits_from_desktop=*/true), |
| 259 SizeIs(2)); |
| 260 |
| 261 RemoveLastVisitedDatesBetween(delete_begin, delete_end, DeleteAllFilter(), |
| 262 model.get()); |
| 263 |
| 264 EXPECT_THAT( |
| 265 GetRecentlyVisitedBookmarks(model.get(), 20, base::Time(), |
| 266 /*consider_visits_from_desktop=*/true), |
| 267 SizeIs(2)); |
| 268 } |
| 269 |
| 270 TEST(RemoveLastVisitedDatesBetween, ShouldOnlyRemoveURLsWithinFilter) { |
| 271 const base::Time delete_begin = |
| 272 base::Time::Now() - base::TimeDelta::FromDays(2); |
| 273 const base::Time delete_end = base::Time::Max(); |
| 274 |
| 275 std::unique_ptr<BookmarkModel> model = |
| 276 bookmarks::TestBookmarkClient::CreateModel(); |
| 277 AddSingleBookmark(model.get(), "http://url-1.com", |
| 278 kBookmarkLastVisitDateOnMobileKey, |
| 279 delete_begin + base::TimeDelta::FromSeconds(1)); |
| 280 AddSingleBookmark(model.get(), "http://url-2.com", |
| 281 kBookmarkLastVisitDateOnMobileKey, |
| 282 delete_begin + base::TimeDelta::FromSeconds(1)); |
| 283 ASSERT_THAT( |
| 284 GetRecentlyVisitedBookmarks(model.get(), 20, base::Time(), |
| 285 /*consider_visits_from_desktop=*/false), |
| 286 SizeIs(2)); |
| 287 |
| 288 RemoveLastVisitedDatesBetween(delete_begin, delete_end, |
| 289 DeleteOneURLFilter(GURL("http://url-2.com")), |
| 290 model.get()); |
| 291 |
| 292 std::vector<const bookmarks::BookmarkNode*> remaining_nodes = |
| 293 GetRecentlyVisitedBookmarks(model.get(), 20, base::Time(), |
| 294 /*consider_visits_from_desktop=*/false); |
| 295 EXPECT_THAT(remaining_nodes, SizeIs(1)); |
| 296 EXPECT_THAT(remaining_nodes[0]->url(), Eq(GURL("http://url-1.com"))); |
| 297 } |
| 298 |
152 } // namespace ntp_snippets | 299 } // namespace ntp_snippets |
OLD | NEW |