// 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 COMPONENTS_RLZ_RLZ_TRACKER_H_ #define COMPONENTS_RLZ_RLZ_TRACKER_H_ #include #include #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" #include "base/memory/singleton.h" #include "base/strings/string16.h" #include "base/threading/sequenced_worker_pool.h" #include "base/time/time.h" #include "rlz/lib/rlz_lib.h" namespace net { class URLRequestContextGetter; } namespace rlz { class RLZTrackerDelegate; // 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: // Sets the RLZTrackerDelegate that should be used by the global RLZTracker // instance. Must be called before calling any other method of RLZTracker. static void SetRlzDelegate(scoped_ptr delegate); // 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 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); // Records an RLZ event. Some events can be access point independent. // Returns false it the event could not be recorded. Requires write access // to the HKCU registry hive on windows. static bool RecordProductEvent(rlz_lib::Product product, rlz_lib::AccessPoint point, rlz_lib::Event event_id); // For the point parameter of RecordProductEvent. static rlz_lib::AccessPoint ChromeOmnibox(); #if !defined(OS_IOS) static rlz_lib::AccessPoint ChromeHomePage(); static rlz_lib::AccessPoint ChromeAppList(); #endif // 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: \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, base::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 InitRlzDelayed. For testing only. static void EnableZeroDelayForTesting(); #if !defined(OS_IOS) // Records that the app list search has been used. static void RecordAppListSearch(); #endif // The following methods are made protected so that they can be used for // testing purposes. Production code should never need to call these. protected: RLZTracker(); virtual ~RLZTracker(); // Performs initialization of RLZ tracker that is purposefully delayed so // that it does not interfere with chrome startup time. virtual void DelayedInit(); // Used by test code to override the default RLZTracker instance returned // by GetInstance(). void set_tracker(RLZTracker* tracker) { tracker_ = tracker; } // 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 PingNowImpl(); private: friend struct DefaultSingletonTraits; friend class base::RefCountedThreadSafe; // Implementation called from SetRlzDelegate() static method. void SetDelegate(scoped_ptr delegate); // Implementation called from InitRlzDelayed() static method. bool Init(bool first_run, bool send_ping_immediately, base::TimeDelta delay, bool is_google_default_search, bool is_google_homepage, bool is_google_in_startpages); // Implementation called from CleanupRlz static method. void Cleanup(); // Implementation called from RecordProductEvent() static method. bool RecordProductEventImpl(rlz_lib::Product product, rlz_lib::AccessPoint point, rlz_lib::Event event_id); // Records FIRST_SEARCH event. Passed as bound callback to RLZTrackerDelegate. void RecordFirstSearch(rlz_lib::AccessPoint point); // Implementation called from GetAccessPointRlz() static method. bool GetAccessPointRlzImpl(rlz_lib::AccessPoint point, base::string16* rlz); // Schedules the delayed initialization. This method is virtual to allow // tests to override how the scheduling is done. virtual 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. virtual bool 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. virtual bool 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. virtual void ScheduleFinancialPing(); // 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. virtual bool ScheduleGetAccessPointRlz(rlz_lib::AccessPoint point); // 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 base::string16& lang, const base::string16& referral); #if defined(OS_CHROMEOS) // Implementation called from ClearRlzState static method. void ClearRlzStateImpl(); // Schedules a call to ClearRlzStateImpl(). This method is virtual // to allow tests to override how the scheduling is done. virtual bool ScheduleClearRlzState(); #endif // Returns a pointer to the bool corresponding to whether |point| has been // used but not reported. bool* GetAccessPointRecord(rlz_lib::AccessPoint point); // Tracker used for testing purposes only. If this value is non-NULL, it // will be returned from GetInstance() instead of the regular singleton. static RLZTracker* tracker_; // Delegate abstracting embedder specific knowledge. Must not be null. scoped_ptr delegate_; // 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 IO thread for reading and/or writing. base::Lock cache_lock_; std::map rlz_cache_; // Keeps track of whether the omnibox, home page or app list have been used. bool omnibox_used_; bool homepage_used_; bool app_list_used_; // Main and (optionally) reactivation brand codes, assigned on UI thread. std::string brand_; std::string reactivation_brand_; // Minimum delay before sending financial ping after initialization. base::TimeDelta min_init_delay_; DISALLOW_COPY_AND_ASSIGN(RLZTracker); }; } // namespace rlz #endif // COMPONENTS_RLZ_RLZ_TRACKER_H_