permission_auditing_database_unittest.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. // Copyright 2020 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. #include "components/permissions/permission_auditing_database.h"
  5. #include <memory>
  6. #include "base/bind.h"
  7. #include "base/check.h"
  8. #include "base/files/file_util.h"
  9. #include "base/files/scoped_temp_dir.h"
  10. #include "base/strings/stringprintf.h"
  11. #include "base/time/time.h"
  12. #include "sql/test/scoped_error_expecter.h"
  13. #include "testing/gmock/include/gmock/gmock-matchers.h"
  14. #include "testing/gmock/include/gmock/gmock.h"
  15. #include "testing/gtest/include/gtest/gtest.h"
  16. #include "url/gurl.h"
  17. namespace permissions {
  18. using ::testing::ElementsAre;
  19. using ::testing::IsEmpty;
  20. namespace {
  21. base::Time TimeFromTimestamp(const int64_t& time) {
  22. return base::Time::FromDeltaSinceWindowsEpoch(base::Microseconds(time));
  23. }
  24. constexpr ContentSettingsType kTestTypes[] = {
  25. ContentSettingsType::GEOLOCATION, ContentSettingsType::NOTIFICATIONS};
  26. constexpr char kTestUrl1[] = "http://www.example1.com";
  27. constexpr char kTestUrl2[] = "http://www.example2.com";
  28. std::string GetUniqueUrl(int id) {
  29. return base::StringPrintf("http://www.example%d.com", id);
  30. }
  31. url::Origin GetOrigin(const char* url) {
  32. return url::Origin::Create(GURL(url));
  33. }
  34. PermissionUsageSession SessionLike(ContentSettingsType type,
  35. const char* url,
  36. const PermissionUsageSession& session) {
  37. return {.origin = GetOrigin(url),
  38. .type = type,
  39. .usage_start = session.usage_start,
  40. .usage_end = session.usage_end,
  41. .had_user_activation = session.had_user_activation,
  42. .was_foreground = session.was_foreground,
  43. .had_focus = session.had_focus};
  44. }
  45. } // namespace
  46. class PermissionAuditingDatabaseTest : public testing::Test {
  47. public:
  48. PermissionAuditingDatabaseTest()
  49. : test_sessions_(GeneratePermissionSessions()) {}
  50. PermissionAuditingDatabaseTest(const PermissionAuditingDatabaseTest&) =
  51. delete;
  52. PermissionAuditingDatabaseTest& operator=(
  53. const PermissionAuditingDatabaseTest&) = delete;
  54. protected:
  55. void SetUp() override {
  56. ASSERT_TRUE(temp_directory_.CreateUniqueTempDir());
  57. path_ = temp_directory_.GetPath().Append(
  58. FILE_PATH_LITERAL("test_permission_auditing_database"));
  59. ASSERT_TRUE(db_.Init(path_));
  60. }
  61. std::vector<PermissionUsageSession> GetPermissionUsageHistory(
  62. ContentSettingsType type,
  63. const char* url,
  64. base::Time starting_from = base::Time()) {
  65. return db_.GetPermissionUsageHistory(type, GetOrigin(url), starting_from);
  66. }
  67. absl::optional<base::Time> GetLastUsageTime(ContentSettingsType type,
  68. const char* url) {
  69. return db_.GetLastPermissionUsageTime(type, GetOrigin(url));
  70. }
  71. bool UpdateEndTime(ContentSettingsType type,
  72. const char* url,
  73. base::Time ordering_time,
  74. base::Time new_end_time) {
  75. return db_.UpdateEndTime(type, GetOrigin(url), ordering_time, new_end_time);
  76. }
  77. void StoreSessionForEachTime() {
  78. for (const auto& time : test_times_) {
  79. ASSERT_TRUE(db().StorePermissionUsage({.origin = GetOrigin(kTestUrl1),
  80. .type = kTestTypes[0],
  81. .usage_start = time,
  82. .usage_end = time,
  83. .had_user_activation = false,
  84. .was_foreground = false,
  85. .had_focus = false}));
  86. }
  87. }
  88. PermissionAuditingDatabase& db() { return db_; }
  89. const base::Time test_times_[3] = {TimeFromTimestamp(12864787200000000),
  90. TimeFromTimestamp(12864787200000001),
  91. TimeFromTimestamp(12864787200000002)};
  92. const std::vector<PermissionUsageSession> test_sessions_;
  93. private:
  94. std::vector<PermissionUsageSession> GeneratePermissionSessions() {
  95. std::vector<PermissionUsageSession> sessions;
  96. for (size_t i = 0; i < std::size(test_times_); ++i) {
  97. for (size_t j = i + 1; j <= std::size(test_times_); ++j) {
  98. for (bool had_user_activation : {false, true}) {
  99. for (bool was_foreground : {false, true}) {
  100. for (bool had_focus : {false, true}) {
  101. base::Time start = test_times_[i];
  102. base::Time end = (j == std::size(test_times_)) ? test_times_[i]
  103. : test_times_[j];
  104. sessions.push_back({.usage_start = start,
  105. .usage_end = end,
  106. .had_user_activation = had_user_activation,
  107. .was_foreground = was_foreground,
  108. .had_focus = had_focus});
  109. }
  110. }
  111. }
  112. }
  113. }
  114. return sessions;
  115. }
  116. PermissionAuditingDatabase db_;
  117. base::ScopedTempDir temp_directory_;
  118. base::FilePath path_;
  119. };
  120. TEST_F(PermissionAuditingDatabaseTest, IsUsageHistorySizeCorrect) {
  121. auto session = SessionLike(kTestTypes[0], kTestUrl1, test_sessions_[0]);
  122. EXPECT_THAT(GetPermissionUsageHistory(kTestTypes[0], kTestUrl1), IsEmpty());
  123. size_t current_size = 0;
  124. for (const auto& time : test_times_) {
  125. session.usage_start = time;
  126. session.usage_end = time;
  127. ASSERT_TRUE(db().StorePermissionUsage(
  128. SessionLike(kTestTypes[0], kTestUrl1, session)));
  129. ASSERT_EQ(GetPermissionUsageHistory(kTestTypes[0], kTestUrl1).size(),
  130. ++current_size);
  131. }
  132. }
  133. TEST_F(PermissionAuditingDatabaseTest,
  134. IsUsageHistoryDifferentForDifferentPermissionsAndOrigins) {
  135. const auto& session1 =
  136. SessionLike(kTestTypes[0], kTestUrl1, test_sessions_[0]);
  137. const auto& session2 =
  138. SessionLike(kTestTypes[1], kTestUrl2, test_sessions_[1]);
  139. ASSERT_TRUE(db().StorePermissionUsage(session1));
  140. ASSERT_TRUE(db().StorePermissionUsage(session2));
  141. EXPECT_THAT(GetPermissionUsageHistory(kTestTypes[0], kTestUrl1),
  142. ElementsAre(session1));
  143. EXPECT_THAT(GetPermissionUsageHistory(kTestTypes[1], kTestUrl2),
  144. ElementsAre(session2));
  145. EXPECT_THAT(GetPermissionUsageHistory(kTestTypes[0], kTestUrl2), IsEmpty());
  146. EXPECT_THAT(GetPermissionUsageHistory(kTestTypes[1], kTestUrl1), IsEmpty());
  147. }
  148. TEST_F(PermissionAuditingDatabaseTest, AreFieldsStoredCorrectlyInUsageHistory) {
  149. int counter = 0;
  150. for (const auto& session : test_sessions_) {
  151. const std::string url = GetUniqueUrl(++counter);
  152. auto updated_session = SessionLike(kTestTypes[0], url.c_str(), session);
  153. ASSERT_TRUE(db().StorePermissionUsage(updated_session));
  154. EXPECT_THAT(GetPermissionUsageHistory(kTestTypes[0], url.c_str()),
  155. ElementsAre(updated_session));
  156. }
  157. }
  158. TEST_F(PermissionAuditingDatabaseTest, UsageHistoryContainsOnlyLastSessions) {
  159. for (const auto time : test_times_) {
  160. ASSERT_TRUE(
  161. db().StorePermissionUsage({.origin = GetOrigin(kTestUrl1),
  162. .type = kTestTypes[0],
  163. .usage_start = time,
  164. .usage_end = time + base::Microseconds(1),
  165. .had_user_activation = false,
  166. .was_foreground = false,
  167. .had_focus = false}));
  168. }
  169. EXPECT_EQ(GetPermissionUsageHistory(kTestTypes[0], kTestUrl1).size(),
  170. std::size(test_times_));
  171. for (size_t i = 0; i < std::size(test_times_); ++i) {
  172. EXPECT_EQ(GetPermissionUsageHistory(kTestTypes[0], kTestUrl1,
  173. test_times_[i] + base::Microseconds(2))
  174. .size(),
  175. std::size(test_times_) - i - 1);
  176. }
  177. }
  178. TEST_F(PermissionAuditingDatabaseTest, GetLastPermissionUsageTime) {
  179. EXPECT_FALSE(GetLastUsageTime(kTestTypes[0], kTestUrl1));
  180. for (const auto& time : test_times_) {
  181. ASSERT_TRUE(db().StorePermissionUsage({.origin = GetOrigin(kTestUrl1),
  182. .type = kTestTypes[0],
  183. .usage_start = time,
  184. .usage_end = time,
  185. .had_user_activation = false,
  186. .was_foreground = false,
  187. .had_focus = false}));
  188. EXPECT_EQ(GetLastUsageTime(kTestTypes[0], kTestUrl1), time);
  189. }
  190. }
  191. TEST_F(PermissionAuditingDatabaseTest, UpdateEndTime) {
  192. int counter = 0;
  193. for (const auto& session : test_sessions_) {
  194. const std::string url = GetUniqueUrl(++counter);
  195. ASSERT_TRUE(db().StorePermissionUsage(
  196. SessionLike(kTestTypes[0], url.c_str(), session)));
  197. const auto& end_time = session.usage_end;
  198. auto tomorrow = end_time + base::Days(1);
  199. ASSERT_TRUE(GetLastUsageTime(kTestTypes[0], url.c_str()) == end_time);
  200. ASSERT_TRUE(UpdateEndTime(kTestTypes[0], url.c_str(), session.usage_start,
  201. tomorrow));
  202. EXPECT_EQ(GetLastUsageTime(kTestTypes[0], url.c_str()), tomorrow);
  203. auto history = GetPermissionUsageHistory(kTestTypes[0], url.c_str());
  204. ASSERT_EQ(history.size(), 1u);
  205. EXPECT_EQ(history[0].usage_end, tomorrow);
  206. }
  207. }
  208. TEST_F(PermissionAuditingDatabaseTest, DeleteSessionsBetween) {
  209. size_t current_size = std::size(test_times_);
  210. StoreSessionForEachTime();
  211. for (const auto& time : test_times_) {
  212. ASSERT_TRUE(db().DeleteSessionsBetween(time, time));
  213. ASSERT_EQ(GetPermissionUsageHistory(kTestTypes[0], kTestUrl1).size(),
  214. --current_size);
  215. }
  216. }
  217. TEST_F(PermissionAuditingDatabaseTest,
  218. DeleteSessionsBetweenWithUnspecifiedEndTime) {
  219. StoreSessionForEachTime();
  220. ASSERT_TRUE(db().DeleteSessionsBetween(test_times_[1], base::Time()));
  221. ASSERT_EQ(GetPermissionUsageHistory(kTestTypes[0], kTestUrl1).size(), 1u);
  222. ASSERT_TRUE(db().DeleteSessionsBetween(test_times_[0], base::Time()));
  223. EXPECT_THAT(GetPermissionUsageHistory(kTestTypes[0], kTestUrl1), IsEmpty());
  224. }
  225. TEST_F(PermissionAuditingDatabaseTest,
  226. DeleteSessionsBetweenWithUnspecifiedStartTime) {
  227. StoreSessionForEachTime();
  228. ASSERT_TRUE(db().DeleteSessionsBetween(
  229. base::Time(), test_times_[std::size(test_times_) - 2]));
  230. ASSERT_EQ(GetPermissionUsageHistory(kTestTypes[0], kTestUrl1).size(), 1u);
  231. ASSERT_TRUE(db().DeleteSessionsBetween(
  232. base::Time(), test_times_[std::size(test_times_) - 1]));
  233. EXPECT_THAT(GetPermissionUsageHistory(kTestTypes[0], kTestUrl1), IsEmpty());
  234. }
  235. TEST_F(PermissionAuditingDatabaseTest,
  236. DeleteSessionsBetweenWithUnspecifiedStartAndEndTime) {
  237. StoreSessionForEachTime();
  238. ASSERT_EQ(GetPermissionUsageHistory(kTestTypes[0], kTestUrl1).size(),
  239. std::size(test_times_));
  240. ASSERT_TRUE(db().DeleteSessionsBetween(base::Time(), base::Time()));
  241. EXPECT_THAT(GetPermissionUsageHistory(kTestTypes[0], kTestUrl1), IsEmpty());
  242. }
  243. TEST_F(PermissionAuditingDatabaseTest,
  244. StorePermissionUsageChecksTimerangeConstraint) {
  245. auto session = SessionLike(kTestTypes[0], kTestUrl1, test_sessions_[0]);
  246. session.usage_start = session.usage_end;
  247. EXPECT_TRUE(db().StorePermissionUsage(session));
  248. }
  249. TEST_F(PermissionAuditingDatabaseTest,
  250. StorePermissionUsageDoesntAccpetExistingRecord) {
  251. auto session = SessionLike(kTestTypes[0], kTestUrl1, test_sessions_[0]);
  252. EXPECT_TRUE(db().StorePermissionUsage(session));
  253. {
  254. sql::test::ScopedErrorExpecter expecter;
  255. expecter.ExpectError(SQLITE_CONSTRAINT);
  256. EXPECT_FALSE(db().StorePermissionUsage(session));
  257. EXPECT_TRUE(expecter.SawExpectedErrors());
  258. }
  259. }
  260. TEST_F(PermissionAuditingDatabaseTest, UpdateEndTimeChecksTimerangeConstraint) {
  261. auto session = SessionLike(kTestTypes[0], kTestUrl1, test_sessions_[0]);
  262. ASSERT_TRUE(db().StorePermissionUsage(session));
  263. EXPECT_TRUE(UpdateEndTime(kTestTypes[0], kTestUrl1, session.usage_start,
  264. session.usage_start));
  265. }
  266. } // namespace permissions