Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / web_resource / promo_resource_service.cc
blob95c9e7672fc872cc5b6289d293497c3e7503296c
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/chrome_notification_types.h"
16 #include "chrome/browser/web_resource/notification_promo.h"
17 #include "chrome/common/chrome_switches.h"
18 #include "chrome/common/pref_names.h"
19 #include "components/user_prefs/pref_registry_syncable.h"
20 #include "content/public/browser/notification_service.h"
21 #include "url/gurl.h"
23 namespace {
25 // Delay on first fetch so we don't interfere with startup.
26 const int kStartResourceFetchDelay = 5000;
28 // Delay between calls to fetch the promo json: 6 hours in production, and 3 min
29 // in debug.
30 const int kCacheUpdateDelay = 6 * 60 * 60 * 1000;
31 const int kTestCacheUpdateDelay = 3 * 60 * 1000;
33 // The promotion type used for Unpack() and ScheduleNotificationOnInit().
34 const NotificationPromo::PromoType kValidPromoTypes[] = {
35 #if defined(OS_ANDROID) || defined(OS_IOS)
36 NotificationPromo::MOBILE_NTP_SYNC_PROMO,
37 #else
38 NotificationPromo::NTP_NOTIFICATION_PROMO,
39 NotificationPromo::NTP_BUBBLE_PROMO,
40 #endif
43 GURL GetPromoResourceURL() {
44 const std::string promo_server_url = CommandLine::ForCurrentProcess()->
45 GetSwitchValueASCII(switches::kPromoServerURL);
46 return promo_server_url.empty() ?
47 NotificationPromo::PromoServerURL() : GURL(promo_server_url);
50 bool IsTest() {
51 return CommandLine::ForCurrentProcess()->HasSwitch(switches::kPromoServerURL);
54 int GetCacheUpdateDelay() {
55 return IsTest() ? kTestCacheUpdateDelay : kCacheUpdateDelay;
58 } // namespace
60 // static
61 void PromoResourceService::RegisterPrefs(PrefRegistrySimple* registry) {
62 registry->RegisterStringPref(prefs::kNtpPromoResourceCacheUpdate, "0");
63 NotificationPromo::RegisterPrefs(registry);
66 // static
67 void PromoResourceService::RegisterProfilePrefs(
68 user_prefs::PrefRegistrySyncable* registry) {
69 // TODO(dbeam): This is registered only for migration; remove in M28
70 // when all prefs have been cleared. http://crbug.com/168887
71 registry->RegisterStringPref(
72 prefs::kNtpPromoResourceCacheUpdate,
73 "0",
74 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
75 NotificationPromo::RegisterProfilePrefs(registry);
78 // static
79 void PromoResourceService::MigrateUserPrefs(PrefService* user_prefs) {
80 user_prefs->ClearPref(prefs::kNtpPromoResourceCacheUpdate);
81 NotificationPromo::MigrateUserPrefs(user_prefs);
84 PromoResourceService::PromoResourceService()
85 : WebResourceService(g_browser_process->local_state(),
86 GetPromoResourceURL(),
87 true, // append locale to URL
88 prefs::kNtpPromoResourceCacheUpdate,
89 kStartResourceFetchDelay,
90 GetCacheUpdateDelay()),
91 weak_ptr_factory_(this) {
92 ScheduleNotificationOnInit();
95 PromoResourceService::~PromoResourceService() {
98 void PromoResourceService::ScheduleNotification(
99 const NotificationPromo& notification_promo) {
100 const double promo_start = notification_promo.StartTimeForGroup();
101 const double promo_end = notification_promo.EndTime();
103 if (promo_start > 0 && promo_end > 0) {
104 const int64 ms_until_start =
105 static_cast<int64>((base::Time::FromDoubleT(
106 promo_start) - base::Time::Now()).InMilliseconds());
107 const int64 ms_until_end =
108 static_cast<int64>((base::Time::FromDoubleT(
109 promo_end) - base::Time::Now()).InMilliseconds());
110 if (ms_until_start > 0) {
111 // Schedule the next notification to happen at the start of promotion.
112 PostNotification(ms_until_start);
113 } else if (ms_until_end > 0) {
114 if (ms_until_start <= 0) {
115 // The promo is active. Notify immediately.
116 PostNotification(0);
118 // Schedule the next notification to happen at the end of promotion.
119 PostNotification(ms_until_end);
120 } else {
121 // The promo (if any) has finished. Notify immediately.
122 PostNotification(0);
124 } else {
125 // The promo (if any) was apparently cancelled. Notify immediately.
126 PostNotification(0);
130 void PromoResourceService::ScheduleNotificationOnInit() {
131 // If the promo start is in the future, set a notification task to
132 // invalidate the NTP cache at the time of the promo start.
133 for (size_t i = 0; i < arraysize(kValidPromoTypes); ++i) {
134 NotificationPromo notification_promo;
135 notification_promo.InitFromPrefs(kValidPromoTypes[i]);
136 ScheduleNotification(notification_promo);
140 void PromoResourceService::PostNotification(int64 delay_ms) {
141 // Note that this could cause re-issuing a notification every time
142 // we receive an update from a server if something goes wrong.
143 // Given that this couldn't happen more frequently than every
144 // kCacheUpdateDelay milliseconds, we should be fine.
145 // TODO(achuith): This crashes if we post delay_ms = 0 to the message loop.
146 // during startup.
147 if (delay_ms > 0) {
148 base::MessageLoop::current()->PostDelayedTask(
149 FROM_HERE,
150 base::Bind(&PromoResourceService::PromoResourceStateChange,
151 weak_ptr_factory_.GetWeakPtr()),
152 base::TimeDelta::FromMilliseconds(delay_ms));
153 } else if (delay_ms == 0) {
154 PromoResourceStateChange();
158 void PromoResourceService::PromoResourceStateChange() {
159 content::NotificationService* service =
160 content::NotificationService::current();
161 service->Notify(chrome::NOTIFICATION_PROMO_RESOURCE_STATE_CHANGED,
162 content::Source<WebResourceService>(this),
163 content::NotificationService::NoDetails());
166 void PromoResourceService::Unpack(const base::DictionaryValue& parsed_json) {
167 for (size_t i = 0; i < arraysize(kValidPromoTypes); ++i) {
168 NotificationPromo notification_promo;
169 notification_promo.InitFromJson(parsed_json, kValidPromoTypes[i]);
170 if (notification_promo.new_notification())
171 ScheduleNotification(notification_promo);