1 // Copyright 2019 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 #ifndef CHROME_BROWSER_MEDIA_HISTORY_MEDIA_HISTORY_STORE_H_
6 #define CHROME_BROWSER_MEDIA_HISTORY_MEDIA_HISTORY_STORE_H_
7 
8 #include <set>
9 #include <vector>
10 
11 #include "base/callback_forward.h"
12 #include "base/files/file_path.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/optional.h"
15 #include "base/synchronization/atomic_flag.h"
16 #include "base/updateable_sequenced_task_runner.h"
17 #include "chrome/browser/media/feeds/media_feeds_store.mojom.h"
18 #include "chrome/browser/media/history/media_history_keyed_service.h"
19 #include "chrome/browser/media/history/media_history_store.mojom.h"
20 #include "chrome/browser/profiles/profile.h"
21 #include "content/public/browser/media_player_watch_time.h"
22 #include "sql/init_status.h"
23 #include "sql/meta_table.h"
24 #include "url/origin.h"
25 
26 namespace media_session {
27 struct MediaImage;
28 struct MediaMetadata;
29 struct MediaPosition;
30 }  // namespace media_session
31 
32 namespace url {
33 class Origin;
34 }  // namespace url
35 
36 namespace media_history {
37 
38 class MediaHistoryOriginTable;
39 class MediaHistoryPlaybackTable;
40 class MediaHistorySessionTable;
41 class MediaHistorySessionImagesTable;
42 class MediaHistoryImagesTable;
43 class MediaHistoryFeedsTable;
44 class MediaHistoryFeedItemsTable;
45 class MediaHistoryKaleidoscopeDataTable;
46 
47 // Refcounted as it is created, initialized and destroyed on a different thread
48 // from the DB sequence provided to the constructor of this class that is
49 // required for all methods performing database access.
50 class MediaHistoryStore : public base::RefCountedThreadSafe<MediaHistoryStore> {
51  public:
52   MediaHistoryStore(
53       Profile* profile,
54       scoped_refptr<base::UpdateableSequencedTaskRunner> db_task_runner);
55   MediaHistoryStore(const MediaHistoryStore& t) = delete;
56   MediaHistoryStore& operator=(const MediaHistoryStore&) = delete;
57 
58   using GetPlaybackSessionsFilter =
59       base::RepeatingCallback<bool(const base::TimeDelta& duration,
60                                    const base::TimeDelta& position)>;
61 
62   static const char kInitResultHistogramName[];
63   static const char kInitResultAfterDeleteHistogramName[];
64   static const char kPlaybackWriteResultHistogramName[];
65   static const char kSessionWriteResultHistogramName[];
66   static const char kDatabaseSizeKbHistogramName[];
67 
68   // When we initialize the database we store the result in
69   // |kInitResultHistogramName|. Do not change the numbering since this
70   // is recorded.
71   enum class InitResult {
72     kSuccess = 0,
73     kFailedNoForeignKeys = 1,
74     kFailedDatabaseTooNew = 2,
75     kFailedInitializeTables = 3,
76     kFailedToCreateDirectory = 4,
77     kFailedToOpenDatabase = 5,
78     kFailedToEstablishTransaction = 6,
79     kFailedToCreateMetaTable = 7,
80     kFailedToCommitTransaction = 8,
81     kFailedToDeleteOldDatabase = 9,
82     kMaxValue = kFailedToDeleteOldDatabase,
83   };
84 
85   // If we write a playback into the database then we record the result to
86   // |kPlaybackWriteResultHistogramName|. Do not change the numbering since this
87   // is recorded.
88   enum class PlaybackWriteResult {
89     kSuccess = 0,
90     kFailedToEstablishTransaction = 1,
91     kFailedToWriteOrigin = 2,
92     kFailedToWritePlayback = 3,
93     kFailedToIncrementAggreatedWatchtime = 4,
94     kFailedToWriteBadOrigin = 5,
95     kMaxValue = kFailedToWriteBadOrigin,
96   };
97 
98   // If we write a session into the database then we record the result to
99   // |kSessionWriteResultHistogramName|. Do not change the numbering since this
100   // is recorded.
101   enum class SessionWriteResult {
102     kSuccess = 0,
103     kFailedToEstablishTransaction = 1,
104     kFailedToWriteOrigin = 2,
105     kFailedToWriteSession = 3,
106     kFailedToWriteImage = 4,
107     kMaxValue = kFailedToWriteImage,
108   };
109 
110  protected:
111   friend class MediaHistoryKeyedService;
112 
113   // Opens the database file from the |db_path|. Separated from the
114   // constructor to ease construction/destruction of this object on one thread
115   // and database access on the DB sequence of |db_task_runner_|. If
116   // |should_reset| is true then this will delete and reset the DB.
117   void Initialize(const bool should_reset);
118 
119   InitResult InitializeInternal();
120   sql::InitStatus CreateOrUpgradeIfNeeded();
121   sql::InitStatus InitializeTables();
122   sql::Database* DB();
123 
124   // Returns a flag indicating whether the origin id was created successfully.
125   bool CreateOriginId(const url::Origin& origin);
126 
127   void SavePlayback(std::unique_ptr<content::MediaPlayerWatchTime> watch_time);
128 
129   mojom::MediaHistoryStatsPtr GetMediaHistoryStats();
130   int GetTableRowCount(const std::string& table_name);
131 
132   std::vector<mojom::MediaHistoryOriginRowPtr> GetOriginRowsForDebug();
133 
134   std::vector<mojom::MediaHistoryPlaybackRowPtr>
135   GetMediaHistoryPlaybackRowsForDebug();
136 
137   std::vector<media_feeds::mojom::MediaFeedItemPtr> GetMediaFeedItems(
138       const MediaHistoryKeyedService::GetMediaFeedItemsRequest& request);
139 
140   std::vector<media_feeds::mojom::MediaFeedPtr> GetMediaFeeds(
141       const MediaHistoryKeyedService::GetMediaFeedsRequest& request);
142 
143   std::vector<url::Origin> GetHighWatchTimeOrigins(
144       const base::TimeDelta& audio_video_watchtime_min);
145 
146   void SavePlaybackSession(
147       const GURL& url,
148       const media_session::MediaMetadata& metadata,
149       const base::Optional<media_session::MediaPosition>& position,
150       const std::vector<media_session::MediaImage>& artwork);
151 
152   std::vector<mojom::MediaHistoryPlaybackSessionRowPtr> GetPlaybackSessions(
153       base::Optional<unsigned int> num_sessions,
154       base::Optional<MediaHistoryStore::GetPlaybackSessionsFilter> filter);
155 
156   void DeleteAllOriginData(const std::set<url::Origin>& origins);
157   void DeleteAllURLData(const std::set<GURL>& urls);
158 
159   std::set<GURL> GetURLsInTableForTest(const std::string& table);
160 
161   void DiscoverMediaFeed(const GURL& url);
162 
163   void StoreMediaFeedFetchResult(
164       MediaHistoryKeyedService::MediaFeedFetchResult result);
165 
166   MediaHistoryKeyedService::PendingSafeSearchCheckList
167   GetPendingSafeSearchCheckMediaFeedItems();
168 
169   void StoreMediaFeedItemSafeSearchResults(
170       std::map<MediaHistoryKeyedService::SafeSearchID,
171                media_feeds::mojom::SafeSearchResult> results);
172 
173   void UpdateMediaFeedDisplayTime(const int64_t feed_id);
174 
175   void ResetMediaFeed(const url::Origin& origin,
176                       media_feeds::mojom::ResetReason reason);
177 
178   void ResetMediaFeedDueToCookies(const url::Origin& origin,
179                                   const bool include_subdomains,
180                                   const std::string& name,
181                                   const net::CookieChangeCause& cause);
182 
183   void ResetMediaFeedDueToCacheClearing(
184       const base::Time& start_time,
185       const base::Time& end_time,
186       MediaHistoryKeyedService::CacheClearingFilter filter);
187 
188   bool ResetMediaFeedInternal(const std::set<int64_t>& feed_ids,
189                               media_feeds::mojom::ResetReason reason);
190 
191   // Cancels pending DB transactions. Should only be called on the UI thread.
192   void SetCancelled();
193 
194   void IncrementMediaFeedItemsShownCount(const std::set<int64_t> feed_item_ids);
195 
196   void MarkMediaFeedItemAsClicked(const int64_t& feed_item_id);
197 
198   void DeleteMediaFeed(const int64_t feed_id);
199 
200   base::Optional<MediaHistoryKeyedService::MediaFeedFetchDetails>
201   GetMediaFeedFetchDetails(const int64_t feed_id);
202 
203   void UpdateFeedUserStatus(const int64_t feed_id,
204                             media_feeds::mojom::FeedUserStatus status);
205 
206   void SetKaleidoscopeData(media::mojom::GetCollectionsResponsePtr data,
207                            const std::string& gaia_id);
208 
209   media::mojom::GetCollectionsResponsePtr GetKaleidoscopeData(
210       const std::string& gaia_id);
211 
212   void DeleteKaleidoscopeData();
213 
214  private:
215   friend class base::RefCountedThreadSafe<MediaHistoryStore>;
216 
217   ~MediaHistoryStore();
218 
219   void StoreMediaFeedFetchResultInternal(
220       MediaHistoryKeyedService::MediaFeedFetchResult result);
221 
222   bool CanAccessDatabase() const;
223   bool IsCancelled() const;
224 
225   scoped_refptr<base::UpdateableSequencedTaskRunner> db_task_runner_;
226   const base::FilePath db_path_;
227   std::unique_ptr<sql::Database> db_;
228   std::unique_ptr<sql::MetaTable> meta_table_;
229   scoped_refptr<MediaHistoryOriginTable> origin_table_;
230   scoped_refptr<MediaHistoryPlaybackTable> playback_table_;
231   scoped_refptr<MediaHistorySessionTable> session_table_;
232   scoped_refptr<MediaHistorySessionImagesTable> session_images_table_;
233   scoped_refptr<MediaHistoryImagesTable> images_table_;
234   scoped_refptr<MediaHistoryFeedsTable> feeds_table_;
235   scoped_refptr<MediaHistoryFeedItemsTable> feed_items_table_;
236   scoped_refptr<MediaHistoryKaleidoscopeDataTable> kaleidoscope_table_;
237   bool initialization_successful_;
238   base::AtomicFlag cancelled_;
239 };
240 
241 }  // namespace media_history
242 
243 #endif  // CHROME_BROWSER_MEDIA_HISTORY_MEDIA_HISTORY_STORE_H_
244