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#ifndef CHROME_BROWSER_RLZ_RLZ_H_ 6#define CHROME_BROWSER_RLZ_RLZ_H_ 7 8#include "build/build_config.h" 9 10#if defined(ENABLE_RLZ) 11 12#include <map> 13#include <string> 14 15#include "base/basictypes.h" 16#include "base/memory/singleton.h" 17#include "base/strings/string16.h" 18#include "base/threading/sequenced_worker_pool.h" 19#include "base/time/time.h" 20#include "content/public/browser/notification_observer.h" 21#include "content/public/browser/notification_registrar.h" 22#include "rlz/lib/rlz_lib.h" 23 24class Profile; 25namespace net { 26class URLRequestContextGetter; 27} 28 29// RLZ is a library which is used to measure distribution scenarios. 30// Its job is to record certain lifetime events in the registry and to send 31// them encoded as a compact string at most twice. The sent data does 32// not contain information that can be used to identify a user or to infer 33// browsing habits. The API in this file is a wrapper around the open source 34// RLZ library which can be found at http://code.google.com/p/rlz. 35// 36// For partner or bundled installs, the RLZ might send more information 37// according to the terms disclosed in the EULA. 38 39class RLZTracker : public content::NotificationObserver { 40 public: 41 // Initializes the RLZ library services for use in chrome. Schedules a delayed 42 // task that performs the ping and registers some events when 'first-run' is 43 // true. 44 // 45 // When |send_ping_immediately| is true, a financial ping should be sent 46 // immediately after a first search is recorded, without waiting for |delay|. 47 // However, we only want this behaviour on first run. 48 // 49 // If the chrome brand is organic (no partners) then the pings don't occur. 50 static bool InitRlzFromProfileDelayed(Profile* profile, 51 bool first_run, 52 bool send_ping_immediately, 53 base::TimeDelta delay); 54 55 // Records an RLZ event. Some events can be access point independent. 56 // Returns false it the event could not be recorded. Requires write access 57 // to the HKCU registry hive on windows. 58 static bool RecordProductEvent(rlz_lib::Product product, 59 rlz_lib::AccessPoint point, 60 rlz_lib::Event event_id); 61 62 // For the point parameter of RecordProductEvent. 63 static rlz_lib::AccessPoint ChromeOmnibox(); 64#if !defined(OS_IOS) 65 static rlz_lib::AccessPoint ChromeHomePage(); 66 static rlz_lib::AccessPoint ChromeAppList(); 67#endif 68 69 // Gets the HTTP header value that can be added to requests from the 70 // specific access point. The string returned is of the form: 71 // 72 // "X-Rlz-String: <access-point-rlz>\r\n" 73 // 74 static std::string GetAccessPointHttpHeader(rlz_lib::AccessPoint point); 75 76 // Gets the RLZ value of the access point. 77 // Returns false if the rlz string could not be obtained. In some cases 78 // an empty string can be returned which is not an error. 79 static bool GetAccessPointRlz(rlz_lib::AccessPoint point, 80 base::string16* rlz); 81 82 // Invoked during shutdown to clean up any state created by RLZTracker. 83 static void CleanupRlz(); 84 85#if defined(OS_CHROMEOS) 86 // Clears all product state. Should be called when turning RLZ off. On other 87 // platforms, this is done by product uninstaller. 88 static void ClearRlzState(); 89#endif 90 91 // This method is public for use by the Singleton class. 92 static RLZTracker* GetInstance(); 93 94 // Enables zero delay for InitRlzFromProfileDelayed. For testing only. 95 static void EnableZeroDelayForTesting(); 96 97#if !defined(OS_IOS) 98 // Records that the app list search has been used. 99 static void RecordAppListSearch(); 100#endif 101 102 // The following methods are made protected so that they can be used for 103 // testing purposes. Production code should never need to call these. 104 protected: 105 RLZTracker(); 106 virtual ~RLZTracker(); 107 108 // Called by InitRlzFromProfileDelayed with values taken from |profile|. 109 static bool InitRlzDelayed(bool first_run, 110 bool send_ping_immediately, 111 base::TimeDelta delay, 112 bool is_google_default_search, 113 bool is_google_homepage, 114 bool is_google_in_startpages); 115 116 // Performs initialization of RLZ tracker that is purposefully delayed so 117 // that it does not interfere with chrome startup time. 118 virtual void DelayedInit(); 119 120 // content::NotificationObserver implementation: 121 virtual void Observe(int type, 122 const content::NotificationSource& source, 123 const content::NotificationDetails& details) OVERRIDE; 124 125 // Used by test code to override the default RLZTracker instance returned 126 // by GetInstance(). 127 void set_tracker(RLZTracker* tracker) { 128 tracker_ = tracker; 129 } 130 131 // Sends the financial ping to the RLZ servers and invalidates the RLZ string 132 // cache since the response from the RLZ server may have changed then. 133 // Protected so that its accessible from tests. 134 void PingNowImpl(); 135 136 private: 137 friend struct DefaultSingletonTraits<RLZTracker>; 138 friend class base::RefCountedThreadSafe<RLZTracker>; 139 140 // Implementation called from InitRlzDelayed() static method. 141 bool Init(bool first_run, 142 bool send_ping_immediately, 143 base::TimeDelta delay, 144 bool google_default_search, 145 bool google_default_homepage, 146 bool is_google_in_startpages); 147 148 // Implementation called from RecordProductEvent() static method. 149 bool RecordProductEventImpl(rlz_lib::Product product, 150 rlz_lib::AccessPoint point, 151 rlz_lib::Event event_id); 152 153 // Records FIRST_SEARCH event. Called from Observe() on blocking task runner. 154 void RecordFirstSearch(rlz_lib::AccessPoint point); 155 156 // Implementation called from GetAccessPointRlz() static method. 157 bool GetAccessPointRlzImpl(rlz_lib::AccessPoint point, base::string16* rlz); 158 159 // Schedules the delayed initialization. This method is virtual to allow 160 // tests to override how the scheduling is done. 161 virtual void ScheduleDelayedInit(base::TimeDelta delay); 162 163 // Schedules a call to rlz_lib::RecordProductEvent(). This method is virtual 164 // to allow tests to override how the scheduling is done. 165 virtual bool ScheduleRecordProductEvent(rlz_lib::Product product, 166 rlz_lib::AccessPoint point, 167 rlz_lib::Event event_id); 168 169 // Schedules a call to rlz_lib::RecordFirstSearch(). This method is virtual 170 // to allow tests to override how the scheduling is done. 171 virtual bool ScheduleRecordFirstSearch(rlz_lib::AccessPoint point); 172 173 // Schedules a call to rlz_lib::SendFinancialPing(). This method is virtual 174 // to allow tests to override how the scheduling is done. 175 virtual void ScheduleFinancialPing(); 176 177 // Schedules a call to GetAccessPointRlz() on the I/O thread if the current 178 // thread is not already the I/O thread, otherwise does nothing. Returns 179 // true if the call was scheduled, and false otherwise. This method is 180 // virtual to allow tests to override how the scheduling is done. 181 virtual bool ScheduleGetAccessPointRlz(rlz_lib::AccessPoint point); 182 183 // Sends the financial ping to the RLZ servers. This method is virtual to 184 // allow tests to override. 185 virtual bool SendFinancialPing(const std::string& brand, 186 const base::string16& lang, 187 const base::string16& referral); 188 189#if defined(OS_CHROMEOS) 190 // Implementation called from ClearRlzState static method. 191 void ClearRlzStateImpl(); 192 193 // Schedules a call to ClearRlzStateImpl(). This method is virtual 194 // to allow tests to override how the scheduling is done. 195 virtual bool ScheduleClearRlzState(); 196#endif 197 198 // Returns a pointer to the bool corresponding to whether |point| has been 199 // used but not reported. 200 bool* GetAccessPointRecord(rlz_lib::AccessPoint point); 201 202 // Tracker used for testing purposes only. If this value is non-NULL, it 203 // will be returned from GetInstance() instead of the regular singleton. 204 static RLZTracker* tracker_; 205 206 // Configuation data for RLZ tracker. Set by call to Init(). 207 bool first_run_; 208 bool send_ping_immediately_; 209 bool is_google_default_search_; 210 bool is_google_homepage_; 211 bool is_google_in_startpages_; 212 213 // Unique sequence token so that tasks posted by RLZTracker are executed 214 // sequentially in the blocking pool. 215 base::SequencedWorkerPool::SequenceToken worker_pool_token_; 216 217 // Keeps track if the RLZ tracker has already performed its delayed 218 // initialization. 219 bool already_ran_; 220 221 // Keeps a cache of RLZ access point strings, since they rarely change. 222 // The cache must be protected by a lock since it may be accessed from 223 // the UI thread for reading and the IO thread for reading and/or writing. 224 base::Lock cache_lock_; 225 std::map<rlz_lib::AccessPoint, base::string16> rlz_cache_; 226 227 // Keeps track of whether the omnibox, home page or app list have been used. 228 bool omnibox_used_; 229 bool homepage_used_; 230 bool app_list_used_; 231 232 // Main and (optionally) reactivation brand codes, assigned on UI thread. 233 std::string brand_; 234 std::string reactivation_brand_; 235 236 content::NotificationRegistrar registrar_; 237 238 // Minimum delay before sending financial ping after initialization. 239 base::TimeDelta min_init_delay_; 240 241 DISALLOW_COPY_AND_ASSIGN(RLZTracker); 242}; 243 244#endif // defined(ENABLE_RLZ) 245 246#endif // CHROME_BROWSER_RLZ_RLZ_H_ 247