Roll src/third_party/WebKit eac3800:0237a66 (svn 202606:202607)
[chromium-blink-merge.git] / components / web_resource / promo_resource_service.cc
blob6c23da208f76c771500b5ef550a2bc92122258af
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/web_resource/promo_resource_service.h"
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/location.h"
10 #include "base/prefs/pref_registry_simple.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/thread_task_runner_handle.h"
14 #include "base/threading/thread_restrictions.h"
15 #include "base/values.h"
16 #include "components/pref_registry/pref_registry_syncable.h"
17 #include "components/web_resource/notification_promo.h"
18 #include "components/web_resource/web_resource_pref_names.h"
19 #include "components/web_resource/web_resource_switches.h"
20 #include "url/gurl.h"
22 namespace web_resource {
24 namespace {
26 // Delay on first fetch so we don't interfere with startup.
27 const int kStartResourceFetchDelay = 5000;
29 // Delay between calls to fetch the promo json: 6 hours in production, and 3 min
30 // in debug.
31 const int kCacheUpdateDelay = 6 * 60 * 60 * 1000;
32 const int kTestCacheUpdateDelay = 3 * 60 * 1000;
34 // The promotion type used for Unpack() and ScheduleNotificationOnInit().
35 const NotificationPromo::PromoType kValidPromoTypes[] = {
36 #if defined(OS_ANDROID) || defined(OS_IOS)
37 NotificationPromo::MOBILE_NTP_SYNC_PROMO,
38 #if defined(OS_IOS)
39 NotificationPromo::MOBILE_NTP_WHATS_NEW_PROMO,
40 #endif // defined(OS_IOS)
41 #else
42 NotificationPromo::NTP_NOTIFICATION_PROMO,
43 NotificationPromo::NTP_BUBBLE_PROMO,
44 #endif
47 GURL GetPromoResourceURL(version_info::Channel channel) {
48 const std::string promo_server_url =
49 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
50 switches::kPromoServerURL);
51 return promo_server_url.empty() ? NotificationPromo::PromoServerURL(channel)
52 : GURL(promo_server_url);
55 bool IsTest() {
56 return base::CommandLine::ForCurrentProcess()->HasSwitch(
57 switches::kPromoServerURL);
60 int GetCacheUpdateDelay() {
61 return IsTest() ? kTestCacheUpdateDelay : kCacheUpdateDelay;
64 } // namespace
66 // static
67 void PromoResourceService::RegisterPrefs(PrefRegistrySimple* registry) {
68 registry->RegisterStringPref(prefs::kNtpPromoResourceCacheUpdate, "0");
69 NotificationPromo::RegisterPrefs(registry);
72 // static
73 void PromoResourceService::RegisterProfilePrefs(
74 user_prefs::PrefRegistrySyncable* registry) {
75 // TODO(dbeam): This is registered only for migration; remove in M28
76 // when all prefs have been cleared. http://crbug.com/168887
77 registry->RegisterStringPref(prefs::kNtpPromoResourceCacheUpdate, "0");
78 NotificationPromo::RegisterProfilePrefs(registry);
81 // static
82 void PromoResourceService::MigrateUserPrefs(PrefService* user_prefs) {
83 user_prefs->ClearPref(prefs::kNtpPromoResourceCacheUpdate);
84 NotificationPromo::MigrateUserPrefs(user_prefs);
87 PromoResourceService::PromoResourceService(
88 PrefService* local_state,
89 version_info::Channel channel,
90 const std::string& application_locale,
91 net::URLRequestContextGetter* request_context,
92 const char* disable_network_switch,
93 const ParseJSONCallback& parse_json_callback)
94 : WebResourceService(local_state,
95 GetPromoResourceURL(channel),
96 application_locale, // append locale to URL
97 prefs::kNtpPromoResourceCacheUpdate,
98 kStartResourceFetchDelay,
99 GetCacheUpdateDelay(),
100 request_context,
101 disable_network_switch,
102 parse_json_callback),
103 weak_ptr_factory_(this) {
104 ScheduleNotificationOnInit();
107 PromoResourceService::~PromoResourceService() {}
109 scoped_ptr<PromoResourceService::StateChangedSubscription>
110 PromoResourceService::RegisterStateChangedCallback(
111 const base::Closure& closure) {
112 return callback_list_.Add(closure);
115 void PromoResourceService::ScheduleNotification(
116 const NotificationPromo& notification_promo) {
117 const double promo_start = notification_promo.StartTimeForGroup();
118 const double promo_end = notification_promo.EndTime();
120 if (promo_start > 0 && promo_end > 0) {
121 const int64 ms_until_start = static_cast<int64>(
122 (base::Time::FromDoubleT(promo_start) - base::Time::Now())
123 .InMilliseconds());
124 const int64 ms_until_end = static_cast<int64>(
125 (base::Time::FromDoubleT(promo_end) - base::Time::Now())
126 .InMilliseconds());
127 if (ms_until_start > 0) {
128 // Schedule the next notification to happen at the start of promotion.
129 PostNotification(ms_until_start);
130 } else if (ms_until_end > 0) {
131 if (ms_until_start <= 0) {
132 // The promo is active. Notify immediately.
133 PostNotification(0);
135 // Schedule the next notification to happen at the end of promotion.
136 PostNotification(ms_until_end);
137 } else {
138 // The promo (if any) has finished. Notify immediately.
139 PostNotification(0);
141 } else {
142 // The promo (if any) was apparently cancelled. Notify immediately.
143 PostNotification(0);
147 void PromoResourceService::ScheduleNotificationOnInit() {
148 // If the promo start is in the future, set a notification task to
149 // invalidate the NTP cache at the time of the promo start.
150 for (size_t i = 0; i < arraysize(kValidPromoTypes); ++i) {
151 NotificationPromo notification_promo(prefs_);
152 notification_promo.InitFromPrefs(kValidPromoTypes[i]);
153 ScheduleNotification(notification_promo);
157 void PromoResourceService::PostNotification(int64 delay_ms) {
158 // Note that this could cause re-issuing a notification every time
159 // we receive an update from a server if something goes wrong.
160 // Given that this couldn't happen more frequently than every
161 // kCacheUpdateDelay milliseconds, we should be fine.
162 // TODO(achuith): This crashes if we post delay_ms = 0 to the message loop.
163 // during startup.
164 if (delay_ms > 0) {
165 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
166 FROM_HERE, base::Bind(&PromoResourceService::PromoResourceStateChange,
167 weak_ptr_factory_.GetWeakPtr()),
168 base::TimeDelta::FromMilliseconds(delay_ms));
169 } else if (delay_ms == 0) {
170 PromoResourceStateChange();
174 void PromoResourceService::PromoResourceStateChange() {
175 callback_list_.Notify();
178 void PromoResourceService::Unpack(const base::DictionaryValue& parsed_json) {
179 for (size_t i = 0; i < arraysize(kValidPromoTypes); ++i) {
180 NotificationPromo notification_promo(prefs_);
181 notification_promo.InitFromJson(parsed_json, kValidPromoTypes[i]);
182 if (notification_promo.new_notification())
183 ScheduleNotification(notification_promo);
187 } // namespace web_resource