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