Commit 1af86888 authored by Hesen Zhang's avatar Hesen Zhang Committed by Commit Bot

notification scheduler: Custom throttle layer implementation.

Enable client to customize config related to throttling - mainly
suppression duration and number of negative action count threshold
from client side API -
 std::unique_ptr<ThrottleConfig> GetThrottleConfig() {...}

This API will give client the option to override the fields related to
throttling in global config.

Internally a Delegate of ImpressionHistoryTracker will be created, and
the glue layer NotificationScheduler delegates this request.

Cleaned up throttled related parameters from schedule_params, and
impression struct and proto.

Some task need to do:
- Check consecutive negative actions instead of dismiss actions only.
- Need to write more detailed unit test to go through whole flow.
- May consider adding other way (positive impression - release throttle)
- Apply this layer to current existing clients including a more
functional web_ui for better test and play purpose.


Bug: 1053659
Change-Id: I3c767bd2be9259e74926a83ef5231ab1940b3972
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2063253
Commit-Queue: Hesen Zhang <hesen@chromium.org>
Reviewed-by: default avatarXing Liu <xingliu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#744409}
parent 695e22ba
...@@ -13,7 +13,7 @@ import "notification_data.proto"; ...@@ -13,7 +13,7 @@ import "notification_data.proto";
// Contains data to determine when a notification should be shown to the user // Contains data to determine when a notification should be shown to the user
// and the user impression towards this notification. Should match Impression in // and the user impression towards this notification. Should match Impression in
// impression_types.h. // impression_types.h.
// Next tag: 9 // Next tag: 8
message Impression { message Impression {
// The type of user feedback from a displayed notification. Should match // The type of user feedback from a displayed notification. Should match
// UserFeedback in notification_scheduler_types.h. // UserFeedback in notification_scheduler_types.h.
...@@ -63,7 +63,4 @@ message Impression { ...@@ -63,7 +63,4 @@ message Impression {
// Custom data associated with a notification. // Custom data associated with a notification.
repeated CustomData custom_data = 7; repeated CustomData custom_data = 7;
// Custom suppresion duration in ms.
optional int64 custom_suppression_duration_ms = 8;
} }
...@@ -13,7 +13,7 @@ import "impression.proto"; ...@@ -13,7 +13,7 @@ import "impression.proto";
import "notification_data.proto"; import "notification_data.proto";
// Defines scheduling and throttling details. // Defines scheduling and throttling details.
// Next tag: 6 // Next tag: 5
message ScheduleParams { message ScheduleParams {
enum Priority { enum Priority {
LOW = 0; LOW = 0;
...@@ -28,9 +28,6 @@ message ScheduleParams { ...@@ -28,9 +28,6 @@ message ScheduleParams {
// The end time of deliver time window for the notification. // The end time of deliver time window for the notification.
optional int64 deliver_time_end = 4; optional int64 deliver_time_end = 4;
// The custom suppression duration in ms.
optional int64 custom_suppression_duration_ms = 5;
} }
// The notification entry that contains all data for a scheduled notification. // The notification entry that contains all data for a scheduled notification.
......
...@@ -47,11 +47,15 @@ ImpressionHistoryTrackerImpl::ImpressionHistoryTrackerImpl( ...@@ -47,11 +47,15 @@ ImpressionHistoryTrackerImpl::ImpressionHistoryTrackerImpl(
config_(config), config_(config),
registered_clients_(std::move(registered_clients)), registered_clients_(std::move(registered_clients)),
initialized_(false), initialized_(false),
clock_(clock) {} clock_(clock),
delegate_(nullptr) {}
ImpressionHistoryTrackerImpl::~ImpressionHistoryTrackerImpl() = default; ImpressionHistoryTrackerImpl::~ImpressionHistoryTrackerImpl() = default;
void ImpressionHistoryTrackerImpl::Init(InitCallback callback) { void ImpressionHistoryTrackerImpl::Init(Delegate* delegate,
InitCallback callback) {
DCHECK(delegate && !delegate_);
delegate_ = delegate;
store_->InitAndLoad( store_->InitAndLoad(
base::BindOnce(&ImpressionHistoryTrackerImpl::OnStoreInitialized, base::BindOnce(&ImpressionHistoryTrackerImpl::OnStoreInitialized,
weak_ptr_factory_.GetWeakPtr(), std::move(callback))); weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
...@@ -61,8 +65,7 @@ void ImpressionHistoryTrackerImpl::AddImpression( ...@@ -61,8 +65,7 @@ void ImpressionHistoryTrackerImpl::AddImpression(
SchedulerClientType type, SchedulerClientType type,
const std::string& guid, const std::string& guid,
const Impression::ImpressionResultMap& impression_mapping, const Impression::ImpressionResultMap& impression_mapping,
const Impression::CustomData& custom_data, const Impression::CustomData& custom_data) {
const base::Optional<base::TimeDelta>& custom_suppression_duration) {
DCHECK(initialized_); DCHECK(initialized_);
auto it = client_states_.find(type); auto it = client_states_.find(type);
if (it == client_states_.end()) if (it == client_states_.end())
...@@ -71,7 +74,6 @@ void ImpressionHistoryTrackerImpl::AddImpression( ...@@ -71,7 +74,6 @@ void ImpressionHistoryTrackerImpl::AddImpression(
Impression impression(type, guid, clock_->Now()); Impression impression(type, guid, clock_->Now());
impression.impression_mapping = impression_mapping; impression.impression_mapping = impression_mapping;
impression.custom_data = custom_data; impression.custom_data = custom_data;
impression.custom_suppression_duration = custom_suppression_duration;
it->second->impressions.emplace_back(std::move(impression)); it->second->impressions.emplace_back(std::move(impression));
impression_map_.emplace(guid, &it->second->impressions.back()); impression_map_.emplace(guid, &it->second->impressions.back());
...@@ -219,10 +221,7 @@ void ImpressionHistoryTrackerImpl::AnalyzeImpressionHistory( ...@@ -219,10 +221,7 @@ void ImpressionHistoryTrackerImpl::AnalyzeImpressionHistory(
dismisses.emplace_back(impression); dismisses.emplace_back(impression);
PruneImpressionByCreateTime( PruneImpressionByCreateTime(
&dismisses, impression->create_time - config_.dismiss_duration); &dismisses, impression->create_time - config_.dismiss_duration);
CheckConsecutiveDismiss(client_state, &dismisses);
// Three consecutive dismisses will result in suppression.
CheckConsecutiveDismiss(client_state, &dismisses,
config_.dismiss_count);
break; break;
case UserFeedback::kClick: case UserFeedback::kClick:
OnClickInternal(impression->guid, false /*update_db*/); OnClickInternal(impression->guid, false /*update_db*/);
...@@ -316,8 +315,13 @@ void ImpressionHistoryTrackerImpl::UpdateThrottling(ClientState* client_state, ...@@ -316,8 +315,13 @@ void ImpressionHistoryTrackerImpl::UpdateThrottling(ClientState* client_state,
void ImpressionHistoryTrackerImpl::CheckConsecutiveDismiss( void ImpressionHistoryTrackerImpl::CheckConsecutiveDismiss(
ClientState* client_state, ClientState* client_state,
base::circular_deque<Impression*>* impressions, base::circular_deque<Impression*>* impressions) {
size_t num_actions) { auto custom_throttle_config =
delegate_->GetThrottleConfig(client_state->type);
size_t num_actions =
custom_throttle_config
? custom_throttle_config->negative_action_count_threshold
: config_.dismiss_count;
if (impressions->size() < num_actions) if (impressions->size() < num_actions)
return; return;
...@@ -371,12 +375,15 @@ void ImpressionHistoryTrackerImpl::ApplyNegativeImpression( ...@@ -371,12 +375,15 @@ void ImpressionHistoryTrackerImpl::ApplyNegativeImpression(
SetNeedsUpdate(client_state->type, true); SetNeedsUpdate(client_state->type, true);
impression->integrated = true; impression->integrated = true;
auto custom_throttle_config =
delegate_->GetThrottleConfig(client_state->type);
auto suppression_duration = custom_throttle_config
? custom_throttle_config->suppression_duration
: config_.suppression_duration;
// Suppress the notification, the user will not see this type of notification // Suppress the notification, the user will not see this type of notification
// for a while. // for a while.
SuppressionInfo supression_info( SuppressionInfo supression_info(clock_->Now(), suppression_duration);
clock_->Now(), impression->custom_suppression_duration.has_value()
? impression->custom_suppression_duration.value()
: config_.suppression_duration);
client_state->suppression_info = std::move(supression_info); client_state->suppression_info = std::move(supression_info);
client_state->current_max_daily_show = 0; client_state->current_max_daily_show = 0;
stats::LogImpressionEvent(stats::ImpressionEvent::kNewSuppression); stats::LogImpressionEvent(stats::ImpressionEvent::kNewSuppression);
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "chrome/browser/notifications/scheduler/internal/impression_types.h" #include "chrome/browser/notifications/scheduler/internal/impression_types.h"
#include "chrome/browser/notifications/scheduler/internal/scheduler_config.h" #include "chrome/browser/notifications/scheduler/internal/scheduler_config.h"
#include "chrome/browser/notifications/scheduler/public/impression_detail.h" #include "chrome/browser/notifications/scheduler/public/impression_detail.h"
#include "chrome/browser/notifications/scheduler/public/throttle_config.h"
#include "chrome/browser/notifications/scheduler/public/user_action_handler.h" #include "chrome/browser/notifications/scheduler/public/user_action_handler.h"
namespace notifications { namespace notifications {
...@@ -32,16 +33,28 @@ class ImpressionHistoryTracker : public UserActionHandler { ...@@ -32,16 +33,28 @@ class ImpressionHistoryTracker : public UserActionHandler {
std::map<SchedulerClientType, std::unique_ptr<ClientState>>; std::map<SchedulerClientType, std::unique_ptr<ClientState>>;
using InitCallback = base::OnceCallback<void(bool)>; using InitCallback = base::OnceCallback<void(bool)>;
class Delegate {
public:
Delegate() = default;
virtual ~Delegate() = default;
// Get ThrottleConfig.
virtual std::unique_ptr<ThrottleConfig> GetThrottleConfig(
SchedulerClientType type) = 0;
private:
DISALLOW_COPY_AND_ASSIGN(Delegate);
};
// Initializes the impression tracker. // Initializes the impression tracker.
virtual void Init(InitCallback callback) = 0; virtual void Init(Delegate* delegate, InitCallback callback) = 0;
// Add a new impression, called after the notification is shown. // Add a new impression, called after the notification is shown.
virtual void AddImpression( virtual void AddImpression(
SchedulerClientType type, SchedulerClientType type,
const std::string& guid, const std::string& guid,
const Impression::ImpressionResultMap& impression_map, const Impression::ImpressionResultMap& impression_map,
const Impression::CustomData& custom_data, const Impression::CustomData& custom_data) = 0;
const base::Optional<base::TimeDelta>& custom_suppression_duration) = 0;
// Analyzes the impression history for all notification clients, and adjusts // Analyzes the impression history for all notification clients, and adjusts
// the |current_max_daily_show|. // the |current_max_daily_show|.
...@@ -82,13 +95,11 @@ class ImpressionHistoryTrackerImpl : public ImpressionHistoryTracker { ...@@ -82,13 +95,11 @@ class ImpressionHistoryTrackerImpl : public ImpressionHistoryTracker {
private: private:
// ImpressionHistoryTracker implementation. // ImpressionHistoryTracker implementation.
void Init(InitCallback callback) override; void Init(Delegate* delegate, InitCallback callback) override;
void AddImpression(SchedulerClientType type, void AddImpression(SchedulerClientType type,
const std::string& guid, const std::string& guid,
const Impression::ImpressionResultMap& impression_mapping, const Impression::ImpressionResultMap& impression_mapping,
const Impression::CustomData& custom_data, const Impression::CustomData& custom_data) override;
const base::Optional<base::TimeDelta>&
custom_suppression_duration) override;
void AnalyzeImpressionHistory() override; void AnalyzeImpressionHistory() override;
void GetClientStates(std::map<SchedulerClientType, const ClientState*>* void GetClientStates(std::map<SchedulerClientType, const ClientState*>*
client_states) const override; client_states) const override;
...@@ -119,8 +130,7 @@ class ImpressionHistoryTrackerImpl : public ImpressionHistoryTracker { ...@@ -119,8 +130,7 @@ class ImpressionHistoryTrackerImpl : public ImpressionHistoryTracker {
// Check consecutive user actions, and generate impression result if no less // Check consecutive user actions, and generate impression result if no less
// than |num_actions| count of user actions. // than |num_actions| count of user actions.
void CheckConsecutiveDismiss(ClientState* client_state, void CheckConsecutiveDismiss(ClientState* client_state,
base::circular_deque<Impression*>* impressions, base::circular_deque<Impression*>* impressions);
size_t num_actions);
// Generates user impression result. // Generates user impression result.
void GenerateImpressionResult(Impression* impression); void GenerateImpressionResult(Impression* impression);
...@@ -183,6 +193,9 @@ class ImpressionHistoryTrackerImpl : public ImpressionHistoryTracker { ...@@ -183,6 +193,9 @@ class ImpressionHistoryTrackerImpl : public ImpressionHistoryTracker {
// The clock to provide the current timestamp. // The clock to provide the current timestamp.
base::Clock* clock_; base::Clock* clock_;
// Delegate object.
Delegate* delegate_;
base::WeakPtrFactory<ImpressionHistoryTrackerImpl> weak_ptr_factory_{this}; base::WeakPtrFactory<ImpressionHistoryTrackerImpl> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(ImpressionHistoryTrackerImpl); DISALLOW_COPY_AND_ASSIGN(ImpressionHistoryTrackerImpl);
}; };
......
...@@ -84,10 +84,21 @@ class MockImpressionStore : public CollectionStore<ClientState> { ...@@ -84,10 +84,21 @@ class MockImpressionStore : public CollectionStore<ClientState> {
DISALLOW_COPY_AND_ASSIGN(MockImpressionStore); DISALLOW_COPY_AND_ASSIGN(MockImpressionStore);
}; };
class MockDelegate : public ImpressionHistoryTracker::Delegate {
public:
MockDelegate() = default;
~MockDelegate() final = default;
MOCK_METHOD1(GetThrottleConfig,
std::unique_ptr<ThrottleConfig>(SchedulerClientType));
private:
DISALLOW_COPY_AND_ASSIGN(MockDelegate);
};
// TODO(xingliu): Add more test cases following the test doc. // TODO(xingliu): Add more test cases following the test doc.
class ImpressionHistoryTrackerTest : public ::testing::Test { class ImpressionHistoryTrackerTest : public ::testing::Test {
public: public:
ImpressionHistoryTrackerTest() : store_(nullptr) {} ImpressionHistoryTrackerTest() : store_(nullptr), delegate_(nullptr) {}
~ImpressionHistoryTrackerTest() override = default; ~ImpressionHistoryTrackerTest() override = default;
void SetUp() override { void SetUp() override {
...@@ -101,7 +112,7 @@ class ImpressionHistoryTrackerTest : public ::testing::Test { ...@@ -101,7 +112,7 @@ class ImpressionHistoryTrackerTest : public ::testing::Test {
void CreateTracker(const TestCase& test_case) { void CreateTracker(const TestCase& test_case) {
auto store = std::make_unique<MockImpressionStore>(); auto store = std::make_unique<MockImpressionStore>();
store_ = store.get(); store_ = store.get();
delegate_ = std::make_unique<MockDelegate>();
impression_trakcer_ = std::make_unique<ImpressionHistoryTrackerImpl>( impression_trakcer_ = std::make_unique<ImpressionHistoryTrackerImpl>(
config_, test_case.registered_clients, std::move(store), &clock_); config_, test_case.registered_clients, std::move(store), &clock_);
} }
...@@ -117,12 +128,13 @@ class ImpressionHistoryTrackerTest : public ::testing::Test { ...@@ -117,12 +128,13 @@ class ImpressionHistoryTrackerTest : public ::testing::Test {
std::move(cb).Run(true, std::move(entries)); std::move(cb).Run(true, std::move(entries));
})); }));
base::RunLoop loop; base::RunLoop loop;
impression_trakcer_->Init(base::BindOnce( impression_trakcer_->Init(
[](base::RepeatingClosure closure, bool success) { delegate_.get(), base::BindOnce(
EXPECT_TRUE(success); [](base::RepeatingClosure closure, bool success) {
std::move(closure).Run(); EXPECT_TRUE(success);
}, std::move(closure).Run();
loop.QuitClosure())); },
loop.QuitClosure()));
loop.Run(); loop.Run();
} }
...@@ -149,6 +161,8 @@ class ImpressionHistoryTrackerTest : public ::testing::Test { ...@@ -149,6 +161,8 @@ class ImpressionHistoryTrackerTest : public ::testing::Test {
const SchedulerConfig& config() const { return config_; } const SchedulerConfig& config() const { return config_; }
MockImpressionStore* store() { return store_; } MockImpressionStore* store() { return store_; }
MockDelegate* delegate() { return delegate_.get(); }
ImpressionHistoryTracker* tracker() { return impression_trakcer_.get(); } ImpressionHistoryTracker* tracker() { return impression_trakcer_.get(); }
test::FakeClock* clock() { return &clock_; } test::FakeClock* clock() { return &clock_; }
...@@ -158,6 +172,7 @@ class ImpressionHistoryTrackerTest : public ::testing::Test { ...@@ -158,6 +172,7 @@ class ImpressionHistoryTrackerTest : public ::testing::Test {
SchedulerConfig config_; SchedulerConfig config_;
std::unique_ptr<ImpressionHistoryTracker> impression_trakcer_; std::unique_ptr<ImpressionHistoryTracker> impression_trakcer_;
MockImpressionStore* store_; MockImpressionStore* store_;
std::unique_ptr<MockDelegate> delegate_;
DISALLOW_COPY_AND_ASSIGN(ImpressionHistoryTrackerTest); DISALLOW_COPY_AND_ASSIGN(ImpressionHistoryTrackerTest);
}; };
...@@ -215,9 +230,9 @@ TEST_F(ImpressionHistoryTrackerTest, AddImpression) { ...@@ -215,9 +230,9 @@ TEST_F(ImpressionHistoryTrackerTest, AddImpression) {
InitTrackerWithData(test_case); InitTrackerWithData(test_case);
// No-op for unregistered client. // No-op for unregistered client.
tracker()->AddImpression( tracker()->AddImpression(SchedulerClientType::kTest2, kGuid2,
SchedulerClientType::kTest2, kGuid2, Impression::ImpressionResultMap(), Impression::ImpressionResultMap(),
Impression::CustomData(), base::nullopt /*custom_suppression_duration*/); Impression::CustomData());
VerifyClientStates(test_case); VerifyClientStates(test_case);
clock()->SetNow(kTimeStr); clock()->SetNow(kTimeStr);
...@@ -225,16 +240,13 @@ TEST_F(ImpressionHistoryTrackerTest, AddImpression) { ...@@ -225,16 +240,13 @@ TEST_F(ImpressionHistoryTrackerTest, AddImpression) {
Impression::ImpressionResultMap impression_mapping = { Impression::ImpressionResultMap impression_mapping = {
{UserFeedback::kDismiss, ImpressionResult::kNegative}}; {UserFeedback::kDismiss, ImpressionResult::kNegative}};
Impression::CustomData custom_data = {{"url", "https://www.example.com"}}; Impression::CustomData custom_data = {{"url", "https://www.example.com"}};
auto custom_suppression_duration = base::TimeDelta::FromDays(56);
EXPECT_CALL(*store(), Update(_, _, _)); EXPECT_CALL(*store(), Update(_, _, _));
tracker()->AddImpression(SchedulerClientType::kTest1, kGuid1, tracker()->AddImpression(SchedulerClientType::kTest1, kGuid1,
impression_mapping, custom_data, impression_mapping, custom_data);
custom_suppression_duration);
Impression expected_impression(SchedulerClientType::kTest1, kGuid1, Impression expected_impression(SchedulerClientType::kTest1, kGuid1,
clock()->Now()); clock()->Now());
expected_impression.impression_mapping = impression_mapping; expected_impression.impression_mapping = impression_mapping;
expected_impression.custom_data = custom_data; expected_impression.custom_data = custom_data;
expected_impression.custom_suppression_duration = custom_suppression_duration;
test_case.expected.back().impressions.emplace_back(expected_impression); test_case.expected.back().impressions.emplace_back(expected_impression);
VerifyClientStates(test_case); VerifyClientStates(test_case);
EXPECT_EQ(*tracker()->GetImpression(kGuid1), expected_impression); EXPECT_EQ(*tracker()->GetImpression(kGuid1), expected_impression);
...@@ -303,7 +315,6 @@ struct UserActionTestParam { ...@@ -303,7 +315,6 @@ struct UserActionTestParam {
base::Optional<ActionButtonType> button_type; base::Optional<ActionButtonType> button_type;
bool integrated = false; bool integrated = false;
bool has_suppression = false; bool has_suppression = false;
base::Optional<base::TimeDelta> custom_suppression_duration;
std::map<UserFeedback, ImpressionResult> impression_mapping; std::map<UserFeedback, ImpressionResult> impression_mapping;
}; };
...@@ -344,7 +355,6 @@ const UserActionTestParam kUserActionTestParams[] = { ...@@ -344,7 +355,6 @@ const UserActionTestParam kUserActionTestParams[] = {
base::nullopt, base::nullopt,
true /*integrated*/, true /*integrated*/,
true /*has_suppression*/, true /*has_suppression*/,
base::nullopt /*custom_suppression_duration*/,
{{UserFeedback::kClick, {{UserFeedback::kClick,
ImpressionResult::kNegative}} /*impression_mapping*/}, ImpressionResult::kNegative}} /*impression_mapping*/},
...@@ -355,10 +365,10 @@ const UserActionTestParam kUserActionTestParams[] = { ...@@ -355,10 +365,10 @@ const UserActionTestParam kUserActionTestParams[] = {
base::nullopt, base::nullopt,
true /*integrated*/, true /*integrated*/,
true /*has_suppression*/, true /*has_suppression*/,
base::TimeDelta::FromDays(2) /*custom_suppression_duration*/,
{{UserFeedback::kClick, {{UserFeedback::kClick,
ImpressionResult::kNegative}} /*impression_mapping*/}}; ImpressionResult::kNegative}} /*impression_mapping*/}};
// TODO(hesen): Add test for custom suppression duration from client.
// User actions like clicks should update the ClientState data accordingly. // User actions like clicks should update the ClientState data accordingly.
TEST_P(ImpressionHistoryTrackerUserActionTest, UserAction) { TEST_P(ImpressionHistoryTrackerUserActionTest, UserAction) {
clock()->SetNow(base::Time::UnixEpoch()); clock()->SetNow(base::Time::UnixEpoch());
...@@ -366,8 +376,6 @@ TEST_P(ImpressionHistoryTrackerUserActionTest, UserAction) { ...@@ -366,8 +376,6 @@ TEST_P(ImpressionHistoryTrackerUserActionTest, UserAction) {
Impression impression = CreateImpression(base::Time::Now(), kGuid1); Impression impression = CreateImpression(base::Time::Now(), kGuid1);
DCHECK(!test_case.input.empty()); DCHECK(!test_case.input.empty());
impression.impression_mapping = GetParam().impression_mapping; impression.impression_mapping = GetParam().impression_mapping;
impression.custom_suppression_duration =
GetParam().custom_suppression_duration;
test_case.input.front().impressions.emplace_back(impression); test_case.input.front().impressions.emplace_back(impression);
impression.impression = GetParam().impression_result; impression.impression = GetParam().impression_result;
...@@ -378,10 +386,7 @@ TEST_P(ImpressionHistoryTrackerUserActionTest, UserAction) { ...@@ -378,10 +386,7 @@ TEST_P(ImpressionHistoryTrackerUserActionTest, UserAction) {
test_case.expected.front().impressions.emplace_back(impression); test_case.expected.front().impressions.emplace_back(impression);
if (GetParam().has_suppression) { if (GetParam().has_suppression) {
test_case.expected.front().suppression_info = test_case.expected.front().suppression_info =
SuppressionInfo(base::Time::UnixEpoch(), SuppressionInfo(base::Time::UnixEpoch(), config().suppression_duration);
GetParam().custom_suppression_duration.has_value()
? GetParam().custom_suppression_duration.value()
: config().suppression_duration);
} }
CreateTracker(test_case); CreateTracker(test_case);
......
...@@ -66,10 +66,6 @@ struct Impression { ...@@ -66,10 +66,6 @@ struct Impression {
// Custom data associated with a notification. Send back to the client when // Custom data associated with a notification. Send back to the client when
// the user interacts with the notification. // the user interacts with the notification.
CustomData custom_data; CustomData custom_data;
// Custom suppresion duration in days. It will override |suppression_duration|
// in config.
base::Optional<base::TimeDelta> custom_suppression_duration;
}; };
// Contains details about supression and recovery after suppression expired. // Contains details about supression and recovery after suppression expired.
......
...@@ -46,7 +46,9 @@ class InitHelper { ...@@ -46,7 +46,9 @@ class InitHelper {
// Initializes subsystems in notification scheduler, |callback| will be // Initializes subsystems in notification scheduler, |callback| will be
// invoked if all initializations finished or anyone of them failed. The // invoked if all initializations finished or anyone of them failed. The
// object should be destroyed along with the |callback|. // object should be destroyed along with the |callback|.
void Init(NotificationSchedulerContext* context, InitCallback callback) { void Init(NotificationSchedulerContext* context,
ImpressionHistoryTracker::Delegate* delegate,
InitCallback callback) {
// TODO(xingliu): Initialize the databases in parallel, we currently // TODO(xingliu): Initialize the databases in parallel, we currently
// initialize one by one to work around a shared db issue. See // initialize one by one to work around a shared db issue. See
// https://crbug.com/978680. // https://crbug.com/978680.
...@@ -54,8 +56,8 @@ class InitHelper { ...@@ -54,8 +56,8 @@ class InitHelper {
callback_ = std::move(callback); callback_ = std::move(callback);
context_->impression_tracker()->Init( context_->impression_tracker()->Init(
base::BindOnce(&InitHelper::OnImpressionTrackerInitialized, delegate, base::BindOnce(&InitHelper::OnImpressionTrackerInitialized,
weak_ptr_factory_.GetWeakPtr())); weak_ptr_factory_.GetWeakPtr()));
} }
private: private:
...@@ -154,8 +156,7 @@ class DisplayHelper { ...@@ -154,8 +156,7 @@ class DisplayHelper {
// Tracks user impression on the notification to be shown. // Tracks user impression on the notification to be shown.
context_->impression_tracker()->AddImpression( context_->impression_tracker()->AddImpression(
entry->type, entry->guid, entry->schedule_params.impression_mapping, entry->type, entry->guid, entry->schedule_params.impression_mapping,
updated_notification_data->custom_data, updated_notification_data->custom_data);
entry->schedule_params.custom_suppression_duration);
stats::LogNotificationShow(*updated_notification_data, entry->type); stats::LogNotificationShow(*updated_notification_data, entry->type);
...@@ -191,9 +192,10 @@ class DisplayHelper { ...@@ -191,9 +192,10 @@ class DisplayHelper {
}; };
// Implementation of NotificationScheduler. // Implementation of NotificationScheduler.
class NotificationSchedulerImpl : public NotificationScheduler { class NotificationSchedulerImpl : public NotificationScheduler,
public ImpressionHistoryTracker::Delegate {
public: public:
NotificationSchedulerImpl( explicit NotificationSchedulerImpl(
std::unique_ptr<NotificationSchedulerContext> context) std::unique_ptr<NotificationSchedulerContext> context)
: context_(std::move(context)) {} : context_(std::move(context)) {}
...@@ -203,7 +205,7 @@ class NotificationSchedulerImpl : public NotificationScheduler { ...@@ -203,7 +205,7 @@ class NotificationSchedulerImpl : public NotificationScheduler {
// NotificationScheduler implementation. // NotificationScheduler implementation.
void Init(InitCallback init_callback) override { void Init(InitCallback init_callback) override {
init_helper_ = std::make_unique<InitHelper>(); init_helper_ = std::make_unique<InitHelper>();
init_helper_->Init(context_.get(), init_helper_->Init(context_.get(), this,
base::BindOnce(&NotificationSchedulerImpl::OnInitialized, base::BindOnce(&NotificationSchedulerImpl::OnInitialized,
weak_ptr_factory_.GetWeakPtr(), weak_ptr_factory_.GetWeakPtr(),
std::move(init_callback))); std::move(init_callback)));
...@@ -363,6 +365,12 @@ class NotificationSchedulerImpl : public NotificationScheduler { ...@@ -363,6 +365,12 @@ class NotificationSchedulerImpl : public NotificationScheduler {
client->OnUserAction(client_action_data); client->OnUserAction(client_action_data);
} }
std::unique_ptr<ThrottleConfig> GetThrottleConfig(
SchedulerClientType type) override {
auto* client = context_->client_registrar()->GetClient(type);
return client ? client->GetThrottleConfig() : nullptr;
}
std::unique_ptr<NotificationSchedulerContext> context_; std::unique_ptr<NotificationSchedulerContext> context_;
std::unique_ptr<InitHelper> init_helper_; std::unique_ptr<InitHelper> init_helper_;
std::unique_ptr<DisplayHelper> display_helper_; std::unique_ptr<DisplayHelper> display_helper_;
......
...@@ -86,8 +86,9 @@ class NotificationSchedulerTest : public testing::Test { ...@@ -86,8 +86,9 @@ class NotificationSchedulerTest : public testing::Test {
protected: protected:
void Init() { void Init() {
EXPECT_CALL(*impression_tracker(), Init(_)) EXPECT_CALL(*impression_tracker(), Init(_, _))
.WillOnce(Invoke([&](ImpressionHistoryTracker::InitCallback callback) { .WillOnce(Invoke([&](ImpressionHistoryTracker::Delegate* delegate,
ImpressionHistoryTracker::InitCallback callback) {
std::move(callback).Run(true); std::move(callback).Run(true);
})); }));
...@@ -159,8 +160,9 @@ TEST_F(NotificationSchedulerTest, InitSuccess) { ...@@ -159,8 +160,9 @@ TEST_F(NotificationSchedulerTest, InitSuccess) {
// Tests the case when impression tracker failed to initialize. // Tests the case when impression tracker failed to initialize.
TEST_F(NotificationSchedulerTest, InitImpressionTrackerFailed) { TEST_F(NotificationSchedulerTest, InitImpressionTrackerFailed) {
EXPECT_CALL(*impression_tracker(), Init(_)) EXPECT_CALL(*impression_tracker(), Init(_, _))
.WillOnce(Invoke([](ImpressionHistoryTracker::InitCallback callback) { .WillOnce(Invoke([](ImpressionHistoryTracker::Delegate* delegate,
ImpressionHistoryTracker::InitCallback callback) {
// Impression tracker failed to load. // Impression tracker failed to load.
std::move(callback).Run(false); std::move(callback).Run(false);
})); }));
...@@ -179,8 +181,9 @@ TEST_F(NotificationSchedulerTest, InitImpressionTrackerFailed) { ...@@ -179,8 +181,9 @@ TEST_F(NotificationSchedulerTest, InitImpressionTrackerFailed) {
// Tests the case when scheduled notification manager failed to initialize. // Tests the case when scheduled notification manager failed to initialize.
TEST_F(NotificationSchedulerTest, InitScheduledNotificationManagerFailed) { TEST_F(NotificationSchedulerTest, InitScheduledNotificationManagerFailed) {
EXPECT_CALL(*impression_tracker(), Init(_)) EXPECT_CALL(*impression_tracker(), Init(_, _))
.WillOnce(Invoke([](ImpressionHistoryTracker::InitCallback callback) { .WillOnce(Invoke([](ImpressionHistoryTracker::Delegate* delegate,
ImpressionHistoryTracker::InitCallback callback) {
std::move(callback).Run(true); std::move(callback).Run(true);
})); }));
...@@ -315,7 +318,7 @@ TEST_F(NotificationSchedulerTest, BackgroundTaskStartShowNotification) { ...@@ -315,7 +318,7 @@ TEST_F(NotificationSchedulerTest, BackgroundTaskStartShowNotification) {
.WillOnce(SetArgPointee<2>(result)); .WillOnce(SetArgPointee<2>(result));
EXPECT_CALL(*task_coordinator(), ScheduleBackgroundTask(_, _)); EXPECT_CALL(*task_coordinator(), ScheduleBackgroundTask(_, _));
EXPECT_CALL(*impression_tracker(), AddImpression(_, _, _, _, _)); EXPECT_CALL(*impression_tracker(), AddImpression(_, _, _, _));
EXPECT_CALL(*notification_manager(), DisplayNotification(_, _)) EXPECT_CALL(*notification_manager(), DisplayNotification(_, _))
.WillOnce( .WillOnce(
Invoke([&](const std::string& guid, Invoke([&](const std::string& guid,
...@@ -345,7 +348,7 @@ TEST_F(NotificationSchedulerTest, BackgroundTaskStartNoEntry) { ...@@ -345,7 +348,7 @@ TEST_F(NotificationSchedulerTest, BackgroundTaskStartNoEntry) {
.WillOnce(SetArgPointee<2>(result)); .WillOnce(SetArgPointee<2>(result));
EXPECT_CALL(*task_coordinator(), ScheduleBackgroundTask(_, _)); EXPECT_CALL(*task_coordinator(), ScheduleBackgroundTask(_, _));
EXPECT_CALL(*impression_tracker(), AddImpression(_, _, _, _, _)).Times(0); EXPECT_CALL(*impression_tracker(), AddImpression(_, _, _, _)).Times(0);
EXPECT_CALL(*display_agent(), ShowNotification(_, _)).Times(0); EXPECT_CALL(*display_agent(), ShowNotification(_, _)).Times(0);
EXPECT_CALL(*client(), BeforeShowNotification(_, _)).Times(0); EXPECT_CALL(*client(), BeforeShowNotification(_, _)).Times(0);
EXPECT_CALL(*notification_manager(), DisplayNotification(_, _)) EXPECT_CALL(*notification_manager(), DisplayNotification(_, _))
...@@ -372,7 +375,7 @@ TEST_F(NotificationSchedulerTest, BackgroundTaskStartNoClient) { ...@@ -372,7 +375,7 @@ TEST_F(NotificationSchedulerTest, BackgroundTaskStartNoClient) {
.WillOnce(SetArgPointee<2>(result)); .WillOnce(SetArgPointee<2>(result));
EXPECT_CALL(*task_coordinator(), ScheduleBackgroundTask(_, _)); EXPECT_CALL(*task_coordinator(), ScheduleBackgroundTask(_, _));
EXPECT_CALL(*impression_tracker(), AddImpression(_, _, _, _, _)).Times(0); EXPECT_CALL(*impression_tracker(), AddImpression(_, _, _, _)).Times(0);
EXPECT_CALL(*display_agent(), ShowNotification(_, _)).Times(0); EXPECT_CALL(*display_agent(), ShowNotification(_, _)).Times(0);
EXPECT_CALL(*client(), BeforeShowNotification(_, _)).Times(0); EXPECT_CALL(*client(), BeforeShowNotification(_, _)).Times(0);
EXPECT_CALL(*notification_manager(), DisplayNotification(_, _)) EXPECT_CALL(*notification_manager(), DisplayNotification(_, _))
...@@ -411,7 +414,7 @@ TEST_F(NotificationSchedulerTest, ClientDropNotification) { ...@@ -411,7 +414,7 @@ TEST_F(NotificationSchedulerTest, ClientDropNotification) {
})); }));
EXPECT_CALL(*task_coordinator(), ScheduleBackgroundTask(_, _)); EXPECT_CALL(*task_coordinator(), ScheduleBackgroundTask(_, _));
EXPECT_CALL(*impression_tracker(), AddImpression(_, _, _, _, _)).Times(0); EXPECT_CALL(*impression_tracker(), AddImpression(_, _, _, _)).Times(0);
EXPECT_CALL(*display_agent(), ShowNotification(_, _)).Times(0); EXPECT_CALL(*display_agent(), ShowNotification(_, _)).Times(0);
OnStartTask(); OnStartTask();
......
...@@ -282,11 +282,6 @@ void ScheduleParamsToProto(ScheduleParams* params, ...@@ -282,11 +282,6 @@ void ScheduleParamsToProto(ScheduleParams* params,
proto->set_deliver_time_end( proto->set_deliver_time_end(
TimeToMilliseconds(params->deliver_time_end.value())); TimeToMilliseconds(params->deliver_time_end.value()));
} }
if (params->custom_suppression_duration.has_value()) {
proto->set_custom_suppression_duration_ms(
TimeDeltaToMilliseconds(params->custom_suppression_duration.value()));
}
} }
// Converts ScheduleParams from proto buffer type. // Converts ScheduleParams from proto buffer type.
...@@ -309,10 +304,6 @@ void ScheduleParamsFromProto(proto::ScheduleParams* proto, ...@@ -309,10 +304,6 @@ void ScheduleParamsFromProto(proto::ScheduleParams* proto,
if (proto->has_deliver_time_end()) { if (proto->has_deliver_time_end()) {
params->deliver_time_end = MillisecondsToTime(proto->deliver_time_end()); params->deliver_time_end = MillisecondsToTime(proto->deliver_time_end());
} }
if (proto->has_custom_suppression_duration_ms()) {
params->custom_suppression_duration =
MillisecondsToTimeDelta(proto->custom_suppression_duration_ms());
}
} }
} // namespace } // namespace
...@@ -352,12 +343,6 @@ void ClientStateToProto(ClientState* client_state, ...@@ -352,12 +343,6 @@ void ClientStateToProto(ClientState* client_state,
data->set_key(pair.first); data->set_key(pair.first);
data->set_value(pair.second); data->set_value(pair.second);
} }
if (impression.custom_suppression_duration.has_value()) {
impression_ptr->set_custom_suppression_duration_ms(
TimeDeltaToMilliseconds(
impression.custom_suppression_duration.value()));
}
} }
if (client_state->suppression_info.has_value()) { if (client_state->suppression_info.has_value()) {
...@@ -403,11 +388,6 @@ void ClientStateFromProto(proto::ClientState* proto, ...@@ -403,11 +388,6 @@ void ClientStateFromProto(proto::ClientState* proto,
impression.custom_data.emplace(pair.key(), pair.value()); impression.custom_data.emplace(pair.key(), pair.value());
} }
if (proto_impression.has_custom_suppression_duration_ms()) {
impression.custom_suppression_duration = MillisecondsToTimeDelta(
proto_impression.custom_suppression_duration_ms());
}
client_state->impressions.emplace_back(std::move(impression)); client_state->impressions.emplace_back(std::move(impression));
} }
......
...@@ -143,10 +143,6 @@ TEST(ProtoConversionTest, ImpressionProtoConversion) { ...@@ -143,10 +143,6 @@ TEST(ProtoConversionTest, ImpressionProtoConversion) {
// Verify custom data. // Verify custom data.
first_impression.custom_data = {{"url", "https://www.example.com"}}; first_impression.custom_data = {{"url", "https://www.example.com"}};
TestClientStateConversion(&client_state); TestClientStateConversion(&client_state);
// Verify custom suppression duration.
first_impression.custom_suppression_duration = base::TimeDelta::FromDays(3);
TestClientStateConversion(&client_state);
} }
// Verifies multiple impressions are serialized correctly. // Verifies multiple impressions are serialized correctly.
...@@ -199,8 +195,6 @@ TEST(ProtoConversionTest, NotificationEntryConversion) { ...@@ -199,8 +195,6 @@ TEST(ProtoConversionTest, NotificationEntryConversion) {
entry.schedule_params.deliver_time_start = entry.create_time; entry.schedule_params.deliver_time_start = entry.create_time;
entry.schedule_params.deliver_time_end = entry.schedule_params.deliver_time_end =
entry.create_time + base::TimeDelta::FromMinutes(10); entry.create_time + base::TimeDelta::FromMinutes(10);
entry.schedule_params.custom_suppression_duration =
base::TimeDelta::FromDays(3);
TestNotificationEntryConversion(&entry); TestNotificationEntryConversion(&entry);
} }
......
...@@ -29,4 +29,8 @@ void WebUIClient::OnUserAction(const UserActionData& action_data) { ...@@ -29,4 +29,8 @@ void WebUIClient::OnUserAction(const UserActionData& action_data) {
NOTIMPLEMENTED(); NOTIMPLEMENTED();
} }
std::unique_ptr<ThrottleConfig> WebUIClient::GetThrottleConfig() {
return nullptr;
}
} // namespace notifications } // namespace notifications
...@@ -27,6 +27,7 @@ class WebUIClient : public NotificationSchedulerClient { ...@@ -27,6 +27,7 @@ class WebUIClient : public NotificationSchedulerClient {
void OnSchedulerInitialized(bool success, void OnSchedulerInitialized(bool success,
std::set<std::string> guids) override; std::set<std::string> guids) override;
void OnUserAction(const UserActionData& action_data) override; void OnUserAction(const UserActionData& action_data) override;
std::unique_ptr<ThrottleConfig> GetThrottleConfig() override;
DISALLOW_COPY_AND_ASSIGN(WebUIClient); DISALLOW_COPY_AND_ASSIGN(WebUIClient);
}; };
......
...@@ -61,6 +61,10 @@ class TestClient : public NotificationSchedulerClient { ...@@ -61,6 +61,10 @@ class TestClient : public NotificationSchedulerClient {
void OnUserAction(const UserActionData& action_data) override {} void OnUserAction(const UserActionData& action_data) override {}
std::unique_ptr<ThrottleConfig> GetThrottleConfig() override {
return nullptr;
}
// Any NotificationData received before showing the notification. // Any NotificationData received before showing the notification.
std::vector<NotificationData> shown_notification_data_; std::vector<NotificationData> shown_notification_data_;
......
...@@ -34,6 +34,8 @@ source_set("public") { ...@@ -34,6 +34,8 @@ source_set("public") {
"schedule_params.h", "schedule_params.h",
"schedule_service_utils.cc", "schedule_service_utils.cc",
"schedule_service_utils.h", "schedule_service_utils.h",
"throttle_config.cc",
"throttle_config.h",
"user_action_handler.h", "user_action_handler.h",
] ]
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "base/optional.h" #include "base/optional.h"
#include "chrome/browser/notifications/scheduler/public/notification_data.h" #include "chrome/browser/notifications/scheduler/public/notification_data.h"
#include "chrome/browser/notifications/scheduler/public/notification_scheduler_types.h" #include "chrome/browser/notifications/scheduler/public/notification_scheduler_types.h"
#include "chrome/browser/notifications/scheduler/public/throttle_config.h"
#include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkBitmap.h"
namespace notifications { namespace notifications {
...@@ -45,6 +46,10 @@ class NotificationSchedulerClient { ...@@ -45,6 +46,10 @@ class NotificationSchedulerClient {
// Called when the user interacts with the notification. // Called when the user interacts with the notification.
virtual void OnUserAction(const UserActionData& action_data) = 0; virtual void OnUserAction(const UserActionData& action_data) = 0;
// Used to pull customized throttle config from client and may override global
// config in the framework. Return |nullptr| if no customization is needed.
virtual std::unique_ptr<ThrottleConfig> GetThrottleConfig() = 0;
private: private:
DISALLOW_COPY_AND_ASSIGN(NotificationSchedulerClient); DISALLOW_COPY_AND_ASSIGN(NotificationSchedulerClient);
}; };
......
...@@ -14,8 +14,7 @@ bool ScheduleParams::operator==(const ScheduleParams& other) const { ...@@ -14,8 +14,7 @@ bool ScheduleParams::operator==(const ScheduleParams& other) const {
return priority == other.priority && return priority == other.priority &&
impression_mapping == other.impression_mapping && impression_mapping == other.impression_mapping &&
deliver_time_start == other.deliver_time_start && deliver_time_start == other.deliver_time_start &&
deliver_time_end == other.deliver_time_end && deliver_time_end == other.deliver_time_end;
custom_suppression_duration == other.custom_suppression_duration;
} }
ScheduleParams::~ScheduleParams() = default; ScheduleParams::~ScheduleParams() = default;
......
...@@ -45,11 +45,6 @@ struct ScheduleParams { ...@@ -45,11 +45,6 @@ struct ScheduleParams {
// The end time of the deliver time window of the notification. Use in pair // The end time of the deliver time window of the notification. Use in pair
// with |deliver_time_start|. // with |deliver_time_start|.
base::Optional<base::Time> deliver_time_end; base::Optional<base::Time> deliver_time_end;
// Support a custom suppression duration(in days) for the notification.
// If client sets this field, it will override |suppression_duration| in
// config.
base::Optional<base::TimeDelta> custom_suppression_duration;
}; };
} // namespace notifications } // namespace notifications
......
// 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 "chrome/browser/notifications/scheduler/public/throttle_config.h"
namespace notifications {
ThrottleConfig::ThrottleConfig() : negative_action_count_threshold(0) {}
ThrottleConfig::ThrottleConfig(const ThrottleConfig& other) = default;
bool ThrottleConfig::operator==(const ThrottleConfig& other) const {
return suppression_duration == other.suppression_duration &&
negative_action_count_threshold ==
other.negative_action_count_threshold;
}
ThrottleConfig::~ThrottleConfig() = default;
} // namespace notifications
// 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 CHROME_BROWSER_NOTIFICATIONS_SCHEDULER_PUBLIC_THROTTLE_CONFIG_H_
#define CHROME_BROWSER_NOTIFICATIONS_SCHEDULER_PUBLIC_THROTTLE_CONFIG_H_
#include "base/time/time.h"
namespace notifications {
// Specifies the throttling related configuration for each client.
struct ThrottleConfig {
ThrottleConfig();
ThrottleConfig(const ThrottleConfig& other);
bool operator==(const ThrottleConfig& other) const;
~ThrottleConfig();
// Support a custom suppression duration(in days) for the notification.
// If client sets this field, it will override |suppression_duration| in
// global config.
base::TimeDelta suppression_duration;
// Maxmium number of consecutive negative actions to trigger negative
// impression event.
// If client sets this field, it will override |dismiss_count| in global
// config.
int negative_action_count_threshold;
};
} // namespace notifications
#endif // CHROME_BROWSER_NOTIFICATIONS_SCHEDULER_PUBLIC_THROTTLE_CONFIG_H_
...@@ -19,13 +19,12 @@ class MockImpressionHistoryTracker : public ImpressionHistoryTracker { ...@@ -19,13 +19,12 @@ class MockImpressionHistoryTracker : public ImpressionHistoryTracker {
MockImpressionHistoryTracker(); MockImpressionHistoryTracker();
~MockImpressionHistoryTracker() override; ~MockImpressionHistoryTracker() override;
MOCK_METHOD1(Init, void(ImpressionHistoryTracker::InitCallback)); MOCK_METHOD2(Init, void(Delegate*, ImpressionHistoryTracker::InitCallback));
MOCK_METHOD5(AddImpression, MOCK_METHOD4(AddImpression,
void(SchedulerClientType, void(SchedulerClientType,
const std::string&, const std::string&,
const Impression::ImpressionResultMap&, const Impression::ImpressionResultMap&,
const Impression::CustomData&, const Impression::CustomData&));
const base::Optional<base::TimeDelta>&));
MOCK_METHOD0(AnalyzeImpressionHistory, void()); MOCK_METHOD0(AnalyzeImpressionHistory, void());
MOCK_CONST_METHOD1(GetClientStates, MOCK_CONST_METHOD1(GetClientStates,
void(std::map<SchedulerClientType, const ClientState*>*)); void(std::map<SchedulerClientType, const ClientState*>*));
......
...@@ -24,6 +24,7 @@ class MockNotificationSchedulerClient : public NotificationSchedulerClient { ...@@ -24,6 +24,7 @@ class MockNotificationSchedulerClient : public NotificationSchedulerClient {
NotificationDataCallback)); NotificationDataCallback));
MOCK_METHOD2(OnSchedulerInitialized, void(bool, std::set<std::string>)); MOCK_METHOD2(OnSchedulerInitialized, void(bool, std::set<std::string>));
MOCK_METHOD1(OnUserAction, void(const UserActionData&)); MOCK_METHOD1(OnUserAction, void(const UserActionData&));
MOCK_METHOD0(GetThrottleConfig, std::unique_ptr<ThrottleConfig>());
}; };
} // namespace test } // namespace test
......
...@@ -110,9 +110,6 @@ std::string DebugString(const NotificationEntry* entry) { ...@@ -110,9 +110,6 @@ std::string DebugString(const NotificationEntry* entry) {
stream << " \n large_icons_id:" stream << " \n large_icons_id:"
<< entry->icons_uuid.at(IconType::kLargeIcon); << entry->icons_uuid.at(IconType::kLargeIcon);
if (entry->schedule_params.custom_suppression_duration.has_value())
stream << " \n custom_suppression_duration:"
<< entry->schedule_params.custom_suppression_duration.value();
return stream.str(); return stream.str();
} }
...@@ -149,10 +146,6 @@ std::string DebugString(const ClientState* client_state) { ...@@ -149,10 +146,6 @@ std::string DebugString(const ClientState* client_state) {
<< " value: " << pair.second; << " value: " << pair.second;
} }
if (impression.custom_suppression_duration.has_value()) {
stream << " \n custom suppression duration "
<< impression.custom_suppression_duration.value();
}
log += stream.str(); log += stream.str();
} }
......
...@@ -33,4 +33,9 @@ void PrefetchNotificationClient::OnUserAction( ...@@ -33,4 +33,9 @@ void PrefetchNotificationClient::OnUserAction(
NOTIMPLEMENTED(); NOTIMPLEMENTED();
} }
std::unique_ptr<notifications::ThrottleConfig>
PrefetchNotificationClient::GetThrottleConfig() {
return nullptr;
}
} // namespace offline_pages } // namespace offline_pages
...@@ -22,6 +22,7 @@ class PrefetchNotificationClient ...@@ -22,6 +22,7 @@ class PrefetchNotificationClient
public: public:
using NotificationData = notifications::NotificationData; using NotificationData = notifications::NotificationData;
using UserActionData = notifications::UserActionData; using UserActionData = notifications::UserActionData;
using ThrottleConfig = notifications::ThrottleConfig;
using GetServiceCallback = using GetServiceCallback =
base::RepeatingCallback<PrefetchNotificationService*()>; base::RepeatingCallback<PrefetchNotificationService*()>;
...@@ -36,6 +37,7 @@ class PrefetchNotificationClient ...@@ -36,6 +37,7 @@ class PrefetchNotificationClient
void OnSchedulerInitialized(bool success, void OnSchedulerInitialized(bool success,
std::set<std::string> guids) override; std::set<std::string> guids) override;
void OnUserAction(const UserActionData& action_data) override; void OnUserAction(const UserActionData& action_data) override;
std::unique_ptr<ThrottleConfig> GetThrottleConfig() override;
GetServiceCallback get_service_callback_; GetServiceCallback get_service_callback_;
......
...@@ -59,4 +59,9 @@ void UpdateNotificationClient::OnUserAction(const UserActionData& action_data) { ...@@ -59,4 +59,9 @@ void UpdateNotificationClient::OnUserAction(const UserActionData& action_data) {
} }
} }
std::unique_ptr<notifications::ThrottleConfig>
UpdateNotificationClient::GetThrottleConfig() {
return nullptr;
}
} // namespace updates } // namespace updates
...@@ -23,6 +23,7 @@ class UpdateNotificationClient ...@@ -23,6 +23,7 @@ class UpdateNotificationClient
public: public:
using NotificationData = notifications::NotificationData; using NotificationData = notifications::NotificationData;
using UserActionData = notifications::UserActionData; using UserActionData = notifications::UserActionData;
using ThrottleConfig = notifications::ThrottleConfig;
using GetServiceCallback = using GetServiceCallback =
base::RepeatingCallback<UpdateNotificationService*()>; base::RepeatingCallback<UpdateNotificationService*()>;
...@@ -37,6 +38,7 @@ class UpdateNotificationClient ...@@ -37,6 +38,7 @@ class UpdateNotificationClient
void OnSchedulerInitialized(bool success, void OnSchedulerInitialized(bool success,
std::set<std::string> guids) override; std::set<std::string> guids) override;
void OnUserAction(const UserActionData& action_data) override; void OnUserAction(const UserActionData& action_data) override;
std::unique_ptr<ThrottleConfig> GetThrottleConfig() override;
GetServiceCallback get_service_callback_; GetServiceCallback get_service_callback_;
......
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