Commit 48214c92 authored by evliu's avatar evliu Committed by Commit Bot

Media History DB

This CL creates the Media History database and the accopmanying tables
that will be used to store information relating to media engagement.

Design doc: https://docs.google.com/document/d/1RAq_RY-R87Dlrkbjnq5ghs7Joax2JIKBHuFBHMlqFdc

Bug: 997813
Change-Id: I3848d172a8cda7b42ead4aa6f409435d6fc83412
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1857044
Commit-Queue: Evan Liu <evliu@google.com>
Reviewed-by: default avatarDale Curtis <dalecurtis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#707549}
parent 2b100d3f
...@@ -672,6 +672,22 @@ jumbo_static_library("browser") { ...@@ -672,6 +672,22 @@ jumbo_static_library("browser") {
"media/cast_mirroring_service_host.h", "media/cast_mirroring_service_host.h",
"media/cast_remoting_connector.cc", "media/cast_remoting_connector.cc",
"media/cast_remoting_connector.h", "media/cast_remoting_connector.h",
"media/history/media_history_engagement_table.cc",
"media/history/media_history_engagement_table.h",
"media/history/media_history_keyed_service.cc",
"media/history/media_history_keyed_service.h",
"media/history/media_history_keyed_service_factory.cc",
"media/history/media_history_keyed_service_factory.h",
"media/history/media_history_origin_table.cc",
"media/history/media_history_origin_table.h",
"media/history/media_history_playback_table.cc",
"media/history/media_history_playback_table.h",
"media/history/media_history_store.cc",
"media/history/media_history_store.h",
"media/history/media_history_table_base.cc",
"media/history/media_history_table_base.h",
"media/history/media_player_watchtime.cc",
"media/history/media_player_watchtime.h",
"media/media_access_handler.cc", "media/media_access_handler.cc",
"media/media_access_handler.h", "media/media_access_handler.h",
"media/media_device_id_salt.cc", "media/media_device_id_salt.cc",
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/media/history/media_history_engagement_table.h"
#include "base/strings/stringprintf.h"
#include "sql/statement.h"
namespace media_history {
MediaHistoryEngagementTable::MediaHistoryEngagementTable(
scoped_refptr<base::UpdateableSequencedTaskRunner> db_task_runner)
: MediaHistoryTableBase(std::move(db_task_runner)) {}
MediaHistoryEngagementTable::~MediaHistoryEngagementTable() = default;
sql::InitStatus MediaHistoryEngagementTable::CreateTableIfNonExistent() {
if (!CanAccessDatabase())
return sql::INIT_FAILURE;
bool success = DB()->Execute(
"CREATE TABLE IF NOT EXISTS mediaEngagement("
"origin_id INTEGER PRIMARY KEY,"
"last_updated INTEGER,"
"visits INTEGER,"
"playbacks INTEGER,"
"last_playback_time REAL,"
"has_high_score INTEGER,"
"CONSTRAINT fk_origin "
"FOREIGN KEY (origin_id) "
"REFERENCES origin(id) "
"ON DELETE CASCADE"
")");
if (!success) {
ResetDB();
LOG(ERROR) << "Failed to create media history engagement table.";
return sql::INIT_FAILURE;
}
return sql::INIT_OK;
}
} // namespace media_history
\ No newline at end of file
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_MEDIA_HISTORY_MEDIA_HISTORY_ENGAGEMENT_TABLE_H_
#define CHROME_BROWSER_MEDIA_HISTORY_MEDIA_HISTORY_ENGAGEMENT_TABLE_H_
#include "base/updateable_sequenced_task_runner.h"
#include "chrome/browser/media/history/media_history_table_base.h"
#include "sql/init_status.h"
#include "url/origin.h"
namespace media_history {
class MediaHistoryEngagementTable : public MediaHistoryTableBase {
public:
struct MediaEngagementScore {
MediaEngagementScore();
url::Origin& origin;
base::TimeDelta last_updated; // timestamp (epoch seconds)
int visits;
int playbacks;
base::TimeDelta last_playback_time;
bool has_high_score;
};
private:
friend class MediaHistoryStoreInternal;
explicit MediaHistoryEngagementTable(
scoped_refptr<base::UpdateableSequencedTaskRunner> db_task_runner);
~MediaHistoryEngagementTable() override;
// MediaHistoryTableBase:
sql::InitStatus CreateTableIfNonExistent() override;
DISALLOW_COPY_AND_ASSIGN(MediaHistoryEngagementTable);
};
} // namespace media_history
#endif // CHROME_BROWSER_MEDIA_HISTORY_MEDIA_HISTORY_ENGAGEMENT_TABLE_H_
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/media/history/media_history_keyed_service.h"
#include "base/task/post_task.h"
#include "chrome/browser/media/history/media_history_keyed_service_factory.h"
#include "content/public/browser/browser_context.h"
namespace media_history {
MediaHistoryKeyedService::MediaHistoryKeyedService(
content::BrowserContext* browser_context) {
DCHECK(!browser_context->IsOffTheRecord());
auto db_task_runner = base::CreateUpdateableSequencedTaskRunner(
{base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
media_history_store_ = std::make_unique<MediaHistoryStore>(
Profile::FromBrowserContext(browser_context), std::move(db_task_runner));
}
// static
MediaHistoryKeyedService* MediaHistoryKeyedService::Get(Profile* profile) {
return MediaHistoryKeyedServiceFactory::GetForProfile(profile);
}
MediaHistoryKeyedService::~MediaHistoryKeyedService() = default;
} // namespace media_history
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_MEDIA_HISTORY_MEDIA_HISTORY_KEYED_SERVICE_H_
#define CHROME_BROWSER_MEDIA_HISTORY_MEDIA_HISTORY_KEYED_SERVICE_H_
#include "base/macros.h"
#include "chrome/browser/media/history/media_history_store.h"
#include "components/keyed_service/core/keyed_service.h"
namespace content {
class BrowserContext;
} // namespace content
namespace media_history {
class MediaHistoryKeyedService : public KeyedService {
public:
explicit MediaHistoryKeyedService(content::BrowserContext* browser_context);
~MediaHistoryKeyedService() override;
// Returns the instance attached to the given |profile|.
static MediaHistoryKeyedService* Get(Profile* profile);
private:
std::unique_ptr<MediaHistoryStore> media_history_store_;
DISALLOW_COPY_AND_ASSIGN(MediaHistoryKeyedService);
};
} // namespace media_history
#endif // CHROME_BROWSER_MEDIA_HISTORY_MEDIA_HISTORY_KEYED_SERVICE_H_
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/media/history/media_history_keyed_service_factory.h"
#include "base/logging.h"
#include "chrome/browser/media/history/media_history_keyed_service.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "content/public/browser/browser_context.h"
namespace media_history {
// static
MediaHistoryKeyedService* MediaHistoryKeyedServiceFactory::GetForProfile(
Profile* profile) {
if (profile->IsOffTheRecord())
return nullptr;
return static_cast<MediaHistoryKeyedService*>(
GetInstance()->GetServiceForBrowserContext(profile, true));
}
// static
MediaHistoryKeyedServiceFactory*
MediaHistoryKeyedServiceFactory::GetInstance() {
static base::NoDestructor<MediaHistoryKeyedServiceFactory> factory;
return factory.get();
}
MediaHistoryKeyedServiceFactory::MediaHistoryKeyedServiceFactory()
: BrowserContextKeyedServiceFactory(
"MediaHistoryKeyedService",
BrowserContextDependencyManager::GetInstance()) {}
MediaHistoryKeyedServiceFactory::~MediaHistoryKeyedServiceFactory() = default;
bool MediaHistoryKeyedServiceFactory::ServiceIsCreatedWithBrowserContext()
const {
return true;
}
KeyedService* MediaHistoryKeyedServiceFactory::BuildServiceInstanceFor(
content::BrowserContext* context) const {
DCHECK(!context->IsOffTheRecord());
return new MediaHistoryKeyedService(context);
}
} // namespace media_history
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_MEDIA_HISTORY_MEDIA_HISTORY_KEYED_SERVICE_FACTORY_H_
#define CHROME_BROWSER_MEDIA_HISTORY_MEDIA_HISTORY_KEYED_SERVICE_FACTORY_H_
#include "base/no_destructor.h"
#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
class KeyedService;
class Profile;
namespace content {
class BrowserContext;
} // namespace content
namespace media_history {
class MediaHistoryKeyedService;
class MediaHistoryKeyedServiceFactory
: public BrowserContextKeyedServiceFactory {
public:
static MediaHistoryKeyedService* GetForProfile(Profile* profile);
static MediaHistoryKeyedServiceFactory* GetInstance();
protected:
bool ServiceIsCreatedWithBrowserContext() const override;
private:
friend class base::NoDestructor<MediaHistoryKeyedServiceFactory>;
MediaHistoryKeyedServiceFactory();
~MediaHistoryKeyedServiceFactory() override;
KeyedService* BuildServiceInstanceFor(
content::BrowserContext* context) const override;
DISALLOW_COPY_AND_ASSIGN(MediaHistoryKeyedServiceFactory);
};
} // namespace media_history
#endif // CHROME_BROWSER_MEDIA_HISTORY_MEDIA_HISTORY_KEYED_SERVICE_FACTORY_H_
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/media/history/media_history_keyed_service_factory.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace media_history {
class MediaHistoryKeyedServiceFactoryUnitTest : public testing::Test {
public:
MediaHistoryKeyedServiceFactoryUnitTest() = default;
private:
content::BrowserTaskEnvironment task_environment_;
};
TEST_F(MediaHistoryKeyedServiceFactoryUnitTest, GetForOTRProfile) {
TestingProfile profile;
Profile* otr_profile = profile.GetOffTheRecordProfile();
EXPECT_EQ(nullptr,
MediaHistoryKeyedServiceFactory::GetForProfile(otr_profile));
}
} // namespace media_history
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/media/history/media_history_origin_table.h"
#include "base/strings/stringprintf.h"
#include "sql/statement.h"
namespace media_history {
MediaHistoryOriginTable::MediaHistoryOriginTable(
scoped_refptr<base::UpdateableSequencedTaskRunner> db_task_runner)
: MediaHistoryTableBase(std::move(db_task_runner)) {}
MediaHistoryOriginTable::~MediaHistoryOriginTable() = default;
sql::InitStatus MediaHistoryOriginTable::CreateTableIfNonExistent() {
if (!CanAccessDatabase())
return sql::INIT_FAILURE;
bool success = DB()->Execute(
"CREATE TABLE IF NOT EXISTS origin("
"id INTEGER PRIMARY KEY AUTOINCREMENT,"
"origin TEXT NOT NULL UNIQUE)");
if (!success) {
ResetDB();
LOG(ERROR) << "Failed to create media history origin table.";
return sql::INIT_FAILURE;
}
return sql::INIT_OK;
}
void MediaHistoryOriginTable::CreateOriginId(const std::string& origin) {
if (!CanAccessDatabase())
return;
if (!DB()->BeginTransaction()) {
LOG(ERROR) << "Failed to begin the transaction to create an origin ID.";
return;
}
// Insert the origin into the table if it does not exist.
sql::Statement statement(
DB()->GetCachedStatement(SQL_FROM_HERE,
"INSERT OR IGNORE INTO origin"
"(origin) "
"VALUES (?)"));
statement.BindString(0, origin);
if (!statement.Run()) {
DB()->RollbackTransaction();
LOG(ERROR) << "Failed to create the origin ID.";
return;
}
DB()->CommitTransaction();
}
} // namespace media_history
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_MEDIA_HISTORY_MEDIA_HISTORY_ORIGIN_TABLE_H_
#define CHROME_BROWSER_MEDIA_HISTORY_MEDIA_HISTORY_ORIGIN_TABLE_H_
#include "base/updateable_sequenced_task_runner.h"
#include "chrome/browser/media/history/media_history_table_base.h"
#include "sql/init_status.h"
namespace media_history {
class MediaHistoryOriginTable : public MediaHistoryTableBase {
private:
friend class MediaHistoryStoreInternal;
explicit MediaHistoryOriginTable(
scoped_refptr<base::UpdateableSequencedTaskRunner> db_task_runner);
~MediaHistoryOriginTable() override;
// MediaHistoryTableBase:
sql::InitStatus CreateTableIfNonExistent() override;
void CreateOriginId(const std::string& origin);
DISALLOW_COPY_AND_ASSIGN(MediaHistoryOriginTable);
};
} // namespace media_history
#endif // CHROME_BROWSER_MEDIA_HISTORY_MEDIA_HISTORY_ORIGIN_TABLE_H_
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/media/history/media_history_playback_table.h"
#include "base/strings/stringprintf.h"
#include "base/updateable_sequenced_task_runner.h"
#include "chrome/browser/media/history/media_player_watchtime.h"
#include "content/public/browser/media_player_id.h"
#include "sql/statement.h"
namespace media_history {
MediaHistoryPlaybackTable::MediaHistoryPlaybackTable(
scoped_refptr<base::UpdateableSequencedTaskRunner> db_task_runner)
: MediaHistoryTableBase(std::move(db_task_runner)) {}
MediaHistoryPlaybackTable::~MediaHistoryPlaybackTable() = default;
sql::InitStatus MediaHistoryPlaybackTable::CreateTableIfNonExistent() {
if (!CanAccessDatabase())
return sql::INIT_FAILURE;
bool success = DB()->Execute(
"CREATE TABLE IF NOT EXISTS playback("
"id INTEGER PRIMARY KEY AUTOINCREMENT,"
"origin_id INTEGER NOT NULL,"
"url TEXT,"
"timestamp_ms INTEGER,"
"has_audio INTEGER,"
"has_video INTEGER,"
"watchtime_ms INTEGER,"
"CONSTRAINT fk_origin "
"FOREIGN KEY (origin_id) "
"REFERENCES origin(id) "
"ON DELETE CASCADE"
")");
if (success) {
success = DB()->Execute(
"CREATE INDEX IF NOT EXISTS origin_id_index ON "
"playback (origin_id)");
}
if (success) {
success = DB()->Execute(
"CREATE INDEX IF NOT EXISTS timestamp_index ON "
"playback (timestamp_ms)");
}
if (!success) {
ResetDB();
LOG(ERROR) << "Failed to create media history playback table.";
return sql::INIT_FAILURE;
}
return sql::INIT_OK;
}
void MediaHistoryPlaybackTable::SavePlayback(
const content::MediaPlayerId& id,
const content::MediaPlayerWatchtime& watchtime) {
if (!CanAccessDatabase())
return;
if (!DB()->BeginTransaction())
return;
sql::Statement statement(DB()->GetCachedStatement(
SQL_FROM_HERE,
"INSERT INTO playback "
"(origin_id, has_audio, has_video, watchtime_ms, url, timestamp_ms) "
"VALUES ((SELECT id FROM origin WHERE origin = ?), ?, ?, ?, ?, ?)"));
statement.BindString(0, watchtime.origin);
statement.BindBool(1, watchtime.has_audio);
statement.BindBool(2, watchtime.has_video);
statement.BindInt(3, watchtime.cumulative_watchtime.InMilliseconds());
statement.BindString(4, watchtime.url);
statement.BindInt(5, watchtime.last_timestamp.InMilliseconds());
if (!statement.Run()) {
DB()->RollbackTransaction();
return;
}
DB()->CommitTransaction();
}
MediaHistoryPlaybackTable::MediaHistoryPlaybacks
MediaHistoryPlaybackTable::GetRecentPlaybacks(int num_results) {
MediaHistoryPlaybacks results;
sql::Statement statement(
DB()->GetCachedStatement(SQL_FROM_HERE,
"SELECT id, origin_id, has_audio, has_video, "
"watchtime_ms, timestamp_ms"
"FROM playback ORDER BY id DESC"
"LIMIT ?"));
statement.BindInt(0, num_results);
while (statement.Step()) {
MediaHistoryPlaybackTable::MediaHistoryPlayback playback;
playback.has_audio = statement.ColumnInt(2);
playback.has_video = statement.ColumnInt(3);
playback.watchtime =
base::TimeDelta::FromMilliseconds(statement.ColumnInt(4));
playback.timestamp =
base::TimeDelta::FromMilliseconds(statement.ColumnInt(5));
results.push_back(playback);
}
return results;
}
} // namespace media_history
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_MEDIA_HISTORY_MEDIA_HISTORY_PLAYBACK_TABLE_H_
#define CHROME_BROWSER_MEDIA_HISTORY_MEDIA_HISTORY_PLAYBACK_TABLE_H_
#include "chrome/browser/media/history/media_history_table_base.h"
#include "sql/init_status.h"
namespace base {
class UpdateableSequencedTaskRunner;
} // namespace base
namespace content {
struct MediaPlayerId;
struct MediaPlayerWatchtime;
} // namespace content
namespace media_history {
class MediaHistoryPlaybackTable : public MediaHistoryTableBase {
public:
struct MediaHistoryPlayback {
MediaHistoryPlayback() = default;
bool has_audio;
bool has_video;
base::TimeDelta watchtime;
base::TimeDelta timestamp;
};
using MediaHistoryPlaybacks = std::vector<MediaHistoryPlayback>;
private:
friend class MediaHistoryStoreInternal;
explicit MediaHistoryPlaybackTable(
scoped_refptr<base::UpdateableSequencedTaskRunner> db_task_runner);
~MediaHistoryPlaybackTable() override;
// MediaHistoryTableBase:
sql::InitStatus CreateTableIfNonExistent() override;
void SavePlayback(const content::MediaPlayerId& id,
const content::MediaPlayerWatchtime& watchtime);
// Returns |num_results| playbacks sorted by time with the
// newest first.
MediaHistoryPlaybacks GetRecentPlaybacks(int num_results);
DISALLOW_COPY_AND_ASSIGN(MediaHistoryPlaybackTable);
};
} // namespace media_history
#endif // CHROME_BROWSER_MEDIA_HISTORY_MEDIA_HISTORY_PLAYBACK_TABLE_H_
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/media/history/media_history_store.h"
#include "chrome/browser/media/history/media_player_watchtime.h"
#include "content/public/browser/media_player_id.h"
namespace {
constexpr int kCurrentVersionNumber = 1;
constexpr int kCompatibleVersionNumber = 1;
constexpr base::FilePath::CharType kMediaHistoryDatabaseName[] =
FILE_PATH_LITERAL("Media History");
} // namespace
int GetCurrentVersion() {
return kCurrentVersionNumber;
}
namespace media_history {
// Refcounted as it is created, initialized and destroyed on a different thread
// from the DB sequence provided to the constructor of this class that is
// required for all methods performing database access.
class MediaHistoryStoreInternal
: public base::RefCountedThreadSafe<MediaHistoryStoreInternal> {
private:
friend class base::RefCountedThreadSafe<MediaHistoryStoreInternal>;
friend class MediaHistoryStore;
explicit MediaHistoryStoreInternal(
Profile* profile,
scoped_refptr<base::UpdateableSequencedTaskRunner> db_task_runner);
virtual ~MediaHistoryStoreInternal();
void SavePlayback(const content::MediaPlayerId& id,
const content::MediaPlayerWatchtime& watchtime);
private:
// Opens the database file from the profile path. Separated from the
// constructor to ease construction/destruction of this object on one thread
// and database access on the DB sequence of |db_task_runner_|.
void Initialize();
sql::InitStatus CreateOrUpgradeIfNeeded();
sql::InitStatus InitializeTables();
void CreateOriginId(const std::string& origin);
scoped_refptr<base::UpdateableSequencedTaskRunner> db_task_runner_;
base::FilePath db_path_;
std::unique_ptr<sql::Database> db_;
sql::MetaTable meta_table_;
scoped_refptr<MediaHistoryEngagementTable> engagement_table_;
scoped_refptr<MediaHistoryOriginTable> origin_table_;
scoped_refptr<MediaHistoryPlaybackTable> playback_table_;
bool initialization_successful_;
DISALLOW_COPY_AND_ASSIGN(MediaHistoryStoreInternal);
};
MediaHistoryStoreInternal::MediaHistoryStoreInternal(
Profile* profile,
scoped_refptr<base::UpdateableSequencedTaskRunner> db_task_runner)
: db_task_runner_(db_task_runner),
db_path_(profile->GetPath().Append(kMediaHistoryDatabaseName)),
engagement_table_(new MediaHistoryEngagementTable(db_task_runner_)),
origin_table_(new MediaHistoryOriginTable(db_task_runner_)),
playback_table_(new MediaHistoryPlaybackTable(db_task_runner_)),
initialization_successful_(false) {}
MediaHistoryStoreInternal::~MediaHistoryStoreInternal() {
db_task_runner_->ReleaseSoon(FROM_HERE, std::move(engagement_table_));
db_task_runner_->ReleaseSoon(FROM_HERE, std::move(origin_table_));
db_task_runner_->ReleaseSoon(FROM_HERE, std::move(playback_table_));
db_task_runner_->DeleteSoon(FROM_HERE, std::move(db_));
}
void MediaHistoryStoreInternal::SavePlayback(
const content::MediaPlayerId& id,
const content::MediaPlayerWatchtime& watchtime) {
DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
if (!initialization_successful_)
return;
CreateOriginId(watchtime.origin);
db_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&MediaHistoryPlaybackTable::SavePlayback,
playback_table_, id, watchtime));
}
void MediaHistoryStoreInternal::Initialize() {
DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
db_ = std::make_unique<sql::Database>();
db_->set_histogram_tag("MediaHistory");
bool success = db_->Open(db_path_);
DCHECK(success);
db_->Preload();
meta_table_.Init(db_.get(), GetCurrentVersion(), kCompatibleVersionNumber);
sql::InitStatus status = CreateOrUpgradeIfNeeded();
if (status != sql::INIT_OK) {
LOG(ERROR) << "Failed to create or update the media history store.";
return;
}
status = InitializeTables();
if (status != sql::INIT_OK) {
LOG(ERROR) << "Failed to initialize the media history store tables.";
return;
}
initialization_successful_ = true;
}
sql::InitStatus MediaHistoryStoreInternal::CreateOrUpgradeIfNeeded() {
if (!db_)
return sql::INIT_FAILURE;
int cur_version = meta_table_.GetVersionNumber();
if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) {
LOG(WARNING) << "Media history database is too new.";
return sql::INIT_TOO_NEW;
}
LOG_IF(WARNING, cur_version < GetCurrentVersion())
<< "Media history database version " << cur_version
<< " is too old to handle.";
return sql::INIT_OK;
}
sql::InitStatus MediaHistoryStoreInternal::InitializeTables() {
DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
sql::InitStatus status = engagement_table_->Initialize(db_.get());
if (status == sql::INIT_OK)
status = origin_table_->Initialize(db_.get());
if (status == sql::INIT_OK)
status = playback_table_->Initialize(db_.get());
return status;
}
void MediaHistoryStoreInternal::CreateOriginId(const std::string& origin) {
DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
if (!initialization_successful_)
return;
db_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&MediaHistoryOriginTable::CreateOriginId,
origin_table_, origin));
}
MediaHistoryStore::MediaHistoryStore(
Profile* profile,
scoped_refptr<base::UpdateableSequencedTaskRunner> db_task_runner)
: db_(new MediaHistoryStoreInternal(profile, db_task_runner)) {
db_task_runner->PostTask(
FROM_HERE, base::BindOnce(&MediaHistoryStoreInternal::Initialize, db_));
}
MediaHistoryStore::~MediaHistoryStore() {}
} // namespace media_history
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_MEDIA_HISTORY_MEDIA_HISTORY_STORE_H_
#define CHROME_BROWSER_MEDIA_HISTORY_MEDIA_HISTORY_STORE_H_
#include <memory>
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
#include "base/updateable_sequenced_task_runner.h"
#include "chrome/browser/media/history/media_history_engagement_table.h"
#include "chrome/browser/media/history/media_history_origin_table.h"
#include "chrome/browser/media/history/media_history_playback_table.h"
#include "chrome/browser/profiles/profile.h"
#include "sql/database.h"
#include "sql/init_status.h"
#include "sql/meta_table.h"
namespace sql {
class Database;
}
namespace media_history {
class MediaHistoryStoreInternal;
class MediaHistoryStore {
public:
MediaHistoryStore(
Profile* profile,
scoped_refptr<base::UpdateableSequencedTaskRunner> db_task_runner);
~MediaHistoryStore();
private:
scoped_refptr<MediaHistoryStoreInternal> db_;
};
} // namespace media_history
#endif // CHROME_BROWSER_MEDIA_HISTORY_MEDIA_HISTORY_STORE_H_
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/media/history/media_history_store.h"
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool/pooled_sequenced_task_runner.h"
#include "base/test/test_timeouts.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_utils.h"
#include "sql/database.h"
#include "sql/statement.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace media_history {
class MediaHistoryStoreUnitTest : public testing::Test {
public:
MediaHistoryStoreUnitTest() = default;
void SetUp() override {
// Set up the profile.
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
TestingProfile::Builder profile_builder;
profile_builder.SetPath(temp_dir_.GetPath());
// Set up the media history store.
scoped_refptr<base::UpdateableSequencedTaskRunner> task_runner =
base::CreateUpdateableSequencedTaskRunner(
{base::ThreadPool(), base::MayBlock(),
base::WithBaseSyncPrimitives()});
media_history_store_ = std::make_unique<MediaHistoryStore>(
profile_builder.Build().get(), task_runner);
// Sleep the thread to allow the media history store to asynchronously
// create the database and tables before proceeding with the tests and
// tearing down the temporary directory.
content::RunAllTasksUntilIdle();
// Set up the local DB connection used for assertions.
base::FilePath db_file =
temp_dir_.GetPath().Append(FILE_PATH_LITERAL("Media History"));
EXPECT_TRUE(db_.Open(db_file));
}
protected:
sql::Database& GetDB() { return db_; }
content::BrowserTaskEnvironment task_environment_;
private:
sql::Database db_;
std::unique_ptr<MediaHistoryStore> media_history_store_;
base::ScopedTempDir temp_dir_;
};
TEST_F(MediaHistoryStoreUnitTest, CreateDatabaseTables) {
ASSERT_TRUE(GetDB().DoesTableExist("mediaEngagement"));
ASSERT_TRUE(GetDB().DoesTableExist("origin"));
ASSERT_TRUE(GetDB().DoesTableExist("playback"));
}
} // namespace media_history
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/media/history/media_history_table_base.h"
#include "base/updateable_sequenced_task_runner.h"
namespace media_history {
base::UpdateableSequencedTaskRunner* MediaHistoryTableBase::GetTaskRunner() {
return db_task_runner_.get();
}
MediaHistoryTableBase::MediaHistoryTableBase(
scoped_refptr<base::UpdateableSequencedTaskRunner> db_task_runner)
: db_task_runner_(std::move(db_task_runner)), db_(nullptr) {}
MediaHistoryTableBase::~MediaHistoryTableBase() = default;
sql::InitStatus MediaHistoryTableBase::Initialize(sql::Database* db) {
DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
DCHECK(db);
db_ = db;
return CreateTableIfNonExistent();
}
sql::Database* MediaHistoryTableBase::DB() {
DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
return db_;
}
void MediaHistoryTableBase::ResetDB() {
DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
db_ = nullptr;
}
bool MediaHistoryTableBase::CanAccessDatabase() {
DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
return db_;
}
} // namespace media_history
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_MEDIA_HISTORY_MEDIA_HISTORY_TABLE_BASE_H_
#define CHROME_BROWSER_MEDIA_HISTORY_MEDIA_HISTORY_TABLE_BASE_H_
#include "base/memory/ref_counted.h"
#include "sql/init_status.h"
namespace base {
class UpdateableSequencedTaskRunner;
} // namespace base
namespace sql {
class Database;
} // namespace sql
namespace media_history {
// Base class for all tables in the MediaHistoryTableBase.
class MediaHistoryTableBase
: public base::RefCountedThreadSafe<MediaHistoryTableBase> {
protected:
explicit MediaHistoryTableBase(
scoped_refptr<base::UpdateableSequencedTaskRunner> db_task_runner);
virtual ~MediaHistoryTableBase();
// Returns a UpdateableSequencedTaskRunner that is used to run tasks on the DB
// sequence.
base::UpdateableSequencedTaskRunner* GetTaskRunner();
// DB sequence functions.
virtual sql::InitStatus CreateTableIfNonExistent() = 0;
sql::InitStatus Initialize(sql::Database* db);
sql::Database* DB();
void ResetDB();
bool CanAccessDatabase();
private:
friend class base::RefCountedThreadSafe<MediaHistoryTableBase>;
scoped_refptr<base::UpdateableSequencedTaskRunner> db_task_runner_;
sql::Database* db_;
DISALLOW_COPY_AND_ASSIGN(MediaHistoryTableBase);
};
} // namespace media_history
#endif // CHROME_BROWSER_MEDIA_HISTORY_MEDIA_HISTORY_TABLE_BASE_H_
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/media/history/media_player_watchtime.h"
namespace content {
MediaPlayerWatchtime::MediaPlayerWatchtime(bool has_audio,
bool has_video,
base::TimeDelta cumulative_watchtime,
base::TimeDelta last_timestamp)
: has_audio(has_audio),
has_video(has_video),
cumulative_watchtime(cumulative_watchtime),
last_timestamp(last_timestamp) {}
MediaPlayerWatchtime::MediaPlayerWatchtime(const MediaPlayerWatchtime& other) =
default;
} // namespace content
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_MEDIA_HISTORY_MEDIA_PLAYER_WATCHTIME_H_
#define CHROME_BROWSER_MEDIA_HISTORY_MEDIA_PLAYER_WATCHTIME_H_
#include <string>
#include "base/time/time.h"
namespace content {
struct MediaPlayerWatchtime {
MediaPlayerWatchtime(bool has_audio,
bool has_video,
base::TimeDelta cumulative_watchtime,
base::TimeDelta last_timestamp);
MediaPlayerWatchtime(const MediaPlayerWatchtime& other);
~MediaPlayerWatchtime() = default;
bool has_audio;
bool has_video;
base::TimeDelta cumulative_watchtime;
base::TimeDelta last_timestamp;
std::string origin;
std::string url;
};
} // namespace content
#endif // CHROME_BROWSER_MEDIA_HISTORY_MEDIA_PLAYER_WATCHTIME_H_
...@@ -3011,6 +3011,8 @@ test("unit_tests") { ...@@ -3011,6 +3011,8 @@ test("unit_tests") {
"../browser/mac/keystone_glue_unittest.mm", "../browser/mac/keystone_glue_unittest.mm",
"../browser/media/android/router/media_router_android_unittest.cc", "../browser/media/android/router/media_router_android_unittest.cc",
"../browser/media/cast_mirroring_service_host_unittest.cc", "../browser/media/cast_mirroring_service_host_unittest.cc",
"../browser/media/history/media_history_keyed_service_factory_unittest.cc",
"../browser/media/history/media_history_store_unittest.cc",
"../browser/media/media_engagement_contents_observer_unittest.cc", "../browser/media/media_engagement_contents_observer_unittest.cc",
"../browser/media/media_engagement_preloaded_list_unittest.cc", "../browser/media/media_engagement_preloaded_list_unittest.cc",
"../browser/media/media_engagement_score_unittest.cc", "../browser/media/media_engagement_score_unittest.cc",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment