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