Upstream version 7.35.139.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / rlz / rlz.cc
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 "chrome/browser/rlz/rlz.h"
10
11 #include <algorithm>
12
13 #include "base/bind.h"
14 #include "base/command_line.h"
15 #include "base/debug/trace_event.h"
16 #include "base/message_loop/message_loop.h"
17 #include "base/prefs/pref_service.h"
18 #include "base/strings/string_util.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "chrome/browser/browser_process.h"
21 #include "chrome/browser/chrome_notification_types.h"
22 #include "chrome/browser/google/google_util.h"
23 #include "chrome/browser/prefs/session_startup_pref.h"
24 #include "chrome/browser/search_engines/template_url.h"
25 #include "chrome/browser/search_engines/template_url_service.h"
26 #include "chrome/browser/search_engines/template_url_service_factory.h"
27 #include "chrome/browser/ui/startup/startup_browser_creator.h"
28 #include "chrome/common/chrome_switches.h"
29 #include "chrome/common/pref_names.h"
30 #include "content/public/browser/browser_thread.h"
31 #include "content/public/browser/navigation_entry.h"
32 #include "content/public/browser/notification_service.h"
33 #include "net/http/http_util.h"
34
35 #if defined(OS_WIN)
36 #include "chrome/installer/util/google_update_settings.h"
37 #else
38 namespace GoogleUpdateSettings {
39 static bool GetLanguage(base::string16* language) {
40   // TODO(thakis): Implement.
41   NOTIMPLEMENTED();
42   return false;
43 }
44
45 // The referral program is defunct and not used. No need to implement these
46 // functions on non-Win platforms.
47 static bool GetReferral(base::string16* referral) {
48   return true;
49 }
50 static bool ClearReferral() {
51   return true;
52 }
53 }  // namespace GoogleUpdateSettings
54 #endif
55
56 using content::BrowserThread;
57 using content::NavigationEntry;
58
59 namespace {
60
61 // Maximum and minimum delay for financial ping we would allow to be set through
62 // master preferences. Somewhat arbitrary, may need to be adjusted in future.
63 const base::TimeDelta kMaxInitDelay = base::TimeDelta::FromSeconds(200);
64 const base::TimeDelta kMinInitDelay = base::TimeDelta::FromSeconds(20);
65
66 bool IsBrandOrganic(const std::string& brand) {
67   return brand.empty() || google_util::IsOrganic(brand);
68 }
69
70 void RecordProductEvents(bool first_run,
71                          bool is_google_default_search,
72                          bool is_google_homepage,
73                          bool is_google_in_startpages,
74                          bool already_ran,
75                          bool omnibox_used,
76                          bool homepage_used) {
77   TRACE_EVENT0("RLZ", "RecordProductEvents");
78   // Record the installation of chrome. We call this all the time but the rlz
79   // lib should ignore all but the first one.
80   rlz_lib::RecordProductEvent(rlz_lib::CHROME,
81                               RLZTracker::CHROME_OMNIBOX,
82                               rlz_lib::INSTALL);
83 #if !defined(OS_IOS)
84   rlz_lib::RecordProductEvent(rlz_lib::CHROME,
85                               RLZTracker::CHROME_HOME_PAGE,
86                               rlz_lib::INSTALL);
87 #endif  // !defined(OS_IOS)
88
89   if (!already_ran) {
90     // Do the initial event recording if is the first run or if we have an
91     // empty rlz which means we haven't got a chance to do it.
92     char omnibox_rlz[rlz_lib::kMaxRlzLength + 1];
93     if (!rlz_lib::GetAccessPointRlz(RLZTracker::CHROME_OMNIBOX, omnibox_rlz,
94                                     rlz_lib::kMaxRlzLength)) {
95       omnibox_rlz[0] = 0;
96     }
97
98     // Record if google is the initial search provider and/or home page.
99     if ((first_run || omnibox_rlz[0] == 0) && is_google_default_search) {
100       rlz_lib::RecordProductEvent(rlz_lib::CHROME,
101                                   RLZTracker::CHROME_OMNIBOX,
102                                   rlz_lib::SET_TO_GOOGLE);
103     }
104
105 #if !defined(OS_IOS)
106     char homepage_rlz[rlz_lib::kMaxRlzLength + 1];
107     if (!rlz_lib::GetAccessPointRlz(RLZTracker::CHROME_HOME_PAGE, homepage_rlz,
108                                     rlz_lib::kMaxRlzLength)) {
109       homepage_rlz[0] = 0;
110     }
111
112     if ((first_run || homepage_rlz[0] == 0) &&
113         (is_google_homepage || is_google_in_startpages)) {
114       rlz_lib::RecordProductEvent(rlz_lib::CHROME,
115                                   RLZTracker::CHROME_HOME_PAGE,
116                                   rlz_lib::SET_TO_GOOGLE);
117     }
118 #endif  // !defined(OS_IOS)
119   }
120
121   // Record first user interaction with the omnibox. We call this all the
122   // time but the rlz lib should ingore all but the first one.
123   if (omnibox_used) {
124     rlz_lib::RecordProductEvent(rlz_lib::CHROME,
125                                 RLZTracker::CHROME_OMNIBOX,
126                                 rlz_lib::FIRST_SEARCH);
127   }
128
129 #if !defined(OS_IOS)
130   // Record first user interaction with the home page. We call this all the
131   // time but the rlz lib should ingore all but the first one.
132   if (homepage_used || is_google_in_startpages) {
133     rlz_lib::RecordProductEvent(rlz_lib::CHROME,
134                                 RLZTracker::CHROME_HOME_PAGE,
135                                 rlz_lib::FIRST_SEARCH);
136   }
137 #endif  // !defined(OS_IOS)
138 }
139
140 bool SendFinancialPing(const std::string& brand,
141                        const base::string16& lang,
142                        const base::string16& referral) {
143   rlz_lib::AccessPoint points[] = {RLZTracker::CHROME_OMNIBOX,
144 #if !defined(OS_IOS)
145                                    RLZTracker::CHROME_HOME_PAGE,
146 #endif
147                                    rlz_lib::NO_ACCESS_POINT};
148   std::string lang_ascii(base::UTF16ToASCII(lang));
149   std::string referral_ascii(base::UTF16ToASCII(referral));
150   std::string product_signature;
151 #if defined(OS_CHROMEOS)
152   product_signature = "chromeos";
153 #else
154   product_signature = "chrome";
155 #endif
156   return rlz_lib::SendFinancialPing(rlz_lib::CHROME, points,
157                                     product_signature.c_str(),
158                                     brand.c_str(), referral_ascii.c_str(),
159                                     lang_ascii.c_str(), false, true);
160 }
161
162 }  // namespace
163
164 #if defined(OS_WIN)
165 // static
166 const rlz_lib::AccessPoint RLZTracker::CHROME_OMNIBOX =
167     rlz_lib::CHROME_OMNIBOX;
168 // static
169 const rlz_lib::AccessPoint RLZTracker::CHROME_HOME_PAGE =
170     rlz_lib::CHROME_HOME_PAGE;
171 #elif defined(OS_IOS)
172 // static
173 const rlz_lib::AccessPoint RLZTracker::CHROME_OMNIBOX =
174     rlz_lib::CHROME_IOS_OMNIBOX;
175 #elif defined(OS_MACOSX)
176 // static
177 const rlz_lib::AccessPoint RLZTracker::CHROME_OMNIBOX =
178     rlz_lib::CHROME_MAC_OMNIBOX;
179 // static
180 const rlz_lib::AccessPoint RLZTracker::CHROME_HOME_PAGE =
181     rlz_lib::CHROME_MAC_HOME_PAGE;
182 #elif defined(OS_CHROMEOS)
183 // static
184 const rlz_lib::AccessPoint RLZTracker::CHROME_OMNIBOX =
185     rlz_lib::CHROMEOS_OMNIBOX;
186 // static
187 const rlz_lib::AccessPoint RLZTracker::CHROME_HOME_PAGE =
188     rlz_lib::CHROMEOS_HOME_PAGE;
189 #endif
190
191 RLZTracker* RLZTracker::tracker_ = NULL;
192
193 // static
194 RLZTracker* RLZTracker::GetInstance() {
195   return tracker_ ? tracker_ : Singleton<RLZTracker>::get();
196 }
197
198 RLZTracker::RLZTracker()
199     : first_run_(false),
200       send_ping_immediately_(false),
201       is_google_default_search_(false),
202       is_google_homepage_(false),
203       is_google_in_startpages_(false),
204       worker_pool_token_(BrowserThread::GetBlockingPool()->GetSequenceToken()),
205       already_ran_(false),
206       omnibox_used_(false),
207       homepage_used_(false),
208       min_init_delay_(kMinInitDelay) {
209 }
210
211 RLZTracker::~RLZTracker() {
212 }
213
214 // static
215 bool RLZTracker::InitRlzDelayed(bool first_run,
216                                 bool send_ping_immediately,
217                                 base::TimeDelta delay,
218                                 bool is_google_default_search,
219                                 bool is_google_homepage,
220                                 bool is_google_in_startpages) {
221   return GetInstance()->Init(first_run, send_ping_immediately, delay,
222                              is_google_default_search, is_google_homepage,
223                              is_google_in_startpages);
224 }
225
226 // static
227 bool RLZTracker::InitRlzFromProfileDelayed(Profile* profile,
228                                            bool first_run,
229                                            bool send_ping_immediately,
230                                            base::TimeDelta delay) {
231   bool is_google_default_search = false;
232   TemplateURLService* template_url_service =
233       TemplateURLServiceFactory::GetForProfile(profile);
234   if (template_url_service) {
235     const TemplateURL* url_template =
236         template_url_service->GetDefaultSearchProvider();
237     is_google_default_search =
238         url_template && url_template->url_ref().HasGoogleBaseURLs();
239   }
240
241   PrefService* pref_service = profile->GetPrefs();
242   bool is_google_homepage = google_util::IsGoogleHomePageUrl(
243       GURL(pref_service->GetString(prefs::kHomePage)));
244
245   bool is_google_in_startpages = false;
246 #if !defined(OS_IOS)
247   // iOS does not have a notion of startpages.
248   SessionStartupPref session_startup_prefs =
249       StartupBrowserCreator::GetSessionStartupPref(
250           *CommandLine::ForCurrentProcess(), profile);
251   if (session_startup_prefs.type == SessionStartupPref::URLS) {
252     is_google_in_startpages =
253         std::count_if(session_startup_prefs.urls.begin(),
254                       session_startup_prefs.urls.end(),
255                       google_util::IsGoogleHomePageUrl) > 0;
256   }
257 #endif
258
259   if (!InitRlzDelayed(first_run, send_ping_immediately, delay,
260                       is_google_default_search, is_google_homepage,
261                       is_google_in_startpages)) {
262     return false;
263   }
264
265 #if !defined(OS_IOS)
266   // Prime the RLZ cache for the home page access point so that its avaiable
267   // for the startup page if needed (i.e., when the startup page is set to
268   // the home page).
269   GetAccessPointRlz(CHROME_HOME_PAGE, NULL);
270 #endif  // !defined(OS_IOS)
271
272   return true;
273 }
274
275 bool RLZTracker::Init(bool first_run,
276                       bool send_ping_immediately,
277                       base::TimeDelta delay,
278                       bool is_google_default_search,
279                       bool is_google_homepage,
280                       bool is_google_in_startpages) {
281   first_run_ = first_run;
282   is_google_default_search_ = is_google_default_search;
283   is_google_homepage_ = is_google_homepage;
284   is_google_in_startpages_ = is_google_in_startpages;
285   send_ping_immediately_ = send_ping_immediately;
286
287   // Enable zero delays for testing.
288   if (CommandLine::ForCurrentProcess()->HasSwitch(::switches::kTestType))
289     EnableZeroDelayForTesting();
290
291   delay = std::min(kMaxInitDelay, std::max(min_init_delay_, delay));
292
293   if (google_util::GetBrand(&brand_) && !IsBrandOrganic(brand_)) {
294     // Register for notifications from the omnibox so that we can record when
295     // the user performs a first search.
296     registrar_.Add(this, chrome::NOTIFICATION_OMNIBOX_OPENED_URL,
297                    content::NotificationService::AllSources());
298
299 #if !defined(OS_IOS)
300     // Register for notifications from navigations, to see if the user has used
301     // the home page.
302     registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_PENDING,
303                    content::NotificationService::AllSources());
304 #endif  // !defined(OS_IOS)
305   }
306   google_util::GetReactivationBrand(&reactivation_brand_);
307
308   net::URLRequestContextGetter* context_getter =
309       g_browser_process->system_request_context();
310
311   // Could be NULL; don't run if so.  RLZ will try again next restart.
312   if (context_getter) {
313     rlz_lib::SetURLRequestContext(context_getter);
314     ScheduleDelayedInit(delay);
315   }
316
317   return true;
318 }
319
320 void RLZTracker::ScheduleDelayedInit(base::TimeDelta delay) {
321   // The RLZTracker is a singleton object that outlives any runnable tasks
322   // that will be queued up.
323   BrowserThread::GetBlockingPool()->PostDelayedSequencedWorkerTask(
324       worker_pool_token_,
325       FROM_HERE,
326       base::Bind(&RLZTracker::DelayedInit, base::Unretained(this)),
327       delay);
328 }
329
330 void RLZTracker::DelayedInit() {
331   bool schedule_ping = false;
332
333   // For organic brandcodes do not use rlz at all. Empty brandcode usually
334   // means a chromium install. This is ok.
335   if (!IsBrandOrganic(brand_)) {
336     RecordProductEvents(first_run_, is_google_default_search_,
337                         is_google_homepage_, is_google_in_startpages_,
338                         already_ran_, omnibox_used_, homepage_used_);
339     schedule_ping = true;
340   }
341
342   // If chrome has been reactivated, record the events for this brand
343   // as well.
344   if (!IsBrandOrganic(reactivation_brand_)) {
345     rlz_lib::SupplementaryBranding branding(reactivation_brand_.c_str());
346     RecordProductEvents(first_run_, is_google_default_search_,
347                         is_google_homepage_, is_google_in_startpages_,
348                         already_ran_, omnibox_used_, homepage_used_);
349     schedule_ping = true;
350   }
351
352   already_ran_ = true;
353
354   if (schedule_ping)
355     ScheduleFinancialPing();
356 }
357
358 void RLZTracker::ScheduleFinancialPing() {
359   BrowserThread::GetBlockingPool()->PostSequencedWorkerTaskWithShutdownBehavior(
360       worker_pool_token_,
361       FROM_HERE,
362       base::Bind(&RLZTracker::PingNowImpl, base::Unretained(this)),
363       base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
364 }
365
366 void RLZTracker::PingNowImpl() {
367   TRACE_EVENT0("RLZ", "RLZTracker::PingNowImpl");
368   base::string16 lang;
369   GoogleUpdateSettings::GetLanguage(&lang);
370   if (lang.empty())
371     lang = base::ASCIIToUTF16("en");
372   base::string16 referral;
373   GoogleUpdateSettings::GetReferral(&referral);
374
375   if (!IsBrandOrganic(brand_) && SendFinancialPing(brand_, lang, referral)) {
376     GoogleUpdateSettings::ClearReferral();
377
378     {
379       base::AutoLock lock(cache_lock_);
380       rlz_cache_.clear();
381     }
382
383     // Prime the RLZ cache for the access points we are interested in.
384     GetAccessPointRlz(RLZTracker::CHROME_OMNIBOX, NULL);
385 #if !defined(OS_IOS)
386     GetAccessPointRlz(RLZTracker::CHROME_HOME_PAGE, NULL);
387 #endif  // !defined(OS_IOS)
388   }
389
390   if (!IsBrandOrganic(reactivation_brand_)) {
391     rlz_lib::SupplementaryBranding branding(reactivation_brand_.c_str());
392     SendFinancialPing(reactivation_brand_, lang, referral);
393   }
394 }
395
396 bool RLZTracker::SendFinancialPing(const std::string& brand,
397                                    const base::string16& lang,
398                                    const base::string16& referral) {
399   return ::SendFinancialPing(brand, lang, referral);
400 }
401
402 void RLZTracker::Observe(int type,
403                          const content::NotificationSource& source,
404                          const content::NotificationDetails& details) {
405   switch (type) {
406     case chrome::NOTIFICATION_OMNIBOX_OPENED_URL:
407       RecordFirstSearch(CHROME_OMNIBOX);
408       registrar_.Remove(this, chrome::NOTIFICATION_OMNIBOX_OPENED_URL,
409                         content::NotificationService::AllSources());
410       break;
411 #if !defined(OS_IOS)
412     case content::NOTIFICATION_NAV_ENTRY_PENDING: {
413       const NavigationEntry* entry =
414           content::Details<content::NavigationEntry>(details).ptr();
415       if (entry != NULL &&
416           ((entry->GetTransitionType() &
417             content::PAGE_TRANSITION_HOME_PAGE) != 0)) {
418         RecordFirstSearch(CHROME_HOME_PAGE);
419         registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_PENDING,
420                           content::NotificationService::AllSources());
421       }
422       break;
423     }
424 #endif  // !defined(OS_IOS)
425     default:
426       NOTREACHED();
427       break;
428   }
429 }
430
431 // static
432 bool RLZTracker::RecordProductEvent(rlz_lib::Product product,
433                                     rlz_lib::AccessPoint point,
434                                     rlz_lib::Event event_id) {
435   return GetInstance()->RecordProductEventImpl(product, point, event_id);
436 }
437
438 bool RLZTracker::RecordProductEventImpl(rlz_lib::Product product,
439                                         rlz_lib::AccessPoint point,
440                                         rlz_lib::Event event_id) {
441   // Make sure we don't access disk outside of the I/O thread.
442   // In such case we repost the task on the right thread and return error.
443   if (ScheduleRecordProductEvent(product, point, event_id))
444     return true;
445
446   bool ret = rlz_lib::RecordProductEvent(product, point, event_id);
447
448   // If chrome has been reactivated, record the event for this brand as well.
449   if (!reactivation_brand_.empty()) {
450     rlz_lib::SupplementaryBranding branding(reactivation_brand_.c_str());
451     ret &= rlz_lib::RecordProductEvent(product, point, event_id);
452   }
453
454   return ret;
455 }
456
457 bool RLZTracker::ScheduleRecordProductEvent(rlz_lib::Product product,
458                                             rlz_lib::AccessPoint point,
459                                             rlz_lib::Event event_id) {
460   if (!BrowserThread::CurrentlyOn(BrowserThread::UI))
461     return false;
462
463   BrowserThread::GetBlockingPool()->PostSequencedWorkerTaskWithShutdownBehavior(
464       worker_pool_token_,
465       FROM_HERE,
466       base::Bind(base::IgnoreResult(&RLZTracker::RecordProductEvent),
467                  product, point, event_id),
468       base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
469
470   return true;
471 }
472
473 void RLZTracker::RecordFirstSearch(rlz_lib::AccessPoint point) {
474   // Make sure we don't access disk outside of the I/O thread.
475   // In such case we repost the task on the right thread and return error.
476   if (ScheduleRecordFirstSearch(point))
477     return;
478
479 #if !defined(OS_IOS)
480   bool* record_used = point == CHROME_OMNIBOX ?
481       &omnibox_used_ : &homepage_used_;
482 #else
483   DCHECK_EQ(CHROME_OMNIBOX, point);
484   bool* record_used = &omnibox_used_;
485 #endif
486
487   // Try to record event now, else set the flag to try later when we
488   // attempt the ping.
489   if (!RecordProductEvent(rlz_lib::CHROME, point, rlz_lib::FIRST_SEARCH))
490     *record_used = true;
491   else if (send_ping_immediately_ && point == CHROME_OMNIBOX)
492     ScheduleDelayedInit(base::TimeDelta());
493 }
494
495 bool RLZTracker::ScheduleRecordFirstSearch(rlz_lib::AccessPoint point) {
496   if (!BrowserThread::CurrentlyOn(BrowserThread::UI))
497     return false;
498   BrowserThread::GetBlockingPool()->PostSequencedWorkerTaskWithShutdownBehavior(
499       worker_pool_token_,
500       FROM_HERE,
501       base::Bind(&RLZTracker::RecordFirstSearch,
502                  base::Unretained(this), point),
503       base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
504   return true;
505 }
506
507 // static
508 std::string RLZTracker::GetAccessPointHttpHeader(rlz_lib::AccessPoint point) {
509   TRACE_EVENT0("RLZ", "RLZTracker::GetAccessPointHttpHeader");
510   std::string extra_headers;
511   base::string16 rlz_string;
512   RLZTracker::GetAccessPointRlz(point, &rlz_string);
513   if (!rlz_string.empty()) {
514     net::HttpUtil::AppendHeaderIfMissing("X-Rlz-String",
515                                          base::UTF16ToUTF8(rlz_string),
516                                          &extra_headers);
517   }
518
519   return extra_headers;
520 }
521
522 // GetAccessPointRlz() caches RLZ strings for all access points. If we had
523 // a successful ping, then we update the cached value.
524 bool RLZTracker::GetAccessPointRlz(rlz_lib::AccessPoint point,
525                                    base::string16* rlz) {
526   TRACE_EVENT0("RLZ", "RLZTracker::GetAccessPointRlz");
527   return GetInstance()->GetAccessPointRlzImpl(point, rlz);
528 }
529
530 // GetAccessPointRlz() caches RLZ strings for all access points. If we had
531 // a successful ping, then we update the cached value.
532 bool RLZTracker::GetAccessPointRlzImpl(rlz_lib::AccessPoint point,
533                                        base::string16* rlz) {
534   // If the RLZ string for the specified access point is already cached,
535   // simply return its value.
536   {
537     base::AutoLock lock(cache_lock_);
538     if (rlz_cache_.find(point) != rlz_cache_.end()) {
539       if (rlz)
540         *rlz = rlz_cache_[point];
541       return true;
542     }
543   }
544
545   // Make sure we don't access disk outside of the I/O thread.
546   // In such case we repost the task on the right thread and return error.
547   if (ScheduleGetAccessPointRlz(point))
548     return false;
549
550   char str_rlz[rlz_lib::kMaxRlzLength + 1];
551   if (!rlz_lib::GetAccessPointRlz(point, str_rlz, rlz_lib::kMaxRlzLength))
552     return false;
553
554   base::string16 rlz_local(base::ASCIIToUTF16(std::string(str_rlz)));
555   if (rlz)
556     *rlz = rlz_local;
557
558   base::AutoLock lock(cache_lock_);
559   rlz_cache_[point] = rlz_local;
560   return true;
561 }
562
563 bool RLZTracker::ScheduleGetAccessPointRlz(rlz_lib::AccessPoint point) {
564   if (!BrowserThread::CurrentlyOn(BrowserThread::UI))
565     return false;
566
567   base::string16* not_used = NULL;
568   BrowserThread::GetBlockingPool()->PostSequencedWorkerTaskWithShutdownBehavior(
569       worker_pool_token_,
570       FROM_HERE,
571       base::Bind(base::IgnoreResult(&RLZTracker::GetAccessPointRlz), point,
572                  not_used),
573       base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
574   return true;
575 }
576
577 #if defined(OS_CHROMEOS)
578 // static
579 void RLZTracker::ClearRlzState() {
580   GetInstance()->ClearRlzStateImpl();
581 }
582
583 void RLZTracker::ClearRlzStateImpl() {
584   if (ScheduleClearRlzState())
585     return;
586   rlz_lib::ClearAllProductEvents(rlz_lib::CHROME);
587 }
588
589 bool RLZTracker::ScheduleClearRlzState() {
590   if (!BrowserThread::CurrentlyOn(BrowserThread::UI))
591     return false;
592
593   BrowserThread::GetBlockingPool()->PostSequencedWorkerTaskWithShutdownBehavior(
594       worker_pool_token_,
595       FROM_HERE,
596       base::Bind(&RLZTracker::ClearRlzStateImpl,
597                  base::Unretained(this)),
598       base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
599   return true;
600 }
601 #endif
602
603 // static
604 void RLZTracker::CleanupRlz() {
605   GetInstance()->rlz_cache_.clear();
606   GetInstance()->registrar_.RemoveAll();
607   rlz_lib::SetURLRequestContext(NULL);
608 }
609
610 // static
611 void RLZTracker::EnableZeroDelayForTesting() {
612   GetInstance()->min_init_delay_ = base::TimeDelta();
613 }