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