Add ENABLE_MEDIA_ROUTER define to builds other than Android and iOS.
[chromium-blink-merge.git] / chrome / browser / web_resource / promo_resource_service.cc
blob140dff07407d912ff98c9c8ca0bd68816d2931b3
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 "chrome/browser/web_resource/promo_resource_service.h"
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/prefs/pref_registry_simple.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/threading/thread_restrictions.h"
13 #include "base/values.h"
14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/web_resource/notification_promo.h"
16 #include "components/pref_registry/pref_registry_syncable.h"
17 #include "components/web_resource/web_resource_pref_names.h"
18 #include "components/web_resource/web_resource_switches.h"
19 #include "url/gurl.h"
21 namespace {
23 // Delay on first fetch so we don't interfere with startup.
24 const int kStartResourceFetchDelay = 5000;
26 // Delay between calls to fetch the promo json: 6 hours in production, and 3 min
27 // in debug.
28 const int kCacheUpdateDelay = 6 * 60 * 60 * 1000;
29 const int kTestCacheUpdateDelay = 3 * 60 * 1000;
31 // The promotion type used for Unpack() and ScheduleNotificationOnInit().
32 const NotificationPromo::PromoType kValidPromoTypes[] = {
33 #if defined(OS_ANDROID) || defined(OS_IOS)
34 NotificationPromo::MOBILE_NTP_SYNC_PROMO,
35 #if defined(OS_IOS)
36 NotificationPromo::MOBILE_NTP_WHATS_NEW_PROMO,
37 #endif // defined(OS_IOS)
38 #else
39 NotificationPromo::NTP_NOTIFICATION_PROMO,
40 NotificationPromo::NTP_BUBBLE_PROMO,
41 #endif
44 GURL GetPromoResourceURL() {
45 const std::string promo_server_url =
46 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
47 switches::kPromoServerURL);
48 return promo_server_url.empty() ?
49 NotificationPromo::PromoServerURL() : GURL(promo_server_url);
52 bool IsTest() {
53 return base::CommandLine::ForCurrentProcess()->HasSwitch(
54 switches::kPromoServerURL);
57 int GetCacheUpdateDelay() {
58 return IsTest() ? kTestCacheUpdateDelay : kCacheUpdateDelay;
61 } // namespace
63 // static
64 void PromoResourceService::RegisterPrefs(PrefRegistrySimple* registry) {
65 registry->RegisterStringPref(prefs::kNtpPromoResourceCacheUpdate, "0");
66 NotificationPromo::RegisterPrefs(registry);
69 // static
70 void PromoResourceService::RegisterProfilePrefs(
71 user_prefs::PrefRegistrySyncable* registry) {
72 // TODO(dbeam): This is registered only for migration; remove in M28
73 // when all prefs have been cleared. http://crbug.com/168887
74 registry->RegisterStringPref(
75 prefs::kNtpPromoResourceCacheUpdate,
76 "0",
77 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
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 : ChromeWebResourceService(g_browser_process->local_state(),
89 GetPromoResourceURL(),
90 true, // append locale to URL
91 prefs::kNtpPromoResourceCacheUpdate,
92 kStartResourceFetchDelay,
93 GetCacheUpdateDelay()),
94 weak_ptr_factory_(this) {
95 ScheduleNotificationOnInit();
98 PromoResourceService::~PromoResourceService() {
101 scoped_ptr<PromoResourceService::StateChangedSubscription>
102 PromoResourceService::RegisterStateChangedCallback(
103 const base::Closure& closure) {
104 return callback_list_.Add(closure);
107 void PromoResourceService::ScheduleNotification(
108 const NotificationPromo& notification_promo) {
109 const double promo_start = notification_promo.StartTimeForGroup();
110 const double promo_end = notification_promo.EndTime();
112 if (promo_start > 0 && promo_end > 0) {
113 const int64 ms_until_start =
114 static_cast<int64>((base::Time::FromDoubleT(
115 promo_start) - base::Time::Now()).InMilliseconds());
116 const int64 ms_until_end =
117 static_cast<int64>((base::Time::FromDoubleT(
118 promo_end) - base::Time::Now()).InMilliseconds());
119 if (ms_until_start > 0) {
120 // Schedule the next notification to happen at the start of promotion.
121 PostNotification(ms_until_start);
122 } else if (ms_until_end > 0) {
123 if (ms_until_start <= 0) {
124 // The promo is active. Notify immediately.
125 PostNotification(0);
127 // Schedule the next notification to happen at the end of promotion.
128 PostNotification(ms_until_end);
129 } else {
130 // The promo (if any) has finished. Notify immediately.
131 PostNotification(0);
133 } else {
134 // The promo (if any) was apparently cancelled. Notify immediately.
135 PostNotification(0);
139 void PromoResourceService::ScheduleNotificationOnInit() {
140 // If the promo start is in the future, set a notification task to
141 // invalidate the NTP cache at the time of the promo start.
142 for (size_t i = 0; i < arraysize(kValidPromoTypes); ++i) {
143 NotificationPromo notification_promo;
144 notification_promo.InitFromPrefs(kValidPromoTypes[i]);
145 ScheduleNotification(notification_promo);
149 void PromoResourceService::PostNotification(int64 delay_ms) {
150 // Note that this could cause re-issuing a notification every time
151 // we receive an update from a server if something goes wrong.
152 // Given that this couldn't happen more frequently than every
153 // kCacheUpdateDelay milliseconds, we should be fine.
154 // TODO(achuith): This crashes if we post delay_ms = 0 to the message loop.
155 // during startup.
156 if (delay_ms > 0) {
157 base::MessageLoop::current()->PostDelayedTask(
158 FROM_HERE,
159 base::Bind(&PromoResourceService::PromoResourceStateChange,
160 weak_ptr_factory_.GetWeakPtr()),
161 base::TimeDelta::FromMilliseconds(delay_ms));
162 } else if (delay_ms == 0) {
163 PromoResourceStateChange();
167 void PromoResourceService::PromoResourceStateChange() {
168 callback_list_.Notify();
171 void PromoResourceService::Unpack(const base::DictionaryValue& parsed_json) {
172 for (size_t i = 0; i < arraysize(kValidPromoTypes); ++i) {
173 NotificationPromo notification_promo;
174 notification_promo.InitFromJson(parsed_json, kValidPromoTypes[i]);
175 if (notification_promo.new_notification())
176 ScheduleNotification(notification_promo);