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 24 class Profile; 25 namespace net { 26 class 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 39 class 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 const rlz_lib::AccessPoint CHROME_OMNIBOX; 64 static const rlz_lib::AccessPoint CHROME_HOME_PAGE; 65 66 // Gets the HTTP header value that can be added to requests from the 67 // specific access point. The string returned is of the form: 68 // 69 // "X-Rlz-String: <access-point-rlz>\r\n" 70 // 71 static std::string GetAccessPointHttpHeader(rlz_lib::AccessPoint point); 72 73 // Gets the RLZ value of the access point. 74 // Returns false if the rlz string could not be obtained. In some cases 75 // an empty string can be returned which is not an error. 76 static bool GetAccessPointRlz(rlz_lib::AccessPoint point, 77 base::string16* rlz); 78 79 // Invoked during shutdown to clean up any state created by RLZTracker. 80 static void CleanupRlz(); 81 82 #if defined(OS_CHROMEOS) 83 // Clears all product state. Should be called when turning RLZ off. On other 84 // platforms, this is done by product uninstaller. 85 static void ClearRlzState(); 86 #endif 87 88 // This method is public for use by the Singleton class. 89 static RLZTracker* GetInstance(); 90 91 // Enables zero delay for InitRlzFromProfileDelayed. For testing only. 92 static void EnableZeroDelayForTesting(); 93 94 // The following methods are made protected so that they can be used for 95 // testing purposes. Production code should never need to call these. 96 protected: 97 RLZTracker(); 98 virtual ~RLZTracker(); 99 100 // Called by InitRlzFromProfileDelayed with values taken from |profile|. 101 static bool InitRlzDelayed(bool first_run, 102 bool send_ping_immediately, 103 base::TimeDelta delay, 104 bool is_google_default_search, 105 bool is_google_homepage, 106 bool is_google_in_startpages); 107 108 // Performs initialization of RLZ tracker that is purposefully delayed so 109 // that it does not interfere with chrome startup time. 110 virtual void DelayedInit(); 111 112 // content::NotificationObserver implementation: 113 virtual void Observe(int type, 114 const content::NotificationSource& source, 115 const content::NotificationDetails& details) OVERRIDE; 116 117 // Used by test code to override the default RLZTracker instance returned 118 // by GetInstance(). set_tracker(RLZTracker * tracker)119 void set_tracker(RLZTracker* tracker) { 120 tracker_ = tracker; 121 } 122 123 // Sends the financial ping to the RLZ servers and invalidates the RLZ string 124 // cache since the response from the RLZ server may have changed then. 125 // Protected so that its accessible from tests. 126 void PingNowImpl(); 127 128 private: 129 friend struct DefaultSingletonTraits<RLZTracker>; 130 friend class base::RefCountedThreadSafe<RLZTracker>; 131 132 // Implementation called from InitRlzDelayed() static method. 133 bool Init(bool first_run, 134 bool send_ping_immediately, 135 base::TimeDelta delay, 136 bool google_default_search, 137 bool google_default_homepage, 138 bool is_google_in_startpages); 139 140 // Implementation called from RecordProductEvent() static method. 141 bool RecordProductEventImpl(rlz_lib::Product product, 142 rlz_lib::AccessPoint point, 143 rlz_lib::Event event_id); 144 145 // Records FIRST_SEARCH event. Called from Observe() on blocking task runner. 146 void RecordFirstSearch(rlz_lib::AccessPoint point); 147 148 // Implementation called from GetAccessPointRlz() static method. 149 bool GetAccessPointRlzImpl(rlz_lib::AccessPoint point, base::string16* rlz); 150 151 // Schedules the delayed initialization. This method is virtual to allow 152 // tests to override how the scheduling is done. 153 virtual void ScheduleDelayedInit(base::TimeDelta delay); 154 155 // Schedules a call to rlz_lib::RecordProductEvent(). This method is virtual 156 // to allow tests to override how the scheduling is done. 157 virtual bool ScheduleRecordProductEvent(rlz_lib::Product product, 158 rlz_lib::AccessPoint point, 159 rlz_lib::Event event_id); 160 161 // Schedules a call to rlz_lib::RecordFirstSearch(). This method is virtual 162 // to allow tests to override how the scheduling is done. 163 virtual bool ScheduleRecordFirstSearch(rlz_lib::AccessPoint point); 164 165 // Schedules a call to rlz_lib::SendFinancialPing(). This method is virtual 166 // to allow tests to override how the scheduling is done. 167 virtual void ScheduleFinancialPing(); 168 169 // Schedules a call to GetAccessPointRlz() on the I/O thread if the current 170 // thread is not already the I/O thread, otherwise does nothing. Returns 171 // true if the call was scheduled, and false otherwise. This method is 172 // virtual to allow tests to override how the scheduling is done. 173 virtual bool ScheduleGetAccessPointRlz(rlz_lib::AccessPoint point); 174 175 // Sends the financial ping to the RLZ servers. This method is virtual to 176 // allow tests to override. 177 virtual bool SendFinancialPing(const std::string& brand, 178 const base::string16& lang, 179 const base::string16& referral); 180 181 #if defined(OS_CHROMEOS) 182 // Implementation called from ClearRlzState static method. 183 void ClearRlzStateImpl(); 184 185 // Schedules a call to ClearRlzStateImpl(). This method is virtual 186 // to allow tests to override how the scheduling is done. 187 virtual bool ScheduleClearRlzState(); 188 #endif 189 190 // Tracker used for testing purposes only. If this value is non-NULL, it 191 // will be returned from GetInstance() instead of the regular singleton. 192 static RLZTracker* tracker_; 193 194 // Configuation data for RLZ tracker. Set by call to Init(). 195 bool first_run_; 196 bool send_ping_immediately_; 197 bool is_google_default_search_; 198 bool is_google_homepage_; 199 bool is_google_in_startpages_; 200 201 // Unique sequence token so that tasks posted by RLZTracker are executed 202 // sequentially in the blocking pool. 203 base::SequencedWorkerPool::SequenceToken worker_pool_token_; 204 205 // Keeps track if the RLZ tracker has already performed its delayed 206 // initialization. 207 bool already_ran_; 208 209 // Keeps a cache of RLZ access point strings, since they rarely change. 210 // The cache must be protected by a lock since it may be accessed from 211 // the UI thread for reading and the IO thread for reading and/or writing. 212 base::Lock cache_lock_; 213 std::map<rlz_lib::AccessPoint, base::string16> rlz_cache_; 214 215 // Keeps track of whether the omnibox or host page have been used. 216 bool omnibox_used_; 217 bool homepage_used_; 218 219 // Main and (optionally) reactivation brand codes, assigned on UI thread. 220 std::string brand_; 221 std::string reactivation_brand_; 222 223 content::NotificationRegistrar registrar_; 224 225 // Minimum delay before sending financial ping after initialization. 226 base::TimeDelta min_init_delay_; 227 228 DISALLOW_COPY_AND_ASSIGN(RLZTracker); 229 }; 230 231 #endif // defined(ENABLE_RLZ) 232 233 #endif // CHROME_BROWSER_RLZ_RLZ_H_ 234