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

Side by Side Diff: components/rlz/rlz_tracker.cc

Issue 1229933005: Revert "Componentize chrome/browser/rlz" (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 5 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
« no previous file with comments | « components/rlz/rlz_tracker.h ('k') | components/rlz/rlz_tracker_chromeos.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4 //
5 // This code glues the RLZ library DLL with Chrome. It allows Chrome to work
6 // with or without the DLL being present. If the DLL is not present the
7 // functions do nothing and just return false.
8
9 #include "components/rlz/rlz_tracker.h"
10
11 #include <algorithm>
12
13 #include "base/bind.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/strings/string_util.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "base/trace_event/trace_event.h"
18 #include "components/rlz/rlz_tracker_delegate.h"
19 #include "net/http/http_util.h"
20
21 namespace rlz {
22 namespace {
23
24 // Maximum and minimum delay for financial ping we would allow to be set through
25 // master preferences. Somewhat arbitrary, may need to be adjusted in future.
26 const base::TimeDelta kMaxInitDelay = base::TimeDelta::FromSeconds(200);
27 const base::TimeDelta kMinInitDelay = base::TimeDelta::FromSeconds(20);
28
29 void RecordProductEvents(bool first_run,
30 bool is_google_default_search,
31 bool is_google_homepage,
32 bool is_google_in_startpages,
33 bool already_ran,
34 bool omnibox_used,
35 bool homepage_used,
36 bool app_list_used) {
37 TRACE_EVENT0("RLZ", "RecordProductEvents");
38 // Record the installation of chrome. We call this all the time but the rlz
39 // lib should ignore all but the first one.
40 rlz_lib::RecordProductEvent(rlz_lib::CHROME,
41 RLZTracker::ChromeOmnibox(),
42 rlz_lib::INSTALL);
43 #if !defined(OS_IOS)
44 rlz_lib::RecordProductEvent(rlz_lib::CHROME,
45 RLZTracker::ChromeHomePage(),
46 rlz_lib::INSTALL);
47 rlz_lib::RecordProductEvent(rlz_lib::CHROME,
48 RLZTracker::ChromeAppList(),
49 rlz_lib::INSTALL);
50 #endif // !defined(OS_IOS)
51
52 if (!already_ran) {
53 // Do the initial event recording if is the first run or if we have an
54 // empty rlz which means we haven't got a chance to do it.
55 char omnibox_rlz[rlz_lib::kMaxRlzLength + 1];
56 if (!rlz_lib::GetAccessPointRlz(RLZTracker::ChromeOmnibox(), omnibox_rlz,
57 rlz_lib::kMaxRlzLength)) {
58 omnibox_rlz[0] = 0;
59 }
60
61 // Record if google is the initial search provider and/or home page.
62 if ((first_run || omnibox_rlz[0] == 0) && is_google_default_search) {
63 rlz_lib::RecordProductEvent(rlz_lib::CHROME,
64 RLZTracker::ChromeOmnibox(),
65 rlz_lib::SET_TO_GOOGLE);
66 }
67
68 #if !defined(OS_IOS)
69 char homepage_rlz[rlz_lib::kMaxRlzLength + 1];
70 if (!rlz_lib::GetAccessPointRlz(RLZTracker::ChromeHomePage(), homepage_rlz,
71 rlz_lib::kMaxRlzLength)) {
72 homepage_rlz[0] = 0;
73 }
74
75 if ((first_run || homepage_rlz[0] == 0) &&
76 (is_google_homepage || is_google_in_startpages)) {
77 rlz_lib::RecordProductEvent(rlz_lib::CHROME,
78 RLZTracker::ChromeHomePage(),
79 rlz_lib::SET_TO_GOOGLE);
80 }
81
82 char app_list_rlz[rlz_lib::kMaxRlzLength + 1];
83 if (!rlz_lib::GetAccessPointRlz(RLZTracker::ChromeAppList(), app_list_rlz,
84 rlz_lib::kMaxRlzLength)) {
85 app_list_rlz[0] = 0;
86 }
87
88 // Record if google is the initial search provider and/or home page.
89 if ((first_run || app_list_rlz[0] == 0) && is_google_default_search) {
90 rlz_lib::RecordProductEvent(rlz_lib::CHROME,
91 RLZTracker::ChromeAppList(),
92 rlz_lib::SET_TO_GOOGLE);
93 }
94 #endif // !defined(OS_IOS)
95 }
96
97 // Record first user interaction with the omnibox. We call this all the
98 // time but the rlz lib should ingore all but the first one.
99 if (omnibox_used) {
100 rlz_lib::RecordProductEvent(rlz_lib::CHROME,
101 RLZTracker::ChromeOmnibox(),
102 rlz_lib::FIRST_SEARCH);
103 }
104
105 #if !defined(OS_IOS)
106 // Record first user interaction with the home page. We call this all the
107 // time but the rlz lib should ingore all but the first one.
108 if (homepage_used || is_google_in_startpages) {
109 rlz_lib::RecordProductEvent(rlz_lib::CHROME,
110 RLZTracker::ChromeHomePage(),
111 rlz_lib::FIRST_SEARCH);
112 }
113
114 // Record first user interaction with the app list. We call this all the
115 // time but the rlz lib should ingore all but the first one.
116 if (app_list_used) {
117 rlz_lib::RecordProductEvent(rlz_lib::CHROME,
118 RLZTracker::ChromeAppList(),
119 rlz_lib::FIRST_SEARCH);
120 }
121 #endif // !defined(OS_IOS)
122 }
123
124 bool SendFinancialPing(const std::string& brand,
125 const base::string16& lang,
126 const base::string16& referral) {
127 rlz_lib::AccessPoint points[] = {RLZTracker::ChromeOmnibox(),
128 #if !defined(OS_IOS)
129 RLZTracker::ChromeHomePage(),
130 RLZTracker::ChromeAppList(),
131 #endif
132 rlz_lib::NO_ACCESS_POINT};
133 std::string lang_ascii(base::UTF16ToASCII(lang));
134 std::string referral_ascii(base::UTF16ToASCII(referral));
135 std::string product_signature;
136 #if defined(OS_CHROMEOS)
137 product_signature = "chromeos";
138 #else
139 product_signature = "chrome";
140 #endif
141 return rlz_lib::SendFinancialPing(rlz_lib::CHROME, points,
142 product_signature.c_str(),
143 brand.c_str(), referral_ascii.c_str(),
144 lang_ascii.c_str(), false, true);
145 }
146
147 } // namespace
148
149 RLZTracker* RLZTracker::tracker_ = nullptr;
150
151 // static
152 RLZTracker* RLZTracker::GetInstance() {
153 return tracker_ ? tracker_ : Singleton<RLZTracker>::get();
154 }
155
156 RLZTracker::RLZTracker()
157 : first_run_(false),
158 send_ping_immediately_(false),
159 is_google_default_search_(false),
160 is_google_homepage_(false),
161 is_google_in_startpages_(false),
162 already_ran_(false),
163 omnibox_used_(false),
164 homepage_used_(false),
165 app_list_used_(false),
166 min_init_delay_(kMinInitDelay) {
167 }
168
169 RLZTracker::~RLZTracker() {
170 }
171
172 // static
173 void RLZTracker::SetRlzDelegate(scoped_ptr<RLZTrackerDelegate> delegate) {
174 GetInstance()->SetDelegate(delegate.Pass());
175 }
176
177 void RLZTracker::SetDelegate(scoped_ptr<RLZTrackerDelegate> delegate) {
178 DCHECK(delegate);
179 if (!delegate_) {
180 delegate_ = delegate.Pass();
181 worker_pool_token_ = delegate_->GetBlockingPool()->GetSequenceToken();
182 }
183 }
184
185 // static
186 bool RLZTracker::InitRlzDelayed(bool first_run,
187 bool send_ping_immediately,
188 base::TimeDelta delay,
189 bool is_google_default_search,
190 bool is_google_homepage,
191 bool is_google_in_startpages) {
192 return GetInstance()->Init(first_run, send_ping_immediately, delay,
193 is_google_default_search, is_google_homepage,
194 is_google_in_startpages);
195 }
196
197 bool RLZTracker::Init(bool first_run,
198 bool send_ping_immediately,
199 base::TimeDelta delay,
200 bool is_google_default_search,
201 bool is_google_homepage,
202 bool is_google_in_startpages) {
203 first_run_ = first_run;
204 is_google_default_search_ = is_google_default_search;
205 is_google_homepage_ = is_google_homepage;
206 is_google_in_startpages_ = is_google_in_startpages;
207 send_ping_immediately_ = send_ping_immediately;
208
209 // Enable zero delays for testing.
210 if (delegate_->ShouldEnableZeroDelayForTesting())
211 EnableZeroDelayForTesting();
212
213 delay = std::min(kMaxInitDelay, std::max(min_init_delay_, delay));
214
215 if (delegate_->GetBrand(&brand_) && !delegate_->IsBrandOrganic(brand_)) {
216 // Register for notifications from the omnibox so that we can record when
217 // the user performs a first search.
218 delegate_->SetOmniboxSearchCallback(
219 base::Bind(&RLZTracker::RecordFirstSearch, base::Unretained(this),
220 ChromeOmnibox()));
221
222 #if !defined(OS_IOS)
223 // Register for notifications from navigations, to see if the user has used
224 // the home page.
225 delegate_->SetHomepageSearchCallback(
226 base::Bind(&RLZTracker::RecordFirstSearch, base::Unretained(this),
227 ChromeHomePage()));
228 #endif
229 }
230 delegate_->GetReactivationBrand(&reactivation_brand_);
231
232 // Could be null; don't run if so. RLZ will try again next restart.
233 net::URLRequestContextGetter* context_getter = delegate_->GetRequestContext();
234 if (context_getter) {
235 rlz_lib::SetURLRequestContext(context_getter);
236 ScheduleDelayedInit(delay);
237 }
238
239 #if !defined(OS_IOS)
240 // Prime the RLZ cache for the home page access point so that its avaiable
241 // for the startup page if needed (i.e., when the startup page is set to
242 // the home page).
243 GetAccessPointRlz(ChromeHomePage(), nullptr);
244 #endif // !defined(OS_IOS)
245
246 return true;
247 }
248
249 void RLZTracker::Cleanup() {
250 rlz_cache_.clear();
251 if (delegate_)
252 delegate_->Cleanup();
253 }
254
255 void RLZTracker::ScheduleDelayedInit(base::TimeDelta delay) {
256 // The RLZTracker is a singleton object that outlives any runnable tasks
257 // that will be queued up.
258 delegate_->GetBlockingPool()->PostDelayedSequencedWorkerTask(
259 worker_pool_token_, FROM_HERE,
260 base::Bind(&RLZTracker::DelayedInit, base::Unretained(this)), delay);
261 }
262
263 void RLZTracker::DelayedInit() {
264 bool schedule_ping = false;
265
266 // For organic brandcodes do not use rlz at all. Empty brandcode usually
267 // means a chromium install. This is ok.
268 if (!delegate_->IsBrandOrganic(brand_)) {
269 RecordProductEvents(first_run_, is_google_default_search_,
270 is_google_homepage_, is_google_in_startpages_,
271 already_ran_, omnibox_used_, homepage_used_,
272 app_list_used_);
273 schedule_ping = true;
274 }
275
276 // If chrome has been reactivated, record the events for this brand
277 // as well.
278 if (!delegate_->IsBrandOrganic(reactivation_brand_)) {
279 rlz_lib::SupplementaryBranding branding(reactivation_brand_.c_str());
280 RecordProductEvents(first_run_, is_google_default_search_,
281 is_google_homepage_, is_google_in_startpages_,
282 already_ran_, omnibox_used_, homepage_used_,
283 app_list_used_);
284 schedule_ping = true;
285 }
286
287 already_ran_ = true;
288
289 if (schedule_ping)
290 ScheduleFinancialPing();
291 }
292
293 void RLZTracker::ScheduleFinancialPing() {
294 delegate_->GetBlockingPool()->PostSequencedWorkerTaskWithShutdownBehavior(
295 worker_pool_token_, FROM_HERE,
296 base::Bind(&RLZTracker::PingNowImpl, base::Unretained(this)),
297 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
298 }
299
300 void RLZTracker::PingNowImpl() {
301 TRACE_EVENT0("RLZ", "RLZTracker::PingNowImpl");
302 base::string16 lang;
303 delegate_->GetLanguage(&lang);
304 if (lang.empty())
305 lang = base::ASCIIToUTF16("en");
306 base::string16 referral;
307 delegate_->GetReferral(&referral);
308
309 if (!delegate_->IsBrandOrganic(brand_) &&
310 SendFinancialPing(brand_, lang, referral)) {
311 delegate_->ClearReferral();
312
313 {
314 base::AutoLock lock(cache_lock_);
315 rlz_cache_.clear();
316 }
317
318 // Prime the RLZ cache for the access points we are interested in.
319 GetAccessPointRlz(RLZTracker::ChromeOmnibox(), nullptr);
320 #if !defined(OS_IOS)
321 GetAccessPointRlz(RLZTracker::ChromeHomePage(), nullptr);
322 GetAccessPointRlz(RLZTracker::ChromeAppList(), nullptr);
323 #endif // !defined(OS_IOS)
324 }
325
326 if (!delegate_->IsBrandOrganic(reactivation_brand_)) {
327 rlz_lib::SupplementaryBranding branding(reactivation_brand_.c_str());
328 SendFinancialPing(reactivation_brand_, lang, referral);
329 }
330 }
331
332 bool RLZTracker::SendFinancialPing(const std::string& brand,
333 const base::string16& lang,
334 const base::string16& referral) {
335 return ::rlz::SendFinancialPing(brand, lang, referral);
336 }
337
338 // static
339 bool RLZTracker::RecordProductEvent(rlz_lib::Product product,
340 rlz_lib::AccessPoint point,
341 rlz_lib::Event event_id) {
342 return GetInstance()->RecordProductEventImpl(product, point, event_id);
343 }
344
345 bool RLZTracker::RecordProductEventImpl(rlz_lib::Product product,
346 rlz_lib::AccessPoint point,
347 rlz_lib::Event event_id) {
348 // Make sure we don't access disk outside of the I/O thread.
349 // In such case we repost the task on the right thread and return error.
350 if (ScheduleRecordProductEvent(product, point, event_id))
351 return true;
352
353 bool ret = rlz_lib::RecordProductEvent(product, point, event_id);
354
355 // If chrome has been reactivated, record the event for this brand as well.
356 if (!reactivation_brand_.empty()) {
357 rlz_lib::SupplementaryBranding branding(reactivation_brand_.c_str());
358 ret &= rlz_lib::RecordProductEvent(product, point, event_id);
359 }
360
361 return ret;
362 }
363
364 bool RLZTracker::ScheduleRecordProductEvent(rlz_lib::Product product,
365 rlz_lib::AccessPoint point,
366 rlz_lib::Event event_id) {
367 if (!delegate_->IsOnUIThread())
368 return false;
369
370 delegate_->GetBlockingPool()->PostSequencedWorkerTaskWithShutdownBehavior(
371 worker_pool_token_, FROM_HERE,
372 base::Bind(base::IgnoreResult(&RLZTracker::RecordProductEvent), product,
373 point, event_id),
374 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
375
376 return true;
377 }
378
379 void RLZTracker::RecordFirstSearch(rlz_lib::AccessPoint point) {
380 // Make sure we don't access disk outside of the I/O thread.
381 // In such case we repost the task on the right thread and return error.
382 if (ScheduleRecordFirstSearch(point))
383 return;
384
385 bool* record_used = GetAccessPointRecord(point);
386
387 // Try to record event now, else set the flag to try later when we
388 // attempt the ping.
389 if (!RecordProductEvent(rlz_lib::CHROME, point, rlz_lib::FIRST_SEARCH))
390 *record_used = true;
391 else if (send_ping_immediately_ && point == ChromeOmnibox())
392 ScheduleDelayedInit(base::TimeDelta());
393 }
394
395 bool RLZTracker::ScheduleRecordFirstSearch(rlz_lib::AccessPoint point) {
396 if (!delegate_->IsOnUIThread())
397 return false;
398 delegate_->GetBlockingPool()->PostSequencedWorkerTaskWithShutdownBehavior(
399 worker_pool_token_, FROM_HERE,
400 base::Bind(&RLZTracker::RecordFirstSearch, base::Unretained(this), point),
401 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
402 return true;
403 }
404
405 bool* RLZTracker::GetAccessPointRecord(rlz_lib::AccessPoint point) {
406 if (point == ChromeOmnibox())
407 return &omnibox_used_;
408 #if !defined(OS_IOS)
409 if (point == ChromeHomePage())
410 return &homepage_used_;
411 if (point == ChromeAppList())
412 return &app_list_used_;
413 #endif // !defined(OS_IOS)
414 NOTREACHED();
415 return nullptr;
416 }
417
418 // static
419 std::string RLZTracker::GetAccessPointHttpHeader(rlz_lib::AccessPoint point) {
420 TRACE_EVENT0("RLZ", "RLZTracker::GetAccessPointHttpHeader");
421 std::string extra_headers;
422 base::string16 rlz_string;
423 RLZTracker::GetAccessPointRlz(point, &rlz_string);
424 if (!rlz_string.empty()) {
425 net::HttpUtil::AppendHeaderIfMissing("X-Rlz-String",
426 base::UTF16ToUTF8(rlz_string),
427 &extra_headers);
428 }
429
430 return extra_headers;
431 }
432
433 // GetAccessPointRlz() caches RLZ strings for all access points. If we had
434 // a successful ping, then we update the cached value.
435 bool RLZTracker::GetAccessPointRlz(rlz_lib::AccessPoint point,
436 base::string16* rlz) {
437 TRACE_EVENT0("RLZ", "RLZTracker::GetAccessPointRlz");
438 return GetInstance()->GetAccessPointRlzImpl(point, rlz);
439 }
440
441 // GetAccessPointRlz() caches RLZ strings for all access points. If we had
442 // a successful ping, then we update the cached value.
443 bool RLZTracker::GetAccessPointRlzImpl(rlz_lib::AccessPoint point,
444 base::string16* rlz) {
445 // If the RLZ string for the specified access point is already cached,
446 // simply return its value.
447 {
448 base::AutoLock lock(cache_lock_);
449 if (rlz_cache_.find(point) != rlz_cache_.end()) {
450 if (rlz)
451 *rlz = rlz_cache_[point];
452 return true;
453 }
454 }
455
456 // Make sure we don't access disk outside of the I/O thread.
457 // In such case we repost the task on the right thread and return error.
458 if (ScheduleGetAccessPointRlz(point))
459 return false;
460
461 char str_rlz[rlz_lib::kMaxRlzLength + 1];
462 if (!rlz_lib::GetAccessPointRlz(point, str_rlz, rlz_lib::kMaxRlzLength))
463 return false;
464
465 base::string16 rlz_local(base::ASCIIToUTF16(str_rlz));
466 if (rlz)
467 *rlz = rlz_local;
468
469 base::AutoLock lock(cache_lock_);
470 rlz_cache_[point] = rlz_local;
471 return true;
472 }
473
474 bool RLZTracker::ScheduleGetAccessPointRlz(rlz_lib::AccessPoint point) {
475 if (!delegate_->IsOnUIThread())
476 return false;
477
478 base::string16* not_used = nullptr;
479 delegate_->GetBlockingPool()->PostSequencedWorkerTaskWithShutdownBehavior(
480 worker_pool_token_, FROM_HERE,
481 base::Bind(base::IgnoreResult(&RLZTracker::GetAccessPointRlz), point,
482 not_used),
483 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
484 return true;
485 }
486
487 #if defined(OS_CHROMEOS)
488 // static
489 void RLZTracker::ClearRlzState() {
490 GetInstance()->ClearRlzStateImpl();
491 }
492
493 void RLZTracker::ClearRlzStateImpl() {
494 if (ScheduleClearRlzState())
495 return;
496 rlz_lib::ClearAllProductEvents(rlz_lib::CHROME);
497 }
498
499 bool RLZTracker::ScheduleClearRlzState() {
500 if (!delegate_->IsOnUIThread())
501 return false;
502
503 delegate_->GetBlockingPool()->PostSequencedWorkerTaskWithShutdownBehavior(
504 worker_pool_token_, FROM_HERE,
505 base::Bind(&RLZTracker::ClearRlzStateImpl, base::Unretained(this)),
506 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
507 return true;
508 }
509 #endif
510
511 // static
512 void RLZTracker::CleanupRlz() {
513 GetInstance()->Cleanup();
514 rlz_lib::SetURLRequestContext(nullptr);
515 }
516
517 // static
518 void RLZTracker::EnableZeroDelayForTesting() {
519 GetInstance()->min_init_delay_ = base::TimeDelta();
520 }
521
522 #if !defined(OS_IOS)
523 // static
524 void RLZTracker::RecordAppListSearch() {
525 GetInstance()->RecordFirstSearch(RLZTracker::ChromeAppList());
526 }
527 #endif
528
529 } // namespace rlz
OLDNEW
« no previous file with comments | « components/rlz/rlz_tracker.h ('k') | components/rlz/rlz_tracker_chromeos.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698