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

Unified Diff: chrome/browser/rlz/rlz.cc

Issue 7736001: Adding unit tests to RLZ code. Refactoring RLZ code to make it more testable. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Removing all references to headless envvar Created 9 years, 4 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/rlz/rlz.h ('k') | chrome/browser/rlz/rlz_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/rlz/rlz.cc
===================================================================
--- chrome/browser/rlz/rlz.cc (revision 98701)
+++ chrome/browser/rlz/rlz.cc (working copy)
@@ -31,23 +31,78 @@
#include "chrome/common/env_vars.h"
#include "chrome/installer/util/google_update_settings.h"
#include "content/browser/browser_thread.h"
-#include "content/common/notification_registrar.h"
+#include "content/browser/tab_contents/navigation_entry.h"
#include "content/common/notification_service.h"
namespace {
-enum {
- ACCESS_VALUES_STALE, // Possibly new values available.
- ACCESS_VALUES_FRESH // The cached values are current.
-};
+// Organic brands all start with GG, such as GGCM.
+static bool is_organic(const std::wstring& brand) {
+ return (brand.size() < 2) ? false : (brand.substr(0, 2) == L"GG");
+}
-// Tracks if we have tried and succeeded sending the ping. This helps us
-// decide if we need to refresh the cached RLZ string.
-volatile int access_values_state = ACCESS_VALUES_STALE;
-base::Lock rlz_lock;
+void RecordProductEvents(bool first_run, bool google_default_search,
+ bool google_default_homepage, bool already_ran,
+ bool omnibox_used, bool homepage_used) {
+ // Record the installation of chrome. We call this all the time but the rlz
+ // lib should ingore all but the first one.
+ rlz_lib::RecordProductEvent(rlz_lib::CHROME,
+ rlz_lib::CHROME_OMNIBOX,
+ rlz_lib::INSTALL);
+ rlz_lib::RecordProductEvent(rlz_lib::CHROME,
+ rlz_lib::CHROME_HOME_PAGE,
+ rlz_lib::INSTALL);
-bool SendFinancialPing(const std::wstring& brand, const std::wstring& lang,
- const std::wstring& referral, bool exclude_id) {
+ if (!already_ran) {
+ // Do the initial event recording if is the first run or if we have an
+ // empty rlz which means we haven't got a chance to do it.
+ char omnibox_rlz[rlz_lib::kMaxRlzLength + 1];
+ if (!rlz_lib::GetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, omnibox_rlz,
+ rlz_lib::kMaxRlzLength, NULL)) {
+ omnibox_rlz[0] = 0;
+ }
+
+ // Record if google is the initial search provider and/or home page.
+ if ((first_run || omnibox_rlz[0] == 0) && google_default_search) {
+ rlz_lib::RecordProductEvent(rlz_lib::CHROME,
+ rlz_lib::CHROME_OMNIBOX,
+ rlz_lib::SET_TO_GOOGLE);
+ }
+
+ char homepage_rlz[rlz_lib::kMaxRlzLength + 1];
+ if (!rlz_lib::GetAccessPointRlz(rlz_lib::CHROME_HOME_PAGE, homepage_rlz,
+ rlz_lib::kMaxRlzLength, NULL)) {
+ homepage_rlz[0] = 0;
+ }
+
+ if ((first_run || homepage_rlz[0] == 0) && google_default_homepage) {
+ rlz_lib::RecordProductEvent(rlz_lib::CHROME,
+ rlz_lib::CHROME_HOME_PAGE,
+ rlz_lib::SET_TO_GOOGLE);
+ }
+ }
+
+ // Record first user interaction with the omnibox. We call this all the
+ // time but the rlz lib should ingore all but the first one.
+ if (omnibox_used) {
+ rlz_lib::RecordProductEvent(rlz_lib::CHROME,
+ rlz_lib::CHROME_OMNIBOX,
+ rlz_lib::FIRST_SEARCH);
+ }
+
+ // Record first user interaction with the home page. We call this all the
+ // time but the rlz lib should ingore all but the first one.
+ if (homepage_used) {
+ rlz_lib::RecordProductEvent(rlz_lib::CHROME,
+ rlz_lib::CHROME_HOME_PAGE,
+ rlz_lib::FIRST_SEARCH);
+ }
+}
+
+bool SendFinancialPing(const std::wstring& brand,
+ const std::wstring& lang,
+ const std::wstring& referral,
+ bool exclude_id) {
rlz_lib::AccessPoint points[] = {rlz_lib::CHROME_OMNIBOX,
rlz_lib::CHROME_HOME_PAGE,
rlz_lib::NO_ACCESS_POINT};
@@ -57,7 +112,7 @@
// If chrome has been reactivated, send a ping for this brand as well.
// We ignore the return value of SendFinancialPing() since we'll try again
- // later anyway. Callers of this function are only interested in whether
+ // later anyway. Callers of this function are only interested in whether
// the ping for the main brand succeeded or not.
std::wstring reactivation_brand;
if (GoogleUpdateSettings::GetReactivationBrand(&reactivation_brand)) {
@@ -74,248 +129,196 @@
lang_ascii.c_str(), exclude_id, NULL, true);
}
-// This class leverages the AutocompleteEditModel notification to know when
-// the user first interacted with the omnibox and set a global accordingly.
-class OmniBoxUsageObserver : public NotificationObserver {
- public:
- OmniBoxUsageObserver(bool first_run, bool send_ping_immediately,
- bool google_default_search)
- : first_run_(first_run),
- send_ping_immediately_(send_ping_immediately),
- google_default_search_(google_default_search) {
- registrar_.Add(this, chrome::NOTIFICATION_OMNIBOX_OPENED_URL,
- NotificationService::AllSources());
- // If instant is enabled we'll start searching as soon as the user starts
- // typing in the omnibox (which triggers INSTANT_CONTROLLER_UPDATED).
- registrar_.Add(this, chrome::NOTIFICATION_INSTANT_CONTROLLER_UPDATED,
- NotificationService::AllSources());
- omnibox_used_ = false;
- DCHECK(!instance_);
- instance_ = this;
- }
+} // namespace
- virtual void Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details);
+RLZTracker* RLZTracker::tracker_ = NULL;
- static bool used() {
- return omnibox_used_;
- }
+// static
+RLZTracker* RLZTracker::GetInstance() {
+ return tracker_ ? tracker_ : Singleton<RLZTracker>::get();
+}
- // Deletes the single instance of OmniBoxUsageObserver.
- static void DeleteInstance() {
- delete instance_;
- }
+RLZTracker::RLZTracker()
+ : first_run_(false),
+ send_ping_immediately_(false),
+ google_default_search_(false),
+ already_ran_(false),
+ omnibox_used_(false),
+ homepage_used_(false) {
+}
- private:
- // Dtor is private so the object cannot be created on the stack.
- ~OmniBoxUsageObserver() {
- instance_ = NULL;
- }
+RLZTracker::~RLZTracker() {
+}
- static bool omnibox_used_;
+bool RLZTracker::InitRlzDelayed(bool first_run, int delay,
+ bool google_default_search,
+ bool google_default_homepage) {
+ return GetInstance()->Init(first_run, delay, google_default_search,
+ google_default_homepage);
+}
- // There should only be one instance created at a time, and instance_ points
- // to that instance.
- // NOTE: this is only non-null for the amount of time it is needed. Once the
- // instance_ is no longer needed (or Chrome is exiting), this is null.
- static OmniBoxUsageObserver* instance_;
+bool RLZTracker::Init(bool first_run, int delay, bool google_default_search,
+ bool google_default_homepage) {
+ first_run_ = first_run;
+ google_default_search_ = google_default_search;
+ google_default_homepage_ = google_default_homepage;
- NotificationRegistrar registrar_;
- bool first_run_;
- bool send_ping_immediately_;
- bool google_default_search_;
-};
-
-bool OmniBoxUsageObserver::omnibox_used_ = false;
-OmniBoxUsageObserver* OmniBoxUsageObserver::instance_ = NULL;
-
-// This task is run in the file thread, so to not block it for a long time
-// we use a throwaway thread to do the blocking url request.
-class DailyPingTask : public Task {
- public:
- virtual ~DailyPingTask() {
+ // A negative delay means that a financial ping should be sent immediately
+ // after a first search is recorded, without waiting for the next restart
+ // of chrome. However, we only want this behaviour on first run.
+ send_ping_immediately_ = false;
+ if (delay < 0) {
+ send_ping_immediately_ = true;
+ delay = -delay;
}
- virtual void Run() {
- // We use a transient thread because we have no guarantees about
- // how long the RLZ lib can block us.
- _beginthread(PingNow, 0, NULL);
- }
- private:
- // Causes a ping to the server using WinInet.
- static void _cdecl PingNow(void*) {
- // Needs to be evaluated. See http://crbug.com/62328.
- base::ThreadRestrictions::ScopedAllowIO allow_io;
+ // Maximum and minimum delay we would allow to be set through master
+ // preferences. Somewhat arbitrary, may need to be adjusted in future.
+ const int kMaxDelay = 200 * 1000;
+ const int kMinDelay = 20 * 1000;
- std::wstring lang;
- GoogleUpdateSettings::GetLanguage(&lang);
- if (lang.empty())
- lang = L"en";
- std::wstring brand;
- GoogleUpdateSettings::GetBrand(&brand);
- std::wstring referral;
- GoogleUpdateSettings::GetReferral(&referral);
- if (SendFinancialPing(brand, lang, referral, is_organic(brand))) {
- base::AutoLock lock(rlz_lock);
- access_values_state = ACCESS_VALUES_STALE;
- GoogleUpdateSettings::ClearReferral();
- }
- }
+ delay *= 1000;
+ delay = (delay < kMinDelay) ? kMinDelay : delay;
+ delay = (delay > kMaxDelay) ? kMaxDelay : delay;
- // Organic brands all start with GG, such as GGCM.
- static bool is_organic(const std::wstring& brand) {
- return (brand.size() < 2) ? false : (brand.substr(0, 2) == L"GG");
- }
-};
+ // Register for notifications from the omnibox so that we can record when
+ // the user performs a first search.
+ registrar_.Add(this, chrome::NOTIFICATION_OMNIBOX_OPENED_URL,
+ NotificationService::AllSources());
+ // If instant is enabled we'll start searching as soon as the user starts
+ // typing in the omnibox (which triggers INSTANT_CONTROLLER_UPDATED).
+ registrar_.Add(this, chrome::NOTIFICATION_INSTANT_CONTROLLER_UPDATED,
+ NotificationService::AllSources());
-// Performs late RLZ initialization and RLZ event recording for chrome.
-// This task needs to run on the UI thread.
-class DelayedInitTask : public Task {
- public:
- DelayedInitTask(bool first_run, bool google_default_search)
- : first_run_(first_run),
- google_default_search_(google_default_search) {
- }
- virtual ~DelayedInitTask() {
- }
- virtual void Run() {
- // For non-interactive tests we don't do the rest of the initialization
- // because sometimes the very act of loading the dll causes QEMU to crash.
- if (::GetEnvironmentVariableW(ASCIIToWide(env_vars::kHeadless).c_str(),
- NULL, 0)) {
- return;
- }
- // For organic brandcodes do not use rlz at all. Empty brandcode usually
- // means a chromium install. This is ok.
- std::wstring brand;
- if (!GoogleUpdateSettings::GetBrand(&brand) || brand.empty() ||
- GoogleUpdateSettings::IsOrganic(brand))
- return;
+ // Register for notifications from navigations, to see if the user has used
+ // the home page.
+ registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_PENDING,
+ NotificationService::AllSources());
- RecordProductEvents(first_run_, google_default_search_, already_ran_);
+ ScheduleDelayedInit(delay);
+ return true;
+}
- // If chrome has been reactivated, record the events for this brand
- // as well.
- std::wstring reactivation_brand;
- if (GoogleUpdateSettings::GetReactivationBrand(&reactivation_brand)) {
- rlz_lib::SupplementaryBranding branding(reactivation_brand.c_str());
- RecordProductEvents(first_run_, google_default_search_, already_ran_);
- }
+void RLZTracker::ScheduleDelayedInit(int delay) {
+ BrowserThread::PostDelayedTask(
+ BrowserThread::FILE,
+ FROM_HERE,
+ NewRunnableMethod(this, &RLZTracker::DelayedInit),
+ delay);
+}
- already_ran_ = true;
+void RLZTracker::DelayedInit() {
+ // For organic brandcodes do not use rlz at all. Empty brandcode usually
+ // means a chromium install. This is ok.
+ std::wstring brand;
+ if (!GoogleUpdateSettings::GetBrand(&brand) || brand.empty() ||
+ GoogleUpdateSettings::IsOrganic(brand))
+ return;
- // Schedule the daily RLZ ping.
- MessageLoop::current()->PostTask(FROM_HERE, new DailyPingTask());
- }
+ RecordProductEvents(first_run_, google_default_search_,
+ google_default_homepage_, already_ran_,
+ omnibox_used_, homepage_used_);
- private:
- static void RecordProductEvents(bool first_run, bool google_default_search,
- bool already_ran) {
- // Record the installation of chrome. We call this all the time but the rlz
- // lib should ingore all but the first one.
- rlz_lib::RecordProductEvent(rlz_lib::CHROME,
- rlz_lib::CHROME_OMNIBOX,
- rlz_lib::INSTALL);
- rlz_lib::RecordProductEvent(rlz_lib::CHROME,
- rlz_lib::CHROME_HOME_PAGE,
- rlz_lib::INSTALL);
-
- // Do the initial event recording if is the first run or if we have an
- // empty rlz which means we haven't got a chance to do it.
- char omnibox_rlz[rlz_lib::kMaxRlzLength + 1];
- if (!rlz_lib::GetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, omnibox_rlz,
- rlz_lib::kMaxRlzLength, NULL)) {
- omnibox_rlz[0] = 0;
- }
-
- // Record if google is the initial search provider.
- if ((first_run || omnibox_rlz[0] == 0) && google_default_search &&
- !already_ran) {
- rlz_lib::RecordProductEvent(rlz_lib::CHROME,
- rlz_lib::CHROME_OMNIBOX,
- rlz_lib::SET_TO_GOOGLE);
- }
-
- // Record first user interaction with the omnibox. We call this all the
- // time but the rlz lib should ingore all but the first one.
- if (OmniBoxUsageObserver::used()) {
- rlz_lib::RecordProductEvent(rlz_lib::CHROME,
- rlz_lib::CHROME_OMNIBOX,
- rlz_lib::FIRST_SEARCH);
- }
+ // If chrome has been reactivated, record the events for this brand
+ // as well.
+ std::wstring reactivation_brand;
+ if (GoogleUpdateSettings::GetReactivationBrand(&reactivation_brand)) {
+ rlz_lib::SupplementaryBranding branding(reactivation_brand.c_str());
+ RecordProductEvents(first_run_, google_default_search_,
+ google_default_homepage_, already_ran_,
+ omnibox_used_, homepage_used_);
}
- // Flag that remembers if the delayed task already ran or not. This is
- // needed only in the first_run case, since we don't want to record the
- // set-to-google event more than once. We need to worry about this event
- // (and not the others) because it is not a stateful RLZ event.
- static bool already_ran_;
+ already_ran_ = true;
- bool first_run_;
+ ScheduleFinancialPing();
+}
- // True if Google is the default search engine for the first profile starting
- // in a browser during first run.
- bool google_default_search_;
+void RLZTracker::ScheduleFinancialPing() {
+ _beginthread(PingNow, 0, this);
+}
-};
+// static
+void _cdecl RLZTracker::PingNow(void* arg) {
+ RLZTracker* tracker = reinterpret_cast<RLZTracker*>(arg);
+ tracker->PingNowImpl();
+}
-bool DelayedInitTask::already_ran_ = false;
-
-void OmniBoxUsageObserver::Observe(int type,
- const NotificationSource& source,
- const NotificationDetails& details) {
+void RLZTracker::PingNowImpl() {
// Needs to be evaluated. See http://crbug.com/62328.
base::ThreadRestrictions::ScopedAllowIO allow_io;
- // Try to record event now, else set the flag to try later when we
- // attempt the ping.
- if (!RLZTracker::RecordProductEvent(rlz_lib::CHROME,
- rlz_lib::CHROME_OMNIBOX,
- rlz_lib::FIRST_SEARCH))
- omnibox_used_ = true;
- else if (send_ping_immediately_) {
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE, new DelayedInitTask(first_run_,
- google_default_search_));
+ std::wstring lang;
+ GoogleUpdateSettings::GetLanguage(&lang);
+ if (lang.empty())
+ lang = L"en";
+ std::wstring brand;
+ GoogleUpdateSettings::GetBrand(&brand);
+ std::wstring referral;
+ GoogleUpdateSettings::GetReferral(&referral);
+ if (SendFinancialPing(brand, lang, referral, is_organic(brand))) {
+ GoogleUpdateSettings::ClearReferral();
+ base::AutoLock lock(cache_lock_);
+ rlz_cache_.clear();
}
+}
- delete this;
+bool RLZTracker::SendFinancialPing(const std::wstring& brand,
+ const std::wstring& lang,
+ const std::wstring& referral,
+ bool exclude_id) {
+ return ::SendFinancialPing(brand, lang, referral, exclude_id);
}
-} // namespace
+void RLZTracker::Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ // Needs to be evaluated. See http://crbug.com/62328.
+ base::ThreadRestrictions::ScopedAllowIO allow_io;
-bool RLZTracker::InitRlzDelayed(bool first_run, int delay,
- bool google_default_search) {
- // A negative delay means that a financial ping should be sent immediately
- // after a first search is recorded, without waiting for the next restart
- // of chrome. However, we only want this behaviour on first run.
- bool send_ping_immediately = false;
- if (delay < 0) {
- send_ping_immediately = true;
- delay = -delay;
- }
+ rlz_lib::AccessPoint point;
+ bool* record_used = NULL;
+ bool call_record = false;
- // Maximum and minimum delay we would allow to be set through master
- // preferences. Somewhat arbitrary, may need to be adjusted in future.
- const int kMaxDelay = 200 * 1000;
- const int kMinDelay = 20 * 1000;
+ switch (type) {
+ case chrome::NOTIFICATION_OMNIBOX_OPENED_URL:
+ case chrome::NOTIFICATION_INSTANT_CONTROLLER_UPDATED:
+ point = rlz_lib::CHROME_OMNIBOX;
+ record_used = &omnibox_used_;
+ call_record = true;
- delay *= 1000;
- delay = (delay < kMinDelay) ? kMinDelay : delay;
- delay = (delay > kMaxDelay) ? kMaxDelay : delay;
+ registrar_.Remove(this, chrome::NOTIFICATION_OMNIBOX_OPENED_URL,
+ NotificationService::AllSources());
+ registrar_.Remove(this, chrome::NOTIFICATION_INSTANT_CONTROLLER_UPDATED,
+ NotificationService::AllSources());
+ break;
+ case content::NOTIFICATION_NAV_ENTRY_PENDING: {
+ const NavigationEntry* entry = Details<NavigationEntry>(details).ptr();
+ if (entry != NULL &&
+ ((entry->transition_type() & RLZ_PAGETRANSITION_HOME_PAGE) != 0)) {
+ point = rlz_lib::CHROME_HOME_PAGE;
+ record_used = &homepage_used_;
+ call_record = true;
- if (!OmniBoxUsageObserver::used())
- new OmniBoxUsageObserver(first_run, send_ping_immediately,
- google_default_search);
+ registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_PENDING,
+ NotificationService::AllSources());
+ }
+ break;
+ }
+ default:
+ NOTREACHED();
+ break;
+ }
- // Schedule the delayed init items.
- BrowserThread::PostDelayedTask(
- BrowserThread::FILE,
- FROM_HERE,
- new DelayedInitTask(first_run, google_default_search),
- delay);
- return true;
+ if (call_record) {
+ // Try to record event now, else set the flag to try later when we
+ // attempt the ping.
+ if (!RecordProductEvent(rlz_lib::CHROME, point, rlz_lib::FIRST_SEARCH))
+ *record_used = true;
+ else if (send_ping_immediately_ && point == rlz_lib::CHROME_OMNIBOX) {
+ ScheduleDelayedInit(0);
+ }
+ }
}
bool RLZTracker::RecordProductEvent(rlz_lib::Product product,
@@ -333,52 +336,59 @@
return ret;
}
-// We implement caching of the answer of get_access_point() if the request
-// is for CHROME_OMNIBOX. If we had a successful ping, then we update the
-// cached value.
-
+// GetAccessPointRlz() caches RLZ strings for all access points. If we had
+// a successful ping, then we update the cached value.
bool RLZTracker::GetAccessPointRlz(rlz_lib::AccessPoint point,
std::wstring* rlz) {
- static std::wstring cached_ommibox_rlz;
- if (rlz_lib::CHROME_OMNIBOX == point) {
- base::AutoLock lock(rlz_lock);
- if (access_values_state == ACCESS_VALUES_FRESH) {
- *rlz = cached_ommibox_rlz;
+ return GetInstance()->GetAccessPointRlzImpl(point, rlz);
+}
+
+// GetAccessPointRlz() caches RLZ strings for all access points. If we had
+// a successful ping, then we update the cached value.
+bool RLZTracker::GetAccessPointRlzImpl(rlz_lib::AccessPoint point,
+ std::wstring* rlz) {
+ // If the RLZ string for the specified access point is already cached,
+ // simply return its value.
+ {
+ base::AutoLock lock(cache_lock_);
+ if (rlz_cache_.find(point) != rlz_cache_.end()) {
+ if (rlz)
+ *rlz = rlz_cache_[point];
return true;
}
}
- // Make sure we don't access disk outside of the file context.
+ // Make sure we don't access disk outside of the I/O thread.
// In such case we repost the task on the right thread and return error.
- if (!BrowserThread::CurrentlyOn(BrowserThread::FILE)) {
- // Caching of access points is now only implemented for the CHROME_OMNIBOX.
- // Thus it is not possible to call this function on another thread for
- // other access points until proper caching for these has been implemented
- // and the code that calls this function can handle synchronous fetching
- // of the access point.
- DCHECK_EQ(rlz_lib::CHROME_OMNIBOX, point);
+ if (ScheduleGetAccessPointRlz(point))
+ return false;
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- NewRunnableFunction(&RLZTracker::GetAccessPointRlz,
- point, &cached_ommibox_rlz));
- rlz->erase();
- return false;
- }
-
char str_rlz[rlz_lib::kMaxRlzLength + 1];
if (!rlz_lib::GetAccessPointRlz(point, str_rlz, rlz_lib::kMaxRlzLength, NULL))
return false;
- *rlz = ASCIIToWide(std::string(str_rlz));
- if (rlz_lib::CHROME_OMNIBOX == point) {
- base::AutoLock lock(rlz_lock);
- cached_ommibox_rlz.assign(*rlz);
- access_values_state = ACCESS_VALUES_FRESH;
- }
+
+ std::wstring rlz_local(ASCIIToWide(std::string(str_rlz)));
+ if (rlz)
+ *rlz = rlz_local;
+
+ base::AutoLock lock(cache_lock_);
+ rlz_cache_[point] = rlz_local;
return true;
}
+bool RLZTracker::ScheduleGetAccessPointRlz(rlz_lib::AccessPoint point) {
+ if (BrowserThread::CurrentlyOn(BrowserThread::FILE))
+ return false;
+
+ std::wstring* not_used = NULL;
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ NewRunnableFunction(&RLZTracker::GetAccessPointRlz, point, not_used));
+ return true;
+}
+
// static
void RLZTracker::CleanupRlz() {
- OmniBoxUsageObserver::DeleteInstance();
+ GetInstance()->rlz_cache_.clear();
+ GetInstance()->registrar_.RemoveAll();
}
« no previous file with comments | « chrome/browser/rlz/rlz.h ('k') | chrome/browser/rlz/rlz_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698