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

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

Issue 8520009: Only show G+ promo for users logged into G+ (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 1 month 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
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/web_resource/notification_promo.h" 5 #include "chrome/browser/web_resource/notification_promo.h"
6 6
7 #include "base/bind.h"
7 #include "base/rand_util.h" 8 #include "base/rand_util.h"
8 #include "base/string_number_conversions.h" 9 #include "base/string_number_conversions.h"
10 #include "base/string_split.h"
9 #include "base/time.h" 11 #include "base/time.h"
10 #include "base/values.h" 12 #include "base/values.h"
11 #include "chrome/browser/prefs/pref_service.h" 13 #include "chrome/browser/prefs/pref_service.h"
14 #include "chrome/browser/profiles/profile_impl.h"
12 #include "chrome/browser/web_resource/promo_resource_service.h" 15 #include "chrome/browser/web_resource/promo_resource_service.h"
13 #include "chrome/common/pref_names.h" 16 #include "chrome/common/pref_names.h"
17 #include "googleurl/src/gurl.h"
18 #include "net/base/cookie_store.h"
19
14 20
15 namespace { 21 namespace {
16 22
17 // Maximum number of views. 23 // Maximum number of views.
18 static const int kMaxViews = 1000; 24 static const int kMaxViews = 1000;
19 25
20 // Maximum number of hours for each time slice (4 weeks). 26 // Maximum number of hours for each time slice (4 weeks).
21 static const int kMaxTimeSliceHours = 24 * 7 * 4; 27 static const int kMaxTimeSliceHours = 24 * 7 * 4;
22 28
23 bool OutOfBounds(int var, int min, int max) { 29 bool OutOfBounds(int var, int min, int max) {
24 return var < min || var > max; 30 return var < min || var > max;
25 } 31 }
26 32
27 static const char kHeaderProperty[] = "topic"; 33 static const char kHeaderProperty[] = "topic";
28 static const char kArrayProperty[] = "answers"; 34 static const char kArrayProperty[] = "answers";
29 static const char kIdentifierProperty[] = "name"; 35 static const char kIdentifierProperty[] = "name";
30 static const char kStartPropertyValue[] = "promo_start"; 36 static const char kStartPropertyValue[] = "promo_start";
31 static const char kEndPropertyValue[] = "promo_end"; 37 static const char kEndPropertyValue[] = "promo_end";
32 static const char kTextProperty[] = "tooltip"; 38 static const char kTextProperty[] = "tooltip";
33 static const char kTimeProperty[] = "inproduct"; 39 static const char kTimeProperty[] = "inproduct";
34 static const char kParamsProperty[] = "question"; 40 static const char kParamsProperty[] = "question";
35 41
42 static const char kGPlusDomainUrl[] = "http://plus.google.com/";
43 static const char kGPlusDomainSecureCookieId[] = "SID=";
44 static const char kSplitStringToken = ';';
45
36 // Time getters. 46 // Time getters.
37 double GetTimeFromDict(const DictionaryValue* dict) { 47 double GetTimeFromDict(const DictionaryValue* dict) {
38 std::string time_str; 48 std::string time_str;
39 if (!dict->GetString(kTimeProperty, &time_str)) 49 if (!dict->GetString(kTimeProperty, &time_str))
40 return 0.0; 50 return 0.0;
41 51
42 base::Time time; 52 base::Time time;
43 if (time_str.empty() || !base::Time::FromString(time_str.c_str(), &time)) 53 if (time_str.empty() || !base::Time::FromString(time_str.c_str(), &time))
44 return 0.0; 54 return 0.0;
45 55
46 return time.ToDoubleT(); 56 return time.ToDoubleT();
47 } 57 }
48 58
49 double GetTimeFromPrefs(PrefService* prefs, const char* pref) { 59 double GetTimeFromPrefs(PrefService* prefs, const char* pref) {
50 return prefs->HasPrefPath(pref) ? prefs->GetDouble(pref) : 0.0; 60 return prefs->HasPrefPath(pref) ? prefs->GetDouble(pref) : 0.0;
51 } 61 }
52 62
53 } // namespace 63 } // namespace
54 64
55 NotificationPromo::NotificationPromo(PrefService* prefs, Delegate* delegate) 65 NotificationPromo::NotificationPromo(Profile* profile, Delegate* delegate)
56 : prefs_(prefs), 66 : delegate_(delegate),
57 delegate_(delegate), 67 profile_(profile),
achuithb 2011/11/16 20:33:11 Maybe keep this order consistent with the order of
Cait (Slow) 2011/11/16 23:05:24 Done.
58 start_(0.0), 68 start_(0.0),
59 end_(0.0), 69 end_(0.0),
60 build_(0), 70 build_(0),
61 time_slice_(0), 71 time_slice_(0),
62 max_group_(0), 72 max_group_(0),
63 max_views_(0), 73 max_views_(0),
64 group_(0), 74 group_(0),
65 views_(0), 75 views_(0),
66 text_(), 76 text_(),
67 closed_(false) { 77 closed_(false),
68 DCHECK(prefs); 78 gplus_(false),
79 feature_mask_(0) {
80 DCHECK(profile);
81 prefs_ = profile_->GetPrefs();
achuithb 2011/11/16 20:33:11 Could you please put this in the initializer list
Cait (Slow) 2011/11/16 23:05:24 Done.
82 DCHECK(prefs_);
69 } 83 }
70 84
85 NotificationPromo::~NotificationPromo() {}
86
71 void NotificationPromo::InitFromJson(const DictionaryValue& json) { 87 void NotificationPromo::InitFromJson(const DictionaryValue& json) {
72 DictionaryValue* dict; 88 DictionaryValue* dict;
73 if (json.GetDictionary(kHeaderProperty, &dict)) { 89 if (json.GetDictionary(kHeaderProperty, &dict)) {
74 ListValue* answers; 90 ListValue* answers;
75 if (dict->GetList(kArrayProperty, &answers)) { 91 if (dict->GetList(kArrayProperty, &answers)) {
76 for (ListValue::const_iterator it = answers->begin(); 92 for (ListValue::const_iterator it = answers->begin();
77 it != answers->end(); 93 it != answers->end();
78 ++it) { 94 ++it) {
79 if ((*it)->IsType(Value::TYPE_DICTIONARY)) 95 if ((*it)->IsType(Value::TYPE_DICTIONARY))
80 Parse(static_cast<DictionaryValue*>(*it)); 96 Parse(static_cast<DictionaryValue*>(*it));
81 } 97 }
82 } 98 }
83 } 99 }
84 100
85 CheckForNewNotification(); 101 GetCookies(profile_->GetRequestContext());
achuithb 2011/11/16 20:33:11 Could you please call PostTask to BrowserThread::I
Cait (Slow) 2011/11/16 23:05:24 Done.
102 }
103
104 void NotificationPromo::GetCookiesCallback(const std::string& cookies) {
105 std::vector<std::string> cookie_list;
106 bool found_cookie = false;
107 base::SplitString(cookies, kSplitStringToken, &cookie_list);
108 for (std::vector<std::string>::iterator current = cookie_list.begin();
achuithb 2011/11/16 20:33:11 Please use const_iterator instead.
Cait (Slow) 2011/11/16 23:05:24 Done.
109 current != cookie_list.end();
110 ++current) {
111 size_t position = (*current).find(kGPlusDomainSecureCookieId);
112 if (position == 0) {
achuithb 2011/11/16 20:33:11 I think the position var is unnecessary: if ((*cur
Cait (Slow) 2011/11/16 23:05:24 Done.
113 found_cookie = true;
114 break;
115 }
116 }
117 gplus_ = found_cookie;
achuithb 2011/11/16 20:33:11 Please remove this line. It's not safe to do this
Cait (Slow) 2011/11/16 23:05:24 Done.
118 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
119 base::Bind(&NotificationPromo::CheckForNewNotification,
120 base::Unretained(this), found_cookie));
achuithb 2011/11/16 20:33:11 Please do not use base::Unretained here. base::Bi
Cait (Slow) 2011/11/16 23:05:24 Done.
121 }
122
123 void NotificationPromo::GetCookies(net::URLRequestContextGetter* getter) {
124 if (content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)) {
achuithb 2011/11/16 20:33:11 Please replace this if with a DCHECK like: DCHECK(
Cait (Slow) 2011/11/16 23:05:24 Done.
125 getter->GetURLRequestContext()->cookie_store()->
126 GetCookiesWithOptionsAsync(
127 GURL(kGPlusDomainUrl), net::CookieOptions(),
128 base::Bind(&NotificationPromo::GetCookiesCallback,
129 base::Unretained(this)));
achuithb 2011/11/16 20:33:11 Please do not use base::Unretained here; you shoul
Cait (Slow) 2011/11/16 23:05:24 Done.
130 } else {
131 content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
achuithb 2011/11/16 20:33:11 Please PostTask to the IO thread at the calling si
Cait (Slow) 2011/11/16 23:05:24 Done.
132 base::Bind(&NotificationPromo::GetCookies, base::Unretained(this),
133 base::Unretained(getter)));
134 }
86 } 135 }
87 136
88 void NotificationPromo::Parse(const DictionaryValue* dict) { 137 void NotificationPromo::Parse(const DictionaryValue* dict) {
89 std::string key; 138 std::string key;
90 if (dict->GetString(kIdentifierProperty, &key)) { 139 if (dict->GetString(kIdentifierProperty, &key)) {
91 if (key == kStartPropertyValue) { 140 if (key == kStartPropertyValue) {
92 ParseParams(dict); 141 ParseParams(dict);
93 dict->GetString(kTextProperty, &text_); 142 dict->GetString(kTextProperty, &text_);
94 start_ = GetTimeFromDict(dict); 143 start_ = GetTimeFromDict(dict);
95 } else if (key == kEndPropertyValue) { 144 } else if (key == kEndPropertyValue) {
96 end_ = GetTimeFromDict(dict); 145 end_ = GetTimeFromDict(dict);
97 } 146 }
98 } 147 }
99 } 148 }
100 149
101 void NotificationPromo::ParseParams(const DictionaryValue* dict) { 150 void NotificationPromo::ParseParams(const DictionaryValue* dict) {
102 std::string question; 151 std::string question;
103 if (!dict->GetString(kParamsProperty, &question)) 152 if (!dict->GetString(kParamsProperty, &question))
104 return; 153 return;
105 154
106 size_t index = 0; 155 size_t index = 0;
107 bool err = false; 156 bool err = false;
108 157
109 build_ = GetNextQuestionValue(question, &index, &err); 158 build_ = GetNextQuestionValue(question, &index, &err);
110 time_slice_ = GetNextQuestionValue(question, &index, &err); 159 time_slice_ = GetNextQuestionValue(question, &index, &err);
111 max_group_ = GetNextQuestionValue(question, &index, &err); 160 max_group_ = GetNextQuestionValue(question, &index, &err);
112 max_views_ = GetNextQuestionValue(question, &index, &err); 161 max_views_ = GetNextQuestionValue(question, &index, &err);
162 if (index < question.length())
achuithb 2011/11/16 20:33:11 You don't need this. GetNextQuestionValue handles
Cait (Slow) 2011/11/16 23:05:24 Done.
163 feature_mask_ = GetNextQuestionValue(question, &index, &err);
113 164
114 if (err || 165 if (err ||
115 OutOfBounds(build_, PromoResourceService::NO_BUILD, 166 OutOfBounds(build_, PromoResourceService::NO_BUILD,
116 PromoResourceService::ALL_BUILDS) || 167 PromoResourceService::ALL_BUILDS) ||
117 OutOfBounds(time_slice_, 0, kMaxTimeSliceHours) || 168 OutOfBounds(time_slice_, 0, kMaxTimeSliceHours) ||
118 OutOfBounds(max_group_, 0, kMaxGroupSize) || 169 OutOfBounds(max_group_, 0, kMaxGroupSize) ||
119 OutOfBounds(max_views_, 0, kMaxViews)) { 170 OutOfBounds(max_views_, 0, kMaxViews)) {
120 // If values are not valid, do not show promo notification. 171 // If values are not valid, do not show promo notification.
121 DLOG(ERROR) << "Invalid server data, question=" << question << 172 DLOG(ERROR) << "Invalid server data, question=" << question <<
122 ", build=" << build_ << 173 ", build=" << build_ <<
123 ", time_slice=" << time_slice_ << 174 ", time_slice=" << time_slice_ <<
124 ", max_group=" << max_group_ << 175 ", max_group=" << max_group_ <<
125 ", max_views=" << max_views_; 176 ", max_views=" << max_views_;
126 build_ = PromoResourceService::NO_BUILD; 177 build_ = PromoResourceService::NO_BUILD;
127 time_slice_ = 0; 178 time_slice_ = 0;
128 max_group_ = 0; 179 max_group_ = 0;
129 max_views_ = 0; 180 max_views_ = 0;
130 } 181 }
131 } 182 }
132 183
133 void NotificationPromo::CheckForNewNotification() { 184 void NotificationPromo::CheckForNewNotification(bool found_cookie) {
185 gplus_ = found_cookie;
134 const double old_start = GetTimeFromPrefs(prefs_, prefs::kNTPPromoStart); 186 const double old_start = GetTimeFromPrefs(prefs_, prefs::kNTPPromoStart);
135 const double old_end = GetTimeFromPrefs(prefs_, prefs::kNTPPromoEnd); 187 const double old_end = GetTimeFromPrefs(prefs_, prefs::kNTPPromoEnd);
188 const bool old_gplus = prefs_->GetBoolean(prefs::kNTPPromoIsLoggedInToPlus);
136 const bool has_views = prefs_->HasPrefPath(prefs::kNTPPromoViewsMax); 189 const bool has_views = prefs_->HasPrefPath(prefs::kNTPPromoViewsMax);
137 190 const int old_feature_mask = prefs_->GetInteger(prefs::kNTPPromoFeatureMask);
138 // Trigger a new notification if the times have changed, or if 191 // Trigger a new notification if the times have changed, or if
139 // we previously never wrote out a max_views preference. 192 // we previously never wrote out a max_views preference.
140 if (old_start != start_ || old_end != end_ || !has_views) 193 if (old_start != start_ || old_end != end_ || !has_views
194 || old_gplus != gplus_ || old_feature_mask != feature_mask_)
141 OnNewNotification(); 195 OnNewNotification();
142 } 196 }
143 197
144 void NotificationPromo::OnNewNotification() { 198 void NotificationPromo::OnNewNotification() {
145 group_ = NewGroup(); 199 group_ = NewGroup();
146 WritePrefs(); 200 WritePrefs();
147 if (delegate_) 201 if (delegate_)
148 delegate_->OnNewNotification(StartTimeWithOffset(), end_); 202 delegate_->OnNewNotification(StartTimeWithOffset(), end_);
149 } 203 }
150 204
(...skipping 29 matching lines...) Expand all
180 PrefService::UNSYNCABLE_PREF); 234 PrefService::UNSYNCABLE_PREF);
181 prefs->RegisterIntegerPref(prefs::kNTPPromoGroup, 235 prefs->RegisterIntegerPref(prefs::kNTPPromoGroup,
182 0, 236 0,
183 PrefService::UNSYNCABLE_PREF); 237 PrefService::UNSYNCABLE_PREF);
184 prefs->RegisterIntegerPref(prefs::kNTPPromoViews, 238 prefs->RegisterIntegerPref(prefs::kNTPPromoViews,
185 0, 239 0,
186 PrefService::UNSYNCABLE_PREF); 240 PrefService::UNSYNCABLE_PREF);
187 prefs->RegisterBooleanPref(prefs::kNTPPromoClosed, 241 prefs->RegisterBooleanPref(prefs::kNTPPromoClosed,
188 false, 242 false,
189 PrefService::UNSYNCABLE_PREF); 243 PrefService::UNSYNCABLE_PREF);
244 prefs->RegisterBooleanPref(prefs::kNTPPromoIsLoggedInToPlus,
245 false,
246 PrefService::UNSYNCABLE_PREF);
247 prefs->RegisterIntegerPref(prefs::kNTPPromoFeatureMask,
248 0,
249 PrefService::UNSYNCABLE_PREF);
250 }
251
252 // static
253 NotificationPromo* NotificationPromo::Factory(Profile *profile,
254 NotificationPromo::Delegate * delegate) {
255 return new NotificationPromo(profile, delegate);
190 } 256 }
191 257
192 258
193 void NotificationPromo::WritePrefs() { 259 void NotificationPromo::WritePrefs() {
194 prefs_->SetDouble(prefs::kNTPPromoStart, start_); 260 prefs_->SetDouble(prefs::kNTPPromoStart, start_);
195 prefs_->SetDouble(prefs::kNTPPromoEnd, end_); 261 prefs_->SetDouble(prefs::kNTPPromoEnd, end_);
196 262
197 prefs_->SetInteger(prefs::kNTPPromoBuild, build_); 263 prefs_->SetInteger(prefs::kNTPPromoBuild, build_);
198 prefs_->SetInteger(prefs::kNTPPromoGroupTimeSlice, time_slice_); 264 prefs_->SetInteger(prefs::kNTPPromoGroupTimeSlice, time_slice_);
199 prefs_->SetInteger(prefs::kNTPPromoGroupMax, max_group_); 265 prefs_->SetInteger(prefs::kNTPPromoGroupMax, max_group_);
200 prefs_->SetInteger(prefs::kNTPPromoViewsMax, max_views_); 266 prefs_->SetInteger(prefs::kNTPPromoViewsMax, max_views_);
201 267
202 prefs_->SetString(prefs::kNTPPromoLine, text_); 268 prefs_->SetString(prefs::kNTPPromoLine, text_);
203 prefs_->SetInteger(prefs::kNTPPromoGroup, group_); 269 prefs_->SetInteger(prefs::kNTPPromoGroup, group_);
204 prefs_->SetInteger(prefs::kNTPPromoViews, views_); 270 prefs_->SetInteger(prefs::kNTPPromoViews, views_);
205 prefs_->SetBoolean(prefs::kNTPPromoClosed, closed_); 271 prefs_->SetBoolean(prefs::kNTPPromoClosed, closed_);
272 prefs_->SetBoolean(prefs::kNTPPromoIsLoggedInToPlus, gplus_);
273 prefs_->SetInteger(prefs::kNTPPromoFeatureMask, feature_mask_);
206 } 274 }
207 275
208 void NotificationPromo::InitFromPrefs() { 276 void NotificationPromo::InitFromPrefs() {
209 if (prefs_->HasPrefPath(prefs::kNTPPromoStart)) 277 if (prefs_->HasPrefPath(prefs::kNTPPromoStart))
210 start_ = prefs_->GetDouble(prefs::kNTPPromoStart); 278 start_ = prefs_->GetDouble(prefs::kNTPPromoStart);
211 279
212 if (prefs_->HasPrefPath(prefs::kNTPPromoEnd)) 280 if (prefs_->HasPrefPath(prefs::kNTPPromoEnd))
213 end_ = prefs_->GetDouble(prefs::kNTPPromoEnd); 281 end_ = prefs_->GetDouble(prefs::kNTPPromoEnd);
214 282
215 if (prefs_->HasPrefPath(prefs::kNTPPromoBuild)) 283 if (prefs_->HasPrefPath(prefs::kNTPPromoBuild))
(...skipping 12 matching lines...) Expand all
228 text_ = prefs_->GetString(prefs::kNTPPromoLine); 296 text_ = prefs_->GetString(prefs::kNTPPromoLine);
229 297
230 if (prefs_->HasPrefPath(prefs::kNTPPromoGroup)) 298 if (prefs_->HasPrefPath(prefs::kNTPPromoGroup))
231 group_ = prefs_->GetInteger(prefs::kNTPPromoGroup); 299 group_ = prefs_->GetInteger(prefs::kNTPPromoGroup);
232 300
233 if (prefs_->HasPrefPath(prefs::kNTPPromoViews)) 301 if (prefs_->HasPrefPath(prefs::kNTPPromoViews))
234 views_ = prefs_->GetInteger(prefs::kNTPPromoViews); 302 views_ = prefs_->GetInteger(prefs::kNTPPromoViews);
235 303
236 if (prefs_->HasPrefPath(prefs::kNTPPromoClosed)) 304 if (prefs_->HasPrefPath(prefs::kNTPPromoClosed))
237 closed_ = prefs_->GetBoolean(prefs::kNTPPromoClosed); 305 closed_ = prefs_->GetBoolean(prefs::kNTPPromoClosed);
306
307 if (prefs_->HasPrefPath(prefs::kNTPPromoIsLoggedInToPlus))
308 gplus_ = prefs_->GetBoolean(prefs::kNTPPromoIsLoggedInToPlus);
309
310 if (prefs_->HasPrefPath(prefs::kNTPPromoFeatureMask))
311 feature_mask_ = prefs_->GetInteger(prefs::kNTPPromoFeatureMask);
238 } 312 }
239 313
240 bool NotificationPromo::CanShow() const { 314 bool NotificationPromo::CanShow() const {
241 return !closed_ && 315 return !closed_ &&
242 !text_.empty() && 316 !text_.empty() &&
243 group_ < max_group_ && 317 group_ < max_group_ &&
244 views_ < max_views_ && 318 views_ < max_views_ &&
245 IsBuildAllowed(build_) && 319 IsBuildAllowed(build_) &&
246 base::Time::FromDoubleT(StartTimeWithOffset()) < base::Time::Now() && 320 base::Time::FromDoubleT(StartTimeWithOffset()) < base::Time::Now() &&
247 base::Time::FromDoubleT(end_) > base::Time::Now(); 321 base::Time::FromDoubleT(end_) > base::Time::Now() &&
322 ((feature_mask_ & !gplus_) == 0));
248 } 323 }
249 324
250 void NotificationPromo::HandleClosed() { 325 void NotificationPromo::HandleClosed() {
251 prefs_->SetBoolean(prefs::kNTPPromoClosed, true); 326 prefs_->SetBoolean(prefs::kNTPPromoClosed, true);
252 } 327 }
253 328
254 bool NotificationPromo::HandleViewed() { 329 bool NotificationPromo::HandleViewed() {
255 if (prefs_->HasPrefPath(prefs::kNTPPromoViewsMax)) 330 if (prefs_->HasPrefPath(prefs::kNTPPromoViewsMax))
256 max_views_ = prefs_->GetInteger(prefs::kNTPPromoViewsMax); 331 max_views_ = prefs_->GetInteger(prefs::kNTPPromoViewsMax);
257 332
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 delegate_ == other.delegate_ && 373 delegate_ == other.delegate_ &&
299 start_ == other.start_ && 374 start_ == other.start_ &&
300 end_ == other.end_ && 375 end_ == other.end_ &&
301 build_ == other.build_ && 376 build_ == other.build_ &&
302 time_slice_ == other.time_slice_ && 377 time_slice_ == other.time_slice_ &&
303 max_group_ == other.max_group_ && 378 max_group_ == other.max_group_ &&
304 max_views_ == other.max_views_ && 379 max_views_ == other.max_views_ &&
305 group_ == other.group_ && 380 group_ == other.group_ &&
306 views_ == other.views_ && 381 views_ == other.views_ &&
307 text_ == other.text_ && 382 text_ == other.text_ &&
308 closed_ == other.closed_; 383 closed_ == other.closed_ &&
384 gplus_ == other.gplus_;
achuithb 2011/11/16 20:33:11 feature_mask_ is needed here too.
Cait (Slow) 2011/11/16 23:05:24 Done.
309 } 385 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698