Commit 061f86e4 authored by John Delaney's avatar John Delaney Committed by Commit Bot

Implement sqlite storage layer for conversion measurement API

This change implements a storage layer in sqlite for persisting
impressions and conversions from the API to disk.

The storage for the API consists of two tables, an impression table and
a conversion table. Every row in the conversion table is associated with
an impression in the impression table to reuse common data such as
conversion and reporting origins.

The storage layer does not implement specific functionality like last
clicked attribution, bit limits, or reporting delays. Instead it abstracts
that functionality to an injectable delegate class.

This change also includes some common structs that are used by the API,
such as a new mojo struct blink::mojom::Conversion.

The functionality of the API is described on
https://github.com/csharrison/conversion-measurement-api

Reference prototype change:
https://chromium-review.googlesource.com/c/chromium/src/+/1967220

Bug: 1014604
Change-Id: Icff2d720fe7c595398835fcfd026f6d321cb9c99
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1965450
Commit-Queue: John Delaney <johnidel@chromium.org>
Reviewed-by: default avatarVictor Costan <pwnall@chromium.org>
Reviewed-by: default avatarCharlie Harrison <csharrison@chromium.org>
Reviewed-by: default avatarJohn Abd-El-Malek <jam@chromium.org>
Cr-Commit-Position: refs/heads/master@{#735418}
parent 0d581e87
...@@ -671,6 +671,15 @@ jumbo_source_set("browser") { ...@@ -671,6 +671,15 @@ jumbo_source_set("browser") {
"content_index/content_index_service_impl.h", "content_index/content_index_service_impl.h",
"content_service_delegate_impl.cc", "content_service_delegate_impl.cc",
"content_service_delegate_impl.h", "content_service_delegate_impl.h",
"conversions/conversion_report.cc",
"conversions/conversion_report.h",
"conversions/conversion_storage.h",
"conversions/conversion_storage_sql.cc",
"conversions/conversion_storage_sql.h",
"conversions/storable_conversion.cc",
"conversions/storable_conversion.h",
"conversions/storable_impression.cc",
"conversions/storable_impression.h",
"cookie_store/cookie_change_subscription.cc", "cookie_store/cookie_change_subscription.cc",
"cookie_store/cookie_change_subscription.h", "cookie_store/cookie_change_subscription.h",
"cookie_store/cookie_store_context.cc", "cookie_store/cookie_store_context.cc",
......
csharrison@chromium.org
johnidel@chromium.org
# TEAM: privacy-sandbox-dev@chromium.org
# TODO(https://crbug.com/1045468): Add a component for ConversionMeasurement.
// Copyright 2020 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 "content/browser/conversions/conversion_report.h"
#include <tuple>
namespace content {
ConversionReport::ConversionReport(const StorableImpression& impression,
const std::string& conversion_data,
base::Time report_time,
const base::Optional<int64_t>& conversion_id)
: impression(impression),
conversion_data(conversion_data),
report_time(report_time),
conversion_id(conversion_id) {}
ConversionReport::ConversionReport(const ConversionReport& other) = default;
ConversionReport::~ConversionReport() = default;
std::ostream& operator<<(std::ostream& out, const ConversionReport& report) {
out << "impression_data: " << report.impression.impression_data()
<< ", impression_origin: " << report.impression.impression_origin()
<< ", conversion_origin: " << report.impression.conversion_origin()
<< ", reporting_origin: " << report.impression.reporting_origin()
<< ", conversion_data: " << report.conversion_data
<< ", report_time: " << report.report_time
<< ", attribution_credit: " << report.attribution_credit;
return out;
}
} // namespace content
// Copyright 2020 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 CONTENT_BROWSER_CONVERSIONS_CONVERSION_REPORT_H_
#define CONTENT_BROWSER_CONVERSIONS_CONVERSION_REPORT_H_
#include <stdint.h>
#include <string>
#include <vector>
#include "base/optional.h"
#include "base/time/time.h"
#include "content/browser/conversions/storable_impression.h"
#include "content/common/content_export.h"
namespace content {
// Struct that contains all the data needed to serialize and send a conversion
// report. This represents the report for a conversion event and its associated
// impression.
struct CONTENT_EXPORT ConversionReport {
// The conversion_id may not be set for a conversion report.
ConversionReport(const StorableImpression& impression,
const std::string& conversion_data,
base::Time report_time,
const base::Optional<int64_t>& conversion_id);
ConversionReport(const ConversionReport& other);
~ConversionReport();
// Impression associated with this conversion report.
const StorableImpression impression;
// Data provided at reporting time by the reporting origin. String
// representing a valid hexadecimal number.
const std::string conversion_data;
// The time this conversion report should be sent.
base::Time report_time;
// The attribution credit assigned to this conversion report. This is derived
// from the set of all impressions that matched a singular conversion event.
// This should be in the range 0-100. A set of ConversionReports for one
// conversion event should have their |attribution_credit| sum equal to 100.
int attribution_credit = 0;
// Id assigned by storage to uniquely identify a completed conversion. If
// null, an ID has not been assigned yet.
const base::Optional<int64_t> conversion_id;
};
// Only used for logging.
CONTENT_EXPORT std::ostream& operator<<(
std::ostream& out,
const ConversionReport& ConversionReport);
} // namespace content
#endif // CONTENT_BROWSER_CONVERSIONS_CONVERSION_REPORT_H_
// Copyright 2020 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 CONTENT_BROWSER_CONVERSIONS_CONVERSION_STORAGE_H_
#define CONTENT_BROWSER_CONVERSIONS_CONVERSION_STORAGE_H_
#include <stdint.h>
#include <vector>
#include "base/time/time.h"
#include "content/browser/conversions/conversion_report.h"
#include "content/browser/conversions/storable_conversion.h"
#include "content/browser/conversions/storable_impression.h"
namespace content {
// This class provides an interface for persisting impression/conversion data to
// disk, and performing queries on it.
class ConversionStorage {
public:
// Storage delegate that can supplied to extend basic conversion storage
// functionality like annotating conversion reports.
class Delegate {
public:
// New conversions will be sent through this callback for
// pruning/modification before they are added to storage. This will be
// called during the execution of
// ConversionStorage::MaybeCreateAndStoreConversionReports(). |reports| will
// contain a report for each matching impression for a given conversion
// event. Each report will be pre-populated from storage with the conversion
// event data.
virtual void ProcessNewConversionReports(
std::vector<ConversionReport>* reports) = 0;
// This limit is used to determine if an impression is allowed to schedule
// a new conversion reports. When an impression reaches this limit it is
// marked inactive and no new conversion reports will be created for it.
// Impressions will be checked against this limit after they schedule a new
// report.
virtual int GetMaxConversionsPerImpression() const = 0;
};
virtual ~ConversionStorage() = default;
// Initializes the storage. Returns true on success, otherwise the storage
// should not be used.
virtual bool Initialize() = 0;
// Add |impression| to storage. Two impressions are considered
// matching when they share a <reporting_origin, conversion_origin> pair. When
// an impression is stored, all matching impressions that have
// already converted are marked as inactive, and are no longer eligible for
// reporting. Unconverted matching impressions are not modified.
virtual void StoreImpression(const StorableImpression& impression) = 0;
// Finds all stored impressions matching a given |conversion|, and stores new
// associated conversion reports. The delegate will receive a call
// to Delegate::ProcessNewConversionReports() before the reports are added to
// storage. Only active impressions will receive new conversions. Returns the
// number of new conversion reports that have been scheduled/added to storage.
virtual int MaybeCreateAndStoreConversionReports(
const StorableConversion& conversion) = 0;
// Returns all of the conversion reports that should be sent before
// |max_report_time|. This call is logically const, and does not modify the
// underlying storage.
virtual std::vector<ConversionReport> GetConversionsToReport(
base::Time max_report_time) = 0;
// Deletes all impressions that have expired and have no pending conversion
// reports. Returns the number of impressions that were deleted.
virtual int DeleteExpiredImpressions() = 0;
// Deletes the conversion report with the given |conversion_id|. Returns
// whether the deletion was successful.
virtual bool DeleteConversion(int64_t conversion_id) = 0;
// TODO(johnidel): Add an API to ConversionStorage that removes site data, and
// hook it into the data remover. This should be added before the API is
// enabled.
};
} // namespace content
#endif // CONTENT_BROWSER_CONVERSIONS_CONVERSION_STORAGE_H_
This diff is collapsed.
// Copyright 2020 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 CONTENT_BROWSER_CONVERSIONS_CONVERSION_STORAGE_SQL_H_
#define CONTENT_BROWSER_CONVERSIONS_CONVERSION_STORAGE_SQL_H_
#include "base/files/file_path.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/time/clock.h"
#include "content/browser/conversions/conversion_report.h"
#include "content/browser/conversions/conversion_storage.h"
#include "content/common/content_export.h"
#include "sql/database.h"
namespace base {
class Clock;
} // namespace base
namespace content {
// Provides an implementation of ConversionStorage that is backed by SQLite.
// This class may be constructed on any sequence but must be accessed and
// destroyed on the same sequence. The sequence must outlive |this|.
class CONTENT_EXPORT ConversionStorageSql : public ConversionStorage {
public:
ConversionStorageSql(const base::FilePath& path_to_database_dir,
Delegate* delegate,
base::Clock* clock);
ConversionStorageSql(const ConversionStorageSql& other) = delete;
ConversionStorageSql& operator=(const ConversionStorageSql& other) = delete;
~ConversionStorageSql() override;
private:
// ConversionStorage
bool Initialize() override;
void StoreImpression(const StorableImpression& impression) override;
int MaybeCreateAndStoreConversionReports(
const StorableConversion& conversion) override;
std::vector<ConversionReport> GetConversionsToReport(
base::Time expiry_time) override;
int DeleteExpiredImpressions() override;
bool DeleteConversion(int64_t conversion_id) override;
bool InitializeSchema();
void DatabaseErrorCallback(int extended_error, sql::Statement* stmt);
const base::FilePath path_to_database_;
sql::Database db_;
// Must outlive |this|.
base::Clock* const clock_;
// Must outlive |this|.
Delegate* const delegate_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<ConversionStorageSql> weak_factory_;
};
} // namespace content
#endif // CONTENT_BROWSER_CONVERSIONS_CONVERSION_STORAGE_SQL_H_
// Copyright 2020 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 "content/browser/conversions/conversion_storage_sql.h"
#include <memory>
#include "base/files/scoped_temp_dir.h"
#include "base/run_loop.h"
#include "base/test/simple_test_clock.h"
#include "content/browser/conversions/conversion_report.h"
#include "content/browser/conversions/conversion_test_utils.h"
#include "content/browser/conversions/storable_conversion.h"
#include "content/browser/conversions/storable_impression.h"
#include "sql/database.h"
#include "sql/test/scoped_error_expecter.h"
#include "sql/test/test_helpers.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
class ConversionStorageSqlTest : public testing::Test {
public:
ConversionStorageSqlTest() = default;
void SetUp() override { ASSERT_TRUE(temp_directory_.CreateUniqueTempDir()); }
void OpenDatabase() {
storage_.reset();
storage_ = std::make_unique<ConversionStorageSql>(temp_directory_.GetPath(),
&delegate_, &clock_);
EXPECT_TRUE(storage_->Initialize());
}
void CloseDatabase() { storage_.reset(); }
void AddReportToStorage() {
storage_->StoreImpression(ImpressionBuilder(clock()->Now()).Build());
storage_->MaybeCreateAndStoreConversionReports(DefaultConversion());
}
base::FilePath db_path() {
return temp_directory_.GetPath().Append(FILE_PATH_LITERAL("Conversions"));
}
base::SimpleTestClock* clock() { return &clock_; }
ConversionStorage* storage() { return storage_.get(); }
private:
base::ScopedTempDir temp_directory_;
std::unique_ptr<ConversionStorage> storage_;
base::SimpleTestClock clock_;
EmptyStorageDelegate delegate_;
};
TEST_F(ConversionStorageSqlTest,
DatabaseInitialized_TablesAndIndexesInitialized) {
OpenDatabase();
CloseDatabase();
sql::Database raw_db;
EXPECT_TRUE(raw_db.Open(db_path()));
// [impressions] and [conversions].
EXPECT_EQ(2u, sql::test::CountSQLTables(&raw_db));
// [conversion_origin_idx], [impression_expiry_idx],
// [conversion_report_time_idx], [conversion_impression_id_idx].
EXPECT_EQ(4u, sql::test::CountSQLIndices(&raw_db));
}
TEST_F(ConversionStorageSqlTest, DatabaseReopened_DataPersisted) {
OpenDatabase();
AddReportToStorage();
EXPECT_EQ(1u, storage()->GetConversionsToReport(clock()->Now()).size());
CloseDatabase();
OpenDatabase();
EXPECT_EQ(1u, storage()->GetConversionsToReport(clock()->Now()).size());
}
TEST_F(ConversionStorageSqlTest, CorruptDatabase_RecoveredOnOpen) {
OpenDatabase();
AddReportToStorage();
EXPECT_EQ(1u, storage()->GetConversionsToReport(clock()->Now()).size());
CloseDatabase();
// Corrupt the database.
EXPECT_TRUE(sql::test::CorruptSizeInHeader(db_path()));
sql::test::ScopedErrorExpecter expecter;
expecter.ExpectError(SQLITE_CORRUPT);
// Open that database and ensure that it does not fail.
EXPECT_NO_FATAL_FAILURE(OpenDatabase());
// Data should be recovered.
EXPECT_EQ(1u, storage()->GetConversionsToReport(clock()->Now()).size());
EXPECT_TRUE(expecter.SawExpectedErrors());
}
} // namespace content
This diff is collapsed.
// Copyright 2020 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 "content/browser/conversions/conversion_test_utils.h"
#include <tuple>
#include "url/gurl.h"
namespace content {
namespace {
const char kDefaultImpressionOrigin[] = "https:/impression.test/";
const char kDefaultConversionOrigin[] = "https:/conversion.test/";
const char kDefaultReportOrigin[] = "https:/report.test/";
// Default expiry time for impressions for testing.
const int64_t kExpiryTime = 30;
} // namespace
int EmptyStorageDelegate::GetMaxConversionsPerImpression() const {
return 1;
}
// Builds an impression with default values. This is done as a builder because
// all values needed to be provided at construction time.
ImpressionBuilder::ImpressionBuilder(base::Time time)
: impression_data_("123"),
impression_time_(time),
expiry_(base::TimeDelta::FromMilliseconds(kExpiryTime)),
impression_origin_(url::Origin::Create(GURL(kDefaultImpressionOrigin))),
conversion_origin_(url::Origin::Create(GURL(kDefaultConversionOrigin))),
reporting_origin_(url::Origin::Create(GURL(kDefaultReportOrigin))) {}
ImpressionBuilder::~ImpressionBuilder() = default;
ImpressionBuilder& ImpressionBuilder::SetExpiry(base::TimeDelta delta) {
expiry_ = delta;
return *this;
}
ImpressionBuilder& ImpressionBuilder::SetData(const std::string& data) {
impression_data_ = data;
return *this;
}
ImpressionBuilder& ImpressionBuilder::SetImpressionOrigin(
const url::Origin& origin) {
impression_origin_ = origin;
return *this;
}
ImpressionBuilder& ImpressionBuilder::SetConversionOrigin(
const url::Origin& origin) {
conversion_origin_ = origin;
return *this;
}
ImpressionBuilder& ImpressionBuilder::SetReportingOrigin(
const url::Origin& origin) {
reporting_origin_ = origin;
return *this;
}
StorableImpression ImpressionBuilder::Build() const {
return StorableImpression(impression_data_, impression_origin_,
conversion_origin_, reporting_origin_,
impression_time_,
impression_time_ + expiry_ /* expiry_time */,
base::nullopt /* impression_id */);
}
StorableConversion DefaultConversion() {
StorableConversion conversion(
"111" /* conversion_data */,
url::Origin::Create(
GURL(kDefaultConversionOrigin)) /* conversion_origin */,
url::Origin::Create(GURL(kDefaultReportOrigin)) /* reporting_origin */);
return conversion;
}
// Custom comparator for comparing two vectors of conversion reports. Does not
// compare impression and conversion id's as they are set by the underlying
// sqlite db and should not be tested.
testing::AssertionResult ReportsEqual(
const std::vector<ConversionReport>& expected,
const std::vector<ConversionReport>& actual) {
const auto tie = [](const ConversionReport& conversion) {
return std::make_tuple(conversion.impression.impression_data(),
conversion.impression.impression_origin(),
conversion.impression.conversion_origin(),
conversion.impression.reporting_origin(),
conversion.impression.impression_time(),
conversion.impression.expiry_time(),
conversion.conversion_data, conversion.report_time,
conversion.attribution_credit);
};
if (expected.size() != actual.size())
return testing::AssertionFailure() << "Expected length " << expected.size()
<< ", actual: " << actual.size();
for (size_t i = 0; i < expected.size(); i++) {
if (tie(expected[i]) != tie(actual[i])) {
return testing::AssertionFailure()
<< "Expected " << expected[i] << " at index " << i
<< ", actual: " << actual[i];
}
}
return testing::AssertionSuccess();
}
} // namespace content
// Copyright 2020 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 CONTENT_BROWSER_CONVERSIONS_CONVERSION_TEST_UTILS_H_
#define CONTENT_BROWSER_CONVERSIONS_CONVERSION_TEST_UTILS_H_
#include <string>
#include <vector>
#include "base/time/time.h"
#include "content/browser/conversions/conversion_report.h"
#include "content/browser/conversions/conversion_storage.h"
#include "content/browser/conversions/storable_conversion.h"
#include "content/browser/conversions/storable_impression.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "url/origin.h"
namespace content {
class EmptyStorageDelegate : public ConversionStorage::Delegate {
public:
EmptyStorageDelegate() = default;
virtual ~EmptyStorageDelegate() = default;
// ConversionStorage::Delegate
void ProcessNewConversionReports(
std::vector<ConversionReport>* reports) override {}
int GetMaxConversionsPerImpression() const override;
};
// Helper class to construct a StorableImpression for tests using default data.
// StorableImpression members are not mutable after construction requiring a
// builder pattern.
class ImpressionBuilder {
public:
ImpressionBuilder(base::Time time);
~ImpressionBuilder();
ImpressionBuilder& SetExpiry(base::TimeDelta delta);
ImpressionBuilder& SetData(const std::string& data);
ImpressionBuilder& SetImpressionOrigin(const url::Origin& origin);
ImpressionBuilder& SetConversionOrigin(const url::Origin& origin);
ImpressionBuilder& SetReportingOrigin(const url::Origin& origin);
StorableImpression Build() const;
private:
std::string impression_data_;
base::Time impression_time_;
base::TimeDelta expiry_;
url::Origin impression_origin_;
url::Origin conversion_origin_;
url::Origin reporting_origin_;
};
// Returns a StorableConversion with default data which matches the default
// impressions created by ImpressionBuilder.
StorableConversion DefaultConversion();
testing::AssertionResult ReportsEqual(
const std::vector<ConversionReport>& expected,
const std::vector<ConversionReport>& actual);
} // namespace content
#endif // CONTENT_BROWSER_CONVERSIONS_CONVERSION_TEST_UTILS_H_
// Copyright 2020 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 "content/browser/conversions/storable_conversion.h"
#include "base/logging.h"
namespace content {
StorableConversion::StorableConversion(const std::string& conversion_data,
const url::Origin& conversion_origin,
const url::Origin& reporting_origin)
: conversion_data_(conversion_data),
conversion_origin_(conversion_origin),
reporting_origin_(reporting_origin) {
DCHECK(!reporting_origin_.opaque());
DCHECK(!conversion_origin_.opaque());
}
StorableConversion::StorableConversion(const StorableConversion& other) =
default;
StorableConversion::~StorableConversion() = default;
} // namespace content
// Copyright 2020 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 CONTENT_BROWSER_CONVERSIONS_STORABLE_CONVERSION_H_
#define CONTENT_BROWSER_CONVERSIONS_STORABLE_CONVERSION_H_
#include <string>
#include "base/time/time.h"
#include "content/common/content_export.h"
#include "url/origin.h"
namespace content {
// Struct which represents a conversion registration event that was observed in
// the renderer and is now being used by the browser process.
class CONTENT_EXPORT StorableConversion {
public:
// Should only be created with values that the browser process has already
// validated. At creation time, |conversion_data_| should already be stripped
// to a lower entropy. |conversion_origin| should be filled by a navigation
// origin known by the browser process.
StorableConversion(const std::string& conversion_data,
const url::Origin& conversion_origin,
const url::Origin& reporting_origin);
StorableConversion(const StorableConversion& other);
StorableConversion& operator=(const StorableConversion& other) = delete;
~StorableConversion();
const std::string& conversion_data() const { return conversion_data_; }
const url::Origin& conversion_origin() const { return conversion_origin_; }
const url::Origin& reporting_origin() const { return reporting_origin_; }
private:
// Conversion data associated with conversion registration event. String
// representing a valid hexadecimal number.
std::string conversion_data_;
// Origin this conversion event occurred on.
url::Origin conversion_origin_;
// Origin of the conversion redirect url, and the origin that will receive any
// reports.
url::Origin reporting_origin_;
};
} // namespace content
#endif // CONTENT_BROWSER_CONVERSIONS_STORABLE_CONVERSION_H_
// Copyright 2020 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 "content/browser/conversions/storable_impression.h"
#include "base/logging.h"
namespace content {
StorableImpression::StorableImpression(
const std::string& impression_data,
const url::Origin& impression_origin,
const url::Origin& conversion_origin,
const url::Origin& reporting_origin,
base::Time impression_time,
base::Time expiry_time,
const base::Optional<int64_t>& impression_id)
: impression_data_(impression_data),
impression_origin_(impression_origin),
conversion_origin_(conversion_origin),
reporting_origin_(reporting_origin),
impression_time_(impression_time),
expiry_time_(expiry_time),
impression_id_(impression_id) {
DCHECK(!impression_origin.opaque());
DCHECK(!reporting_origin.opaque());
DCHECK(!conversion_origin.opaque());
}
StorableImpression::StorableImpression(const StorableImpression& other) =
default;
StorableImpression::~StorableImpression() = default;
} // namespace content
// Copyright 2020 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 CONTENT_BROWSER_CONVERSIONS_STORABLE_IMPRESSION_H_
#define CONTENT_BROWSER_CONVERSIONS_STORABLE_IMPRESSION_H_
#include <stdint.h>
#include <string>
#include "base/optional.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
#include "url/origin.h"
namespace content {
// Struct which represents all stored attributes of an impression. All values
// should be sanitized before creating this object.
class CONTENT_EXPORT StorableImpression {
public:
// If |impression_id| is not available, 0 should be provided.
StorableImpression(const std::string& impression_data,
const url::Origin& impression_origin,
const url::Origin& conversion_origin,
const url::Origin& reporting_origin,
base::Time impression_time,
base::Time expiry_time,
const base::Optional<int64_t>& impression_id);
StorableImpression(const StorableImpression& other);
StorableImpression& operator=(const StorableImpression& other) = delete;
~StorableImpression();
const std::string& impression_data() const { return impression_data_; }
const url::Origin& impression_origin() const { return impression_origin_; }
const url::Origin& conversion_origin() const { return conversion_origin_; }
const url::Origin& reporting_origin() const { return reporting_origin_; }
base::Time impression_time() const { return impression_time_; }
base::Time expiry_time() const { return expiry_time_; }
base::Optional<int64_t> impression_id() const { return impression_id_; }
private:
// String representing a valid hexadecimal number.
std::string impression_data_;
url::Origin impression_origin_;
url::Origin conversion_origin_;
url::Origin reporting_origin_;
base::Time impression_time_;
base::Time expiry_time_;
// If null, an ID has not been assigned yet.
base::Optional<int64_t> impression_id_;
};
} // namespace content
#endif // CONTENT_BROWSER_CONVERSIONS_STORABLE_IMPRESSION_H_
...@@ -50,6 +50,8 @@ jumbo_static_library("test_support") { ...@@ -50,6 +50,8 @@ jumbo_static_library("test_support") {
"../browser/background_fetch/mock_background_fetch_delegate.h", "../browser/background_fetch/mock_background_fetch_delegate.h",
"../browser/browsing_data/browsing_data_test_utils.cc", "../browser/browsing_data/browsing_data_test_utils.cc",
"../browser/browsing_data/browsing_data_test_utils.h", "../browser/browsing_data/browsing_data_test_utils.h",
"../browser/conversions/conversion_test_utils.cc",
"../browser/conversions/conversion_test_utils.h",
"../browser/media/session/mock_media_session_player_observer.cc", "../browser/media/session/mock_media_session_player_observer.cc",
"../browser/media/session/mock_media_session_player_observer.h", "../browser/media/session/mock_media_session_player_observer.h",
"../browser/media/session/mock_media_session_service_impl.cc", "../browser/media/session/mock_media_session_service_impl.cc",
...@@ -1554,6 +1556,8 @@ test("content_unittests") { ...@@ -1554,6 +1556,8 @@ test("content_unittests") {
"../browser/code_cache/generated_code_cache_unittest.cc", "../browser/code_cache/generated_code_cache_unittest.cc",
"../browser/content_index/content_index_database_unittest.cc", "../browser/content_index/content_index_database_unittest.cc",
"../browser/content_index/content_index_service_impl_unittest.cc", "../browser/content_index/content_index_service_impl_unittest.cc",
"../browser/conversions/conversion_storage_sql_unittest.cc",
"../browser/conversions/conversion_storage_unittest.cc",
"../browser/cookie_store/cookie_store_manager_unittest.cc", "../browser/cookie_store/cookie_store_manager_unittest.cc",
"../browser/devtools/devtools_background_services_context_impl_unittest.cc", "../browser/devtools/devtools_background_services_context_impl_unittest.cc",
"../browser/devtools/devtools_http_handler_unittest.cc", "../browser/devtools/devtools_http_handler_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