Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(333)

Side by Side Diff: chrome/browser/web_resource/promo_notification.cc

Issue 8045012: NotificationPromo (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: rebase Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2011 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.
4
5 #include "chrome/browser/web_resource/promo_notification.h"
6
7 #include "base/rand_util.h"
8 #include "base/string_number_conversions.h"
9 #include "base/time.h"
10 #include "base/values.h"
11 #include "chrome/browser/prefs/pref_service.h"
12 #include "chrome/browser/web_resource/promo_resource_service.h"
13 #include "chrome/common/pref_names.h"
14
15 // Maximum number of hours for each time slice (4 weeks).
16 static const int kMaxTimeSliceHours = 24 * 7 * 4;
17
18 PromoNotification::PromoNotification(PrefService* prefs, Delegate* delegate)
19 : prefs_(prefs),
20 delegate_(delegate),
21 start_(0.0),
22 end_(0.0),
23 build_(0),
24 time_slice_(0),
25 max_group_(0),
26 max_views_(0),
27 group_(0),
28 views_(0),
29 text_(),
30 closed_(false) {
31 DCHECK(prefs);
32 }
33
34 void PromoNotification::InitFromJson(const DictionaryValue& json) {
35 DictionaryValue* dict;
36 if (json.GetDictionary("topic", &dict)) {
37 ListValue* answers;
38 if (dict->GetList("answers", &answers)) {
39 for (ListValue::const_iterator it = answers->begin();
40 it != answers->end();
41 ++it) {
42 if ((*it)->IsType(Value::TYPE_DICTIONARY))
43 Parse(static_cast<DictionaryValue*>(*it));
44 }
45 }
46 }
47
48 CheckForNewNotification();
49 }
50
51 void PromoNotification::Parse(const DictionaryValue* dict) {
52 std::string name;
53 if (dict->GetString("name", &name)) {
54 if (name == "promo_start") {
55 GetParams(dict);
56 dict->GetString("tooltip", &text_);
57 start_ = GetTimeFromDict(dict);
58 } else if (name == "promo_end") {
59 end_ = GetTimeFromDict(dict);
60 }
61 }
62 }
63
64 bool PromoNotification::OutOfBounds(int var, int min, int max) {
65 return var < min || var > max;
66 }
67
68 void PromoNotification::GetParams(const DictionaryValue* dict) {
69 std::string question;
70 dict->GetString("question", &question);
71
72 size_t index = 0;
73 bool err = false;
74
75 build_ = GetNextQuestionValue(question, &index, &err);
76 time_slice_ = GetNextQuestionValue(question, &index, &err);
77 max_group_ = GetNextQuestionValue(question, &index, &err);
78 max_views_ = GetNextQuestionValue(question, &index, &err);
79
80 if (err ||
81 OutOfBounds(build_, PromoResourceService::NO_BUILD,
82 PromoResourceService::ALL_BUILDS) ||
83 OutOfBounds(time_slice_, 0, kMaxTimeSliceHours) ||
84 OutOfBounds(max_group_, 0, kMaxGroupSize) ||
85 OutOfBounds(max_views_, 0, kMaxViews)) {
86 // If values are not valid, do not show promo notification.
87 NOTREACHED() << "Invalid server data, question=" << question <<
88 ", build=" << build_ <<
89 ", time_slice=" << time_slice_ <<
90 ", max_group=" << max_group_ <<
91 ", max_views=" << max_views_;
92 build_ = PromoResourceService::NO_BUILD;
93 time_slice_ = 0;
94 max_group_ = 0;
95 max_views_ = 0;
96 }
97 }
98
99 void PromoNotification::CheckForNewNotification() {
100 const double old_start = GetTimeFromPrefs(prefs::kNTPPromoStart);
101 const double old_end = GetTimeFromPrefs(prefs::kNTPPromoEnd);
102 const bool has_views = prefs_->HasPrefPath(prefs::kNTPPromoViewsMax);
103
104 // Trigger a new notification if the times have changed, or if
105 // we previously never wrote out a max_views preference.
106 if (old_start != start_ || old_end != end_ || !has_views)
107 OnNewNotification();
108 }
109
110 void PromoNotification::OnNewNotification() {
111 group_ = NewGroup();
112 WritePrefs();
113 if (delegate_)
114 delegate_->OnNewNotification(StartTimeWithOffset(), end_);
115 }
116
117 // static
118 int PromoNotification::NewGroup() {
119 return base::RandInt(0, kMaxGroupSize);
120 }
121
122 // static
123 void PromoNotification::RegisterUserPrefs(PrefService* prefs) {
Dan Beam 2011/09/27 03:27:55 I still think that all of the below would be best
achuithb 2011/09/27 08:03:19 I agree. We should probably have the promo class r
124 prefs->RegisterDoublePref(prefs::kNTPPromoStart,
125 0,
126 PrefService::UNSYNCABLE_PREF);
127 prefs->RegisterDoublePref(prefs::kNTPPromoEnd,
128 0,
129 PrefService::UNSYNCABLE_PREF);
130
131 prefs->RegisterIntegerPref(prefs::kNTPPromoBuild,
132 PromoResourceService::ALL_BUILDS,
133 PrefService::UNSYNCABLE_PREF);
134 prefs->RegisterIntegerPref(prefs::kNTPPromoGroupTimeSlice,
135 0,
136 PrefService::UNSYNCABLE_PREF);
137 prefs->RegisterIntegerPref(prefs::kNTPPromoGroupMax,
138 0,
139 PrefService::UNSYNCABLE_PREF);
140 prefs->RegisterIntegerPref(prefs::kNTPPromoViewsMax,
141 0,
142 PrefService::UNSYNCABLE_PREF);
143
144 prefs->RegisterStringPref(prefs::kNTPPromoLine,
145 std::string(),
146 PrefService::UNSYNCABLE_PREF);
147 prefs->RegisterIntegerPref(prefs::kNTPPromoGroup,
148 0,
149 PrefService::UNSYNCABLE_PREF);
150 prefs->RegisterIntegerPref(prefs::kNTPPromoViews,
151 0,
152 PrefService::UNSYNCABLE_PREF);
153 prefs->RegisterBooleanPref(prefs::kNTPPromoClosed,
154 false,
155 PrefService::UNSYNCABLE_PREF);
156 }
157
158
159 void PromoNotification::WritePrefs() {
160 prefs_->SetDouble(prefs::kNTPPromoStart, start_);
161 prefs_->SetDouble(prefs::kNTPPromoEnd, end_);
162
163 prefs_->SetInteger(prefs::kNTPPromoBuild, build_);
164 prefs_->SetInteger(prefs::kNTPPromoGroupTimeSlice, time_slice_);
165 prefs_->SetInteger(prefs::kNTPPromoGroupMax, max_group_);
166 prefs_->SetInteger(prefs::kNTPPromoViewsMax, max_views_);
167
168 prefs_->SetString(prefs::kNTPPromoLine, text_);
169 prefs_->SetInteger(prefs::kNTPPromoGroup, group_);
170 prefs_->SetInteger(prefs::kNTPPromoViews, views_);
171 prefs_->SetBoolean(prefs::kNTPPromoClosed, closed_);
172 }
173
174 void PromoNotification::InitFromPrefs() {
175 if (prefs_->HasPrefPath(prefs::kNTPPromoStart))
176 start_ = prefs_->GetDouble(prefs::kNTPPromoStart);
177
178 if (prefs_->HasPrefPath(prefs::kNTPPromoEnd))
179 end_ = prefs_->GetDouble(prefs::kNTPPromoEnd);
180
181 if (prefs_->HasPrefPath(prefs::kNTPPromoBuild))
182 build_ = prefs_->GetInteger(prefs::kNTPPromoBuild);
183
184 if (prefs_->HasPrefPath(prefs::kNTPPromoGroupTimeSlice))
185 time_slice_ = prefs_->GetInteger(prefs::kNTPPromoGroupTimeSlice);
186
187 if (prefs_->HasPrefPath(prefs::kNTPPromoGroupMax))
188 max_group_ = prefs_->GetInteger(prefs::kNTPPromoGroupMax);
189
190 if (prefs_->HasPrefPath(prefs::kNTPPromoViewsMax))
191 max_views_ = prefs_->GetInteger(prefs::kNTPPromoViewsMax);
192
193 if (prefs_->HasPrefPath(prefs::kNTPPromoLine))
194 text_ = prefs_->GetString(prefs::kNTPPromoLine);
195
196 if (prefs_->HasPrefPath(prefs::kNTPPromoGroup))
197 group_ = prefs_->GetInteger(prefs::kNTPPromoGroup);
198
199 if (prefs_->HasPrefPath(prefs::kNTPPromoViews))
200 views_ = prefs_->GetInteger(prefs::kNTPPromoViews);
201
202 if (prefs_->HasPrefPath(prefs::kNTPPromoClosed))
203 closed_ = prefs_->GetBoolean(prefs::kNTPPromoClosed);
204 }
205
206 bool PromoNotification::CanShow() const {
207 return !closed_ &&
208 !text_.empty() &&
209 group_ < max_group_ &&
210 views_ < max_views_ &&
211 IsBuildAllowed(build_) &&
212 base::Time::FromDoubleT(StartTimeWithOffset()) < base::Time::Now() &&
213 base::Time::FromDoubleT(end_) > base::Time::Now();
Dan Beam 2011/09/27 03:27:55 Not to be a pedant, but should these be <= / >= an
achuithb 2011/09/27 08:03:19 Nope, I think the comparisons are correct as they
214 }
215
216 bool PromoNotification::IsBuildAllowed(int builds_allowed) const {
217 if (delegate_) // For testing.
218 return delegate_->IsBuildAllowed(builds_allowed);
219 else
220 return PromoResourceService::IsBuildTargeted(
221 PromoResourceService::GetChannel(), builds_allowed);
222 }
223
224 double PromoNotification::StartTimeWithOffset() const {
225 // Adjust start using group and time slice, adjusted from hours to seconds.
226 static const double kSecondsInHour = 60.0 * 60.0;
227 return start_ + group_ * time_slice_ * kSecondsInHour;
228 }
229
Dan Beam 2011/09/27 03:27:55 Should the following 3 static methods be const if
achuithb 2011/09/27 08:03:19 All static functions are const by definition, sinc
230 // static
231 int PromoNotification::GetNextQuestionValue(const std::string& question,
232 size_t* index,
233 bool* err) {
234 if (*err)
235 return 0;
236
237 size_t new_index = question.find(':', *index);
238 // Note that substr correctly handles npos.
239 std::string fragment(question.substr(*index, new_index - *index));
240 *index = new_index + 1;
241
242 int value;
243 *err = !base::StringToInt(fragment, &value);
244 return *err ? 0 : value;
245 }
246
247 // static
248 double PromoNotification::GetTimeFromDict(const DictionaryValue* dict) {
249 std::string str;
250 dict->GetString("inproduct", &str);
251 return GetTimeFromString(str);
252 }
253
Dan Beam 2011/09/27 03:27:55 Why are we getting these as doubles but converting
achuithb 2011/09/27 08:03:19 They are saved as doubles in the preferences file.
254 // static
255 double PromoNotification::GetTimeFromString(const std::string& time_str) {
256 base::Time time;
257 if (time_str.empty() || !base::Time::FromString(time_str.c_str(), &time))
258 return 0.0;
259
260 return time.ToDoubleT();
261 }
262
263 double PromoNotification::GetTimeFromPrefs(const char* pref) const {
264 return prefs_->HasPrefPath(pref) ? prefs_->GetDouble(pref) : 0.0;
265 }
266
267 bool PromoNotification::operator==(const PromoNotification& other) const {
268 return prefs_ == other.prefs_ &&
269 delegate_ == other.delegate_ &&
270 start_ == other.start_ &&
271 end_ == other.end_ &&
272 build_ == other.build_ &&
273 time_slice_ == other.time_slice_ &&
274 max_group_ == other.max_group_ &&
275 max_views_ == other.max_views_ &&
276 group_ == other.group_ &&
277 views_ == other.views_ &&
278 text_ == other.text_ &&
279 closed_ == other.closed_;
280 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698