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

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

Issue 8045012: NotificationPromo (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: fix spacing nit 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
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 "base/json/json_reader.h" 5 #include "base/json/json_reader.h"
6 #include "base/time.h" 6 #include "base/time.h"
7 #include "base/utf_string_conversions.h" 7 #include "base/utf_string_conversions.h"
8 #include "base/values.h" 8 #include "base/values.h"
9 #include "chrome/browser/browser_process.h" 9 #include "chrome/browser/browser_process.h"
10 #include "chrome/browser/extensions/apps_promo.h" 10 #include "chrome/browser/extensions/apps_promo.h"
11 #include "chrome/browser/prefs/browser_prefs.h" 11 #include "chrome/browser/prefs/browser_prefs.h"
12 #include "chrome/browser/prefs/pref_service.h" 12 #include "chrome/browser/prefs/pref_service.h"
13 #include "chrome/browser/web_resource/promo_resource_service.h" 13 #include "chrome/browser/web_resource/promo_resource_service.h"
14 #include "chrome/browser/web_resource/promo_notification.h"
Miranda Callahan 2011/09/27 09:18:40 whoops, swap for alphabetical order.
achuithb 2011/09/28 01:40:14 Done.
14 #include "chrome/common/pref_names.h" 15 #include "chrome/common/pref_names.h"
15 #include "chrome/test/base/testing_browser_process.h" 16 #include "chrome/test/base/testing_browser_process.h"
16 #include "chrome/test/base/testing_pref_service.h" 17 #include "chrome/test/base/testing_pref_service.h"
17 #include "chrome/test/base/testing_profile.h" 18 #include "chrome/test/base/testing_profile.h"
18 #include "content/test/test_url_fetcher_factory.h" 19 #include "content/test/test_url_fetcher_factory.h"
19 #include "testing/gtest/include/gtest/gtest.h" 20 #include "testing/gtest/include/gtest/gtest.h"
20 21
21 class PromoResourceServiceTest : public testing::Test { 22 class PromoResourceServiceTest : public testing::Test {
22 public: 23 public:
23 PromoResourceServiceTest() 24 PromoResourceServiceTest()
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 base::JSONReader::Read(json, false))); 105 base::JSONReader::Read(json, false)));
105 106
106 // Check that prefs are set correctly. 107 // Check that prefs are set correctly.
107 web_resource_service_->UnpackLogoSignal(*(test_json.get())); 108 web_resource_service_->UnpackLogoSignal(*(test_json.get()));
108 logo_start = prefs->GetDouble(prefs::kNTPCustomLogoStart); 109 logo_start = prefs->GetDouble(prefs::kNTPCustomLogoStart);
109 EXPECT_EQ(logo_start, 0); // date value reset to 0; 110 EXPECT_EQ(logo_start, 0); // date value reset to 0;
110 logo_end = prefs->GetDouble(prefs::kNTPCustomLogoEnd); 111 logo_end = prefs->GetDouble(prefs::kNTPCustomLogoEnd);
111 EXPECT_EQ(logo_end, 0); // date value reset to 0; 112 EXPECT_EQ(logo_end, 0); // date value reset to 0;
112 } 113 }
113 114
114 TEST_F(PromoResourceServiceTest, UnpackNotificationSignal) { 115 class PromoNotificationTestDelegate : public PromoNotification::Delegate {
116 public:
117 explicit PromoNotificationTestDelegate(PrefService* prefs)
118 : prefs_(prefs),
119 promo_notification_(NULL),
120 received_notification_(false),
121 build_targeted_(true),
122 start_(0.0),
123 end_(0.0),
124 build_(PromoResourceService::ALL_BUILDS),
125 time_slice_(0),
126 max_group_(0),
127 max_views_(0),
128 text_(),
129 closed_(false) {
130 }
131
132 void Init(PromoNotification* promo_notification,
133 const std::string& json,
134 double start, double end,
135 int build, int time_slice, int max_group, int max_views,
136 const std::string& text, bool closed) {
137 promo_notification_ = promo_notification;
138
139 test_json_.reset(static_cast<DictionaryValue*>(
140 base::JSONReader::Read(json, false)));
141
142 start_ = start;
143 end_ = end;
144
145 build_ = build;
146 time_slice_ = time_slice;
147 max_group_ = max_group;
148 max_views_ = max_views;
149
150 text_ = text;
151 closed_ = closed;
152
153 received_notification_ = false;
154 }
155
156 // PromoNotification::Delegate implementation.
157 virtual void OnNewNotification(double start, double end) {
158 EXPECT_EQ(CalcStart(), start);
159 EXPECT_EQ(promo_notification_->StartTimeWithOffset(), start);
160 EXPECT_EQ(promo_notification_->end_, end);
161 received_notification_ = true;
162 }
163
164 virtual bool IsBuildAllowed(int builds_targeted) const {
165 EXPECT_EQ(builds_targeted, build_);
166 return build_targeted_;
167 }
168
169 const base::DictionaryValue& TestJson() const {
170 return *test_json_;
171 }
172
173 double CalcStart() const {
174 return start_ + promo_notification_->group_ * time_slice_ * 60.0 * 60.0;
175 }
176
177 void InitPromoFromJson(bool should_receive_notification) {
178 received_notification_ = false;
179 promo_notification_->InitFromJson(TestJson());
180 EXPECT_TRUE(received_notification_ == should_receive_notification);
181
182 // Test the fields.
183 TestNotification();
184 TestPrefs();
185 }
186
187 void TestNotification() {
188 // Check values.
189 EXPECT_EQ(promo_notification_->start_, start_);
190 EXPECT_EQ(promo_notification_->end_, end_);
191 EXPECT_EQ(promo_notification_->build_, build_);
192 EXPECT_EQ(promo_notification_->time_slice_, time_slice_);
193 EXPECT_EQ(promo_notification_->max_group_, max_group_);
194 EXPECT_EQ(promo_notification_->max_views_, max_views_);
195 EXPECT_EQ(promo_notification_->text_, text_);
196 EXPECT_EQ(promo_notification_->closed_, closed_);
197
198 // Check group within bounds.
199 EXPECT_GE(promo_notification_->group_, 0);
200 EXPECT_LT(promo_notification_->group_, 100);
201
202 // Views should be 0 for now.
203 EXPECT_EQ(promo_notification_->views_, 0);
204
205 // Check calculated time.
206 EXPECT_EQ(promo_notification_->StartTimeWithOffset(), CalcStart());
207 }
208
209 void TestPrefs() {
210 EXPECT_EQ(prefs_->GetDouble(prefs::kNTPPromoStart), start_);
211 EXPECT_EQ(prefs_->GetDouble(prefs::kNTPPromoEnd), end_);
212
213 EXPECT_EQ(prefs_->GetInteger(prefs::kNTPPromoBuild), build_);
214 EXPECT_EQ(prefs_->GetInteger(prefs::kNTPPromoGroupTimeSlice), time_slice_);
215 EXPECT_EQ(prefs_->GetInteger(prefs::kNTPPromoGroupMax), max_group_);
216 EXPECT_EQ(prefs_->GetInteger(prefs::kNTPPromoViewsMax), max_views_);
217
218 EXPECT_EQ(prefs_->GetInteger(prefs::kNTPPromoGroup),
219 promo_notification_ ? promo_notification_->group_: 0);
220 EXPECT_EQ(prefs_->GetInteger(prefs::kNTPPromoViews), 0);
221 EXPECT_EQ(prefs_->GetString(prefs::kNTPPromoLine), text_);
222 EXPECT_EQ(prefs_->GetBoolean(prefs::kNTPPromoClosed), closed_);
223 }
224
225 // Create a new PromoNotification from prefs and compare to current
226 // notification.
227 void TestInitFromPrefs() {
228 PromoNotification prefs_promo_notification(prefs_, this);
229 prefs_promo_notification.InitFromPrefs();
230 const bool is_equal = *promo_notification_ == prefs_promo_notification;
231 EXPECT_TRUE(is_equal);
232 }
233
234 void TestGroup() {
235 // Test out of range groups.
236 for (int i = max_group_; i <= PromoNotification::kMaxGroupSize; ++i) {
237 promo_notification_->group_ = i;
238 EXPECT_FALSE(promo_notification_->CanShow());
239 }
240
241 // Test in-range groups.
242 for (int i = 0; i < max_group_; ++i) {
243 promo_notification_->group_ = i;
244 EXPECT_TRUE(promo_notification_->CanShow());
245 }
246 }
247
248 void TestViews() {
249 // Test out of range views.
250 for (int i = max_views_; i < PromoNotification::kMaxViews; ++i) {
251 promo_notification_->views_ = i;
252 EXPECT_FALSE(promo_notification_->CanShow());
253 }
254
255 // Test in range views.
256 for (int i = 0; i < max_views_; ++i) {
257 promo_notification_->views_ = i;
258 EXPECT_TRUE(promo_notification_->CanShow());
259 }
260 }
261
262 void TestBuild() {
263 build_targeted_ = false;
264 EXPECT_FALSE(promo_notification_->CanShow());
265
266 build_targeted_ = true;
267 EXPECT_TRUE(promo_notification_->CanShow());
268 }
269
270 void TestClosed() {
271 promo_notification_->closed_ = true;
272 EXPECT_FALSE(promo_notification_->CanShow());
273
274 promo_notification_->closed_ = false;
275 EXPECT_TRUE(promo_notification_->CanShow());
276 }
277
278 void TestText() {
279 promo_notification_->text_.clear();
280 EXPECT_FALSE(promo_notification_->CanShow());
281
282 promo_notification_->text_ = text_;
283 EXPECT_TRUE(promo_notification_->CanShow());
284 }
285
286 void TestTime() {
287 const double now = base::Time::Now().ToDoubleT();
288 const double qhour = 15 * 60;
289
290 promo_notification_->group_ = 0; // For simplicity.
291
292 promo_notification_->start_ = now - qhour;
293 promo_notification_->end_ = now + qhour;
294 EXPECT_TRUE(promo_notification_->CanShow());
295
296 // Start time has not arrived.
297 promo_notification_->start_ = now + qhour;
298 promo_notification_->end_ = now + qhour;
299 EXPECT_FALSE(promo_notification_->CanShow());
300
301 // End time has past.
302 promo_notification_->start_ = now - qhour;
303 promo_notification_->end_ = now - qhour;
304 EXPECT_FALSE(promo_notification_->CanShow());
305
306 promo_notification_->start_ = start_;
307 promo_notification_->end_ = end_;
308 EXPECT_TRUE(promo_notification_->CanShow());
309 }
310
311 private:
312 PrefService* prefs_;
313 PromoNotification* promo_notification_;
314 bool received_notification_;
315 bool build_targeted_;
316 scoped_ptr<DictionaryValue> test_json_;
317
318 double start_;
319 double end_;
320
321 int build_;
322 int time_slice_;
323 int max_group_;
324 int max_views_;
325
326 std::string text_;
327 bool closed_;
328 };
329
330 TEST_F(PromoResourceServiceTest, PromoNotificationTest) {
331 // Check that prefs are set correctly.
332 PrefService* prefs = profile_.GetPrefs();
333 ASSERT_TRUE(prefs != NULL);
334
335 PromoNotificationTestDelegate delegate(prefs);
336 PromoNotification promo_notification(prefs, &delegate);
337
338 // Make sure prefs are unset.
339 delegate.TestPrefs();
340
115 // Set up start and end dates and promo line in a Dictionary as if parsed 341 // Set up start and end dates and promo line in a Dictionary as if parsed
116 // from the service. 342 // from the service.
117 std::string json = "{ " 343 delegate.Init(&promo_notification,
118 " \"topic\": {" 344 "{ "
119 " \"answers\": [" 345 " \"topic\": {"
120 " {" 346 " \"answers\": ["
121 " \"name\": \"promo_start\"," 347 " {"
122 " \"question\": \"3:2:5\"," 348 " \"name\": \"promo_start\","
123 " \"tooltip\": \"Eat more pie!\"," 349 " \"question\": \"3:2:5:10\","
124 " \"inproduct\": \"31/01/10 01:00 GMT\"" 350 " \"tooltip\": \"Eat more pie!\","
125 " }," 351 " \"inproduct\": \"31/01/10 01:00 GMT\""
126 " {" 352 " },"
127 " \"name\": \"promo_end\"," 353 " {"
128 " \"inproduct\": \"31/01/12 01:00 GMT\"" 354 " \"name\": \"promo_end\","
129 " }" 355 " \"inproduct\": \"31/01/12 01:00 GMT\""
130 " ]" 356 " }"
131 " }" 357 " ]"
132 "}"; 358 " }"
133 scoped_ptr<DictionaryValue> test_json(static_cast<DictionaryValue*>( 359 "}",
134 base::JSONReader::Read(json, false))); 360 1264899600, // unix epoch for Jan 31 2010 0100 GMT.
135 361 1327971600, // unix epoch for Jan 31 2012 0100 GMT.
362 3, 2, 5, 10,
363 "Eat more pie!", false);
364
365 delegate.InitPromoFromJson(true);
366
367 // Second time should not trigger a notification.
368 delegate.InitPromoFromJson(false);
369
370 delegate.TestInitFromPrefs();
371
372 // Test various conditions of CanShow.
373 // TestGroup Has the side effect of setting us to a passing group.
374 delegate.TestGroup();
375 delegate.TestViews();
376 delegate.TestBuild();
377 delegate.TestClosed();
378 delegate.TestText();
379 delegate.TestTime();
380 }
381
382 TEST_F(PromoResourceServiceTest, PromoNotificationTestFail) {
136 // Check that prefs are set correctly. 383 // Check that prefs are set correctly.
137 web_resource_service_->UnpackNotificationSignal(*(test_json.get()));
138 PrefService* prefs = profile_.GetPrefs(); 384 PrefService* prefs = profile_.GetPrefs();
139 ASSERT_TRUE(prefs != NULL); 385 ASSERT_TRUE(prefs != NULL);
140 386
141 std::string promo_line = prefs->GetString(prefs::kNTPPromoLine); 387 PromoNotificationTestDelegate delegate(prefs);
142 EXPECT_EQ(promo_line, "Eat more pie!"); 388 PromoNotification promo_notification(prefs, &delegate);
143 389
144 int promo_group = prefs->GetInteger(prefs::kNTPPromoGroup); 390 // Set up start and end dates and promo line in a Dictionary as if parsed
145 EXPECT_GE(promo_group, 0); 391 // from the service.
146 EXPECT_LT(promo_group, 100); 392 delegate.Init(&promo_notification,
147 393 "{ "
148 int promo_build_type = prefs->GetInteger(prefs::kNTPPromoBuild); 394 " \"topic\": {"
149 EXPECT_EQ(promo_build_type & PromoResourceService::DEV_BUILD, 395 " \"answers\": ["
150 PromoResourceService::DEV_BUILD); 396 " {"
151 EXPECT_EQ(promo_build_type & PromoResourceService::BETA_BUILD, 397 " \"name\": \"promo_start\","
152 PromoResourceService::BETA_BUILD); 398 " \"question\": \"12:8:10:20\","
153 EXPECT_EQ(promo_build_type & PromoResourceService::STABLE_BUILD, 0); 399 " \"tooltip\": \"Happy 3rd Birthday!\","
154 400 " \"inproduct\": \"09/15/10 05:00 PDT\""
155 int promo_time_slice = prefs->GetInteger(prefs::kNTPPromoGroupTimeSlice); 401 " },"
156 EXPECT_EQ(promo_time_slice, 2); 402 " {"
157 403 " \"name\": \"promo_end\","
158 int promo_group_max = prefs->GetInteger(prefs::kNTPPromoGroupMax); 404 " \"inproduct\": \"09/30/10 05:00 PDT\""
159 EXPECT_EQ(promo_group_max, 5); 405 " }"
160 406 " ]"
161 double promo_start = prefs->GetDouble(prefs::kNTPPromoStart); 407 " }"
162 double actual_start = 1264899600; // unix epoch for Jan 31 2010 0100 GMT. 408 "}",
163 EXPECT_EQ(promo_start, actual_start); 409 1284552000, // unix epoch for Sep 15 2010 0500 PDT.
164 410 1285848000, // unix epoch for Sep 30 2010 0500 PDT.
165 double modified_start = actual_start + promo_group * 2 * 60 * 60; 411 12, 8, 10, 20,
166 EXPECT_EQ(PromoResourceService::GetNotificationStartTime(prefs), 412 "Happy 3rd Birthday!", false);
167 modified_start); 413
168 414 delegate.InitPromoFromJson(true);
169 double promo_end = prefs->GetDouble(prefs::kNTPPromoEnd); 415
170 EXPECT_EQ(promo_end, 1327971600); // unix epoch for Jan 31 2012 0100 GMT. 416 // Second time should not trigger a notification.
171 417 delegate.InitPromoFromJson(false);
172 // Unpack the same json a second time. 418
173 web_resource_service_->UnpackNotificationSignal(*(test_json.get())); 419 delegate.TestInitFromPrefs();
174 420
175 // All the data should be unchanged. 421 // Should fail because out of time bounds.
176 EXPECT_EQ(promo_line, prefs->GetString(prefs::kNTPPromoLine)); 422 EXPECT_FALSE(promo_notification.CanShow());
177 EXPECT_EQ(promo_group, prefs->GetInteger(prefs::kNTPPromoGroup)); 423 }
178 EXPECT_EQ(promo_build_type, prefs->GetInteger(prefs::kNTPPromoBuild)); 424
179 EXPECT_EQ(promo_time_slice, 425 TEST_F(PromoResourceServiceTest, GetNextQuestionValueTest) {
180 prefs->GetInteger(prefs::kNTPPromoGroupTimeSlice)); 426 const std::string question("0:-100:2048:0:2a");
181 EXPECT_EQ(promo_group_max, prefs->GetInteger(prefs::kNTPPromoGroupMax)); 427 const int question_vec[] = { 0, -100, 2048, 0 };
182 EXPECT_EQ(promo_start, prefs->GetDouble(prefs::kNTPPromoStart)); 428 size_t index = 0;
183 EXPECT_EQ(modified_start, 429 bool err = false;
184 PromoResourceService::GetNotificationStartTime(prefs)); 430
185 EXPECT_EQ(promo_end, prefs->GetDouble(prefs::kNTPPromoEnd)); 431 for (size_t i = 0; i < arraysize(question_vec); ++i) {
432 EXPECT_EQ(question_vec[i],
433 PromoNotification::GetNextQuestionValue(question, &index, &err));
434 EXPECT_FALSE(err);
435 }
436 EXPECT_EQ(PromoNotification::GetNextQuestionValue(question, &index, &err), 0);
437 EXPECT_TRUE(err);
438 }
439
440 TEST_F(PromoResourceServiceTest, NewGroupTest) {
441 for (size_t i = 0; i < 1000; ++i) {
442 const int group = PromoNotification::NewGroup();
443 EXPECT_GE(group, 0);
444 EXPECT_LT(group, 100);
445 }
186 } 446 }
187 447
188 TEST_F(PromoResourceServiceTest, UnpackWebStoreSignal) { 448 TEST_F(PromoResourceServiceTest, UnpackWebStoreSignal) {
189 web_resource_service_->set_channel(chrome::VersionInfo::CHANNEL_DEV); 449 web_resource_service_->set_channel(chrome::VersionInfo::CHANNEL_DEV);
190 450
191 std::string json = "{ " 451 std::string json = "{ "
192 " \"topic\": {" 452 " \"topic\": {"
193 " \"answers\": [" 453 " \"answers\": ["
194 " {" 454 " {"
195 " \"answer_id\": \"341252\"," 455 " \"answer_id\": \"341252\","
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 EXPECT_EQ("The button label!", actual_data.button); 662 EXPECT_EQ("The button label!", actual_data.button);
403 EXPECT_EQ(GURL("http://link.com"), actual_data.link); 663 EXPECT_EQ(GURL("http://link.com"), actual_data.link);
404 EXPECT_EQ("No thanks, hide this.", actual_data.expire); 664 EXPECT_EQ("No thanks, hide this.", actual_data.expire);
405 EXPECT_EQ(AppsPromo::USERS_NEW, actual_data.user_group); 665 EXPECT_EQ(AppsPromo::USERS_NEW, actual_data.user_group);
406 666
407 // Logos should be the default values because HTTP URLs are not valid. 667 // Logos should be the default values because HTTP URLs are not valid.
408 EXPECT_EQ(GURL("chrome://theme/IDR_WEBSTORE_ICON"), actual_data.logo); 668 EXPECT_EQ(GURL("chrome://theme/IDR_WEBSTORE_ICON"), actual_data.logo);
409 EXPECT_EQ(GURL(""), AppsPromo::GetSourcePromoLogoURL()); 669 EXPECT_EQ(GURL(""), AppsPromo::GetSourcePromoLogoURL());
410 } 670 }
411 671
412 TEST_F(PromoResourceServiceTest, IsBuildTargeted) { 672 TEST_F(PromoResourceServiceTest, IsBuildTargetedTest) {
413 // canary 673 // canary
414 const chrome::VersionInfo::Channel canary = 674 const chrome::VersionInfo::Channel canary =
415 chrome::VersionInfo::CHANNEL_CANARY; 675 chrome::VersionInfo::CHANNEL_CANARY;
416 EXPECT_FALSE(PromoResourceService::IsBuildTargeted(canary, 1)); 676 EXPECT_FALSE(PromoResourceService::IsBuildTargeted(canary, 1));
417 EXPECT_FALSE(PromoResourceService::IsBuildTargeted(canary, 3)); 677 EXPECT_FALSE(PromoResourceService::IsBuildTargeted(canary, 3));
418 EXPECT_FALSE(PromoResourceService::IsBuildTargeted(canary, 7)); 678 EXPECT_FALSE(PromoResourceService::IsBuildTargeted(canary, 7));
419 EXPECT_TRUE(PromoResourceService::IsBuildTargeted(canary, 15)); 679 EXPECT_TRUE(PromoResourceService::IsBuildTargeted(canary, 15));
420 EXPECT_TRUE(PromoResourceService::IsBuildTargeted(canary, 8)); 680 EXPECT_TRUE(PromoResourceService::IsBuildTargeted(canary, 8));
421 EXPECT_TRUE(PromoResourceService::IsBuildTargeted(canary, 11)); 681 EXPECT_TRUE(PromoResourceService::IsBuildTargeted(canary, 11));
422 682
(...skipping 21 matching lines...) Expand all
444 const chrome::VersionInfo::Channel stable = 704 const chrome::VersionInfo::Channel stable =
445 chrome::VersionInfo::CHANNEL_STABLE; 705 chrome::VersionInfo::CHANNEL_STABLE;
446 EXPECT_FALSE(PromoResourceService::IsBuildTargeted(stable, 1)); 706 EXPECT_FALSE(PromoResourceService::IsBuildTargeted(stable, 1));
447 EXPECT_FALSE(PromoResourceService::IsBuildTargeted(stable, 3)); 707 EXPECT_FALSE(PromoResourceService::IsBuildTargeted(stable, 3));
448 EXPECT_TRUE(PromoResourceService::IsBuildTargeted(stable, 7)); 708 EXPECT_TRUE(PromoResourceService::IsBuildTargeted(stable, 7));
449 EXPECT_TRUE(PromoResourceService::IsBuildTargeted(stable, 15)); 709 EXPECT_TRUE(PromoResourceService::IsBuildTargeted(stable, 15));
450 EXPECT_FALSE(PromoResourceService::IsBuildTargeted(stable, 8)); 710 EXPECT_FALSE(PromoResourceService::IsBuildTargeted(stable, 8));
451 EXPECT_FALSE(PromoResourceService::IsBuildTargeted(stable, 11)); 711 EXPECT_FALSE(PromoResourceService::IsBuildTargeted(stable, 11));
452 EXPECT_TRUE(PromoResourceService::IsBuildTargeted(stable, 12)); 712 EXPECT_TRUE(PromoResourceService::IsBuildTargeted(stable, 12));
453 } 713 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698