blob: 517bb7d8835e6ff4a3f1aee948bb587708089b5d [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_RLZ_RLZ_H_
#define CHROME_BROWSER_RLZ_RLZ_H_
#include "build/build_config.h"
#if defined(ENABLE_RLZ)
#include <map>
#include <string>
#include "base/basictypes.h"
#include "base/gtest_prod_util.h"
#include "base/memory/singleton.h"
#include "base/strings/string16.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/time/time.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "rlz/lib/rlz_lib.h"
class Profile;
namespace net {
class URLRequestContextGetter;
}
// An interface to provide financial ping implementation.
class RLZTrackerDelegate {
public:
// Sends the financial ping to the RLZ servers. This method is virtual to
// allow tests to override.
virtual bool SendFinancialPing(const std::string& brand,
const string16& lang,
const string16& referral) = 0;
};
// RLZ is a library which is used to measure distribution scenarios.
// Its job is to record certain lifetime events in the registry and to send
// them encoded as a compact string at most twice. The sent data does
// not contain information that can be used to identify a user or to infer
// browsing habits. The API in this file is a wrapper around the open source
// RLZ library which can be found at http://code.google.com/p/rlz.
//
// For partner or bundled installs, the RLZ might send more information
// according to the terms disclosed in the EULA.
class RLZTracker : public content::NotificationObserver,
public RLZTrackerDelegate {
public:
// Initializes the RLZ library services for use in chrome. Schedules a delayed
// task that performs the ping and registers some events when 'first-run' is
// true.
//
// When |send_ping_immediately| is true, a financial ping should be sent
// immediately after a first search is recorded, without waiting for |delay|.
// However, we only want this behaviour on first run.
//
// If the chrome brand is organic (no partners) then the pings don't occur.
static bool InitRlzFromProfileDelayed(Profile* profile,
bool first_run,
bool send_ping_immediately,
base::TimeDelta delay);
// Records an RLZ event. Some events can be access point independent.
// Requires write access to the HKCU registry hive on windows.
static void RecordProductEvent(rlz_lib::Product product,
rlz_lib::AccessPoint point,
rlz_lib::Event event_id);
// For the point parameter of RecordProductEvent.
static const rlz_lib::AccessPoint CHROME_OMNIBOX;
static const rlz_lib::AccessPoint CHROME_HOME_PAGE;
// Gets the HTTP header value that can be added to requests from the
// specific access point. The string returned is of the form:
//
// "X-Rlz-String: <access-point-rlz>\r\n"
//
static std::string GetAccessPointHttpHeader(rlz_lib::AccessPoint point);
// Gets the RLZ value of the access point.
// Returns false if the rlz string could not be obtained. In some cases
// an empty string can be returned which is not an error.
static bool GetAccessPointRlz(rlz_lib::AccessPoint point, string16* rlz);
// Invoked during shutdown to clean up any state created by RLZTracker.
static void CleanupRlz();
#if defined(OS_CHROMEOS)
// Clears all product state. Should be called when turning RLZ off. On other
// platforms, this is done by product uninstaller.
static void ClearRlzState();
#endif
// This method is public for use by the Singleton class.
static RLZTracker* GetInstance();
// Enables zero delay for InitRlzFromProfileDelayed. For testing only.
static void EnableZeroDelayForTesting();
private:
friend class RlzLibTest;
friend class TestRLZTrackerDelegate;
friend class base::RefCountedThreadSafe<RLZTracker>;
friend struct DefaultSingletonTraits<RLZTracker>;
FRIEND_TEST_ALL_PREFIXES(RlzLibTest, GetAccessPointRlzIsCached);
FRIEND_TEST_ALL_PREFIXES(RlzLibTest, ObserveHandlesBadArgs);
FRIEND_TEST_ALL_PREFIXES(RlzLibTest, PingUpdatesRlzCache);
// Called by InitRlzFromProfileDelayed with values taken from |profile|.
static bool InitRlzDelayed(bool first_run,
bool send_ping_immediately,
base::TimeDelta delay,
bool is_google_default_search,
bool is_google_homepage,
bool is_google_in_startpages);
// Used by test code to override the default RLZTracker instance returned
// by GetInstance().
static void SetTrackerForTest(RLZTracker* tracker);
RLZTracker();
explicit RLZTracker(RLZTrackerDelegate* delegate);
virtual ~RLZTracker();
// Performs initialization of RLZ tracker that is purposefully delayed so
// that it does not interfere with chrome startup time.
void DelayedInit();
// Sends the financial ping to the RLZ servers and invalidates the RLZ string
// cache since the response from the RLZ server may have changed then.
// Protected so that its accessible from tests.
void SendFinancialPingNow();
// Implementation called from InitRlzDelayed() static method.
bool Init(bool first_run,
bool send_ping_immediately,
base::TimeDelta delay,
bool google_default_search,
bool google_default_homepage,
bool is_google_in_startpages);
// Gets the cached accesspoint rlz. Returns false if the cache doesn't exist.
bool GetCachedAccessPointRlz(rlz_lib::AccessPoint point, string16* rlz);
#if defined(OS_CHROMEOS)
// Implementation called from ClearRlzState static method.
void ClearRlzStateImpl();
#endif
// Schedules the delayed initialization. This method is virtual to allow
// tests to override how the scheduling is done.
void ScheduleDelayedInit(base::TimeDelta delay);
// Schedules a call to rlz_lib::RecordProductEvent(). This method is virtual
// to allow tests to override how the scheduling is done.
void ScheduleRecordProductEvent(rlz_lib::Product product,
rlz_lib::AccessPoint point,
rlz_lib::Event event_id);
// Schedules a call to rlz_lib::RecordFirstSearch(). This method is virtual
// to allow tests to override how the scheduling is done.
void ScheduleRecordFirstSearch(rlz_lib::AccessPoint point);
// Schedules a call to rlz_lib::SendFinancialPing(). This method is virtual
// to allow tests to override how the scheduling is done.
void ScheduleSendFinancialPing();
// Schedules a call to GetAccessPointRlz() on the I/O thread if the current
// thread is not already the I/O thread, otherwise does nothing. Returns
// true if the call was scheduled, and false otherwise. This method is
// virtual to allow tests to override how the scheduling is done.
void ScheduleGetAccessPointRlz(rlz_lib::AccessPoint point);
#if defined(OS_CHROMEOS)
// Schedules a call to ClearRlzStateImpl().
void ScheduleClearRlzState();
#endif
// Implementation called from RecordProductEvent() static method
// on SequencedWorkerPool.
bool RecordProductEventImpl(rlz_lib::Product product,
rlz_lib::AccessPoint point,
rlz_lib::Event event_id);
// Records FIRST_SEARCH event. Scheduled on SequencedWorkerPool
// in Observe.
void RecordFirstSearchImpl(rlz_lib::AccessPoint point);
// Implementation of GetAccessPointRlz() invoked on SequencedWorkerPool.
// This caches RLZ strings for all access points. If we had
// a successful ping, then we update the cached value.
void GetAccessPointRlzImpl(rlz_lib::AccessPoint point);
void Cleanup();
// Overridden from RZLTrackerDelegate:
virtual bool SendFinancialPing(const std::string& brand,
const string16& lang,
const string16& referral) OVERRIDE;
// content::NotificationObserver implementation:
virtual void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE;
// Configuation data for RLZ tracker. Set by call to Init().
bool first_run_;
bool send_ping_immediately_;
bool is_google_default_search_;
bool is_google_homepage_;
bool is_google_in_startpages_;
// Unique sequence token so that tasks posted by RLZTracker are executed
// sequentially in the blocking pool.
base::SequencedWorkerPool::SequenceToken worker_pool_token_;
// Keeps track if the RLZ tracker has already performed its delayed
// initialization.
bool already_ran_;
// Keeps a cache of RLZ access point strings, since they rarely
// change. The cache must be protected by a lock since it may be
// accessed from the UI thread for reading and the global blocking
// pool for reading and/or writing.
base::Lock cache_lock_;
std::map<rlz_lib::AccessPoint, string16> rlz_cache_;
// Keeps track of whether the omnibox or host page have been used.
bool omnibox_used_;
bool homepage_used_;
// Main and (optionally) reactivation brand codes, assigned on UI thread.
std::string brand_;
std::string reactivation_brand_;
content::NotificationRegistrar registrar_;
RLZTrackerDelegate* delegate_; // not owned.
// Minimum delay before sending financial ping after initialization.
base::TimeDelta min_init_delay_;
DISALLOW_COPY_AND_ASSIGN(RLZTracker);
};
#endif // defined(ENABLE_RLZ)
#endif // CHROME_BROWSER_RLZ_RLZ_H_