• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // A library to manage RLZ information for access-points shared
6 // across different client applications.
7 //
8 // All functions return true on success and false on error.
9 // This implemenation is thread safe.
10 
11 
12 #ifndef RLZ_LIB_RLZ_LIB_H_
13 #define RLZ_LIB_RLZ_LIB_H_
14 
15 #include <stdio.h>
16 #include <string>
17 
18 #include "build/build_config.h"
19 
20 #include "rlz/lib/rlz_enums.h"
21 
22 #if defined(OS_WIN)
23 #define RLZ_LIB_API __cdecl
24 #else
25 #define RLZ_LIB_API
26 #endif
27 
28 // Define one of
29 // + RLZ_NETWORK_IMPLEMENTATION_WIN_INET: Uses win inet to send financial pings.
30 // + RLZ_NETWORK_IMPLEMENTATION_CHROME_NET: Uses chrome's network stack to send
31 //   financial pings. rlz_lib::SetURLRequestContext() must be called before
32 //   any calls to SendFinancialPing().
33 #if defined(RLZ_NETWORK_IMPLEMENTATION_WIN_INET) && \
34     defined(RLZ_NETWORK_IMPLEMENTATION_CHROME_NET)
35 #error Exactly one of RLZ_NETWORK_IMPLEMENTATION_WIN_INET and \
36     RLZ_NETWORK_IMPLEMENTATION_CHROME_NET should be defined.
37 #endif
38 #if !defined(RLZ_NETWORK_IMPLEMENTATION_WIN_INET) && \
39     !defined(RLZ_NETWORK_IMPLEMENTATION_CHROME_NET)
40 #if defined(OS_WIN)
41 #define RLZ_NETWORK_IMPLEMENTATION_WIN_INET
42 #else
43 #define RLZ_NETWORK_IMPLEMENTATION_CHROME_NET
44 #endif
45 #endif
46 
47 #if defined(RLZ_NETWORK_IMPLEMENTATION_CHROME_NET)
48 namespace net {
49 class URLRequestContextGetter;
50 }  // namespace net
51 #endif
52 
53 namespace rlz_lib {
54 
55 // All functions return true on success and false on error.
56 // This implemenation is thread safe.
57 //
58 // Each prototype mentions the registry access requirements:
59 //
60 // HKLM read:  Will work from any process and at any privilege level on Vista.
61 // HKCU read:  Calls made from the SYSTEM account must pass the current user's
62 //             SID as the optional 'sid' param. Can be called from low integrity
63 //             process on Vista.
64 // HKCU write: Calls made from the SYSTEM account must pass the current user's
65 //             SID as the optional 'sid' param. Calls require at least medium
66 //             integrity on Vista (e.g. Toolbar will need to use their broker)
67 // HKLM write: Calls must be made from an account with admin rights. No SID
68 //             need be passed when running as SYSTEM.
69 // Functions which do not access registry will be marked with "no restrictions".
70 
71 class ScopedRlzValueStoreLock;
72 
73 // The maximum length of an access points RLZ in bytes.
74 const size_t kMaxRlzLength = 64;
75 // The maximum length of an access points RLZ in bytes.
76 const size_t kMaxDccLength = 128;
77 // The maximum length of a CGI string in bytes.
78 const size_t kMaxCgiLength = 2048;
79 // The maximum length of a ping response we will parse in bytes. If the response
80 // is bigger, please break it up into separate calls.
81 const size_t kMaxPingResponseLength = 0x4000;  // 16K
82 
83 #if defined(RLZ_NETWORK_IMPLEMENTATION_CHROME_NET)
84 // Set the URLRequestContextGetter used by SendFinancialPing(). The IO message
85 // loop returned by this context will be used for the IO done by
86 // SendFinancialPing().
87 bool RLZ_LIB_API SetURLRequestContext(net::URLRequestContextGetter* context);
88 #endif
89 
90 // RLZ storage functions.
91 
92 // Get all the events reported by this product as a CGI string to append to
93 // the daily ping.
94 // Access: HKCU read.
95 bool RLZ_LIB_API GetProductEventsAsCgi(Product product, char* unescaped_cgi,
96                                        size_t unescaped_cgi_size);
97 
98 // Records an RLZ event.
99 // Some events can be product-independent (e.g: First search from home page),
100 // and some can be access point independent (e.g. Pack installed). However,
101 // product independent events must still include the product which cares about
102 // that information being reported.
103 // Access: HKCU write.
104 bool RLZ_LIB_API RecordProductEvent(Product product, AccessPoint point,
105                                     Event event_id);
106 
107 // Clear an event reported by this product. This should be called after a
108 // successful ping to the RLZ server.
109 // Access: HKCU write.
110 bool RLZ_LIB_API ClearProductEvent(Product product, AccessPoint point,
111                                    Event event_id);
112 
113 // Clear all reported events and recorded stateful events of this product.
114 // This should be called on complete uninstallation of the product.
115 // Access: HKCU write.
116 bool RLZ_LIB_API ClearAllProductEvents(Product product);
117 
118 // Clears all product-specifc state from the RLZ registry.
119 // Should be called during product uninstallation.
120 // This removes outstanding product events, product financial ping times,
121 // the product RLS argument (if any), and any RLZ's for access points being
122 // uninstalled with the product.
123 // access_points is an array terminated with NO_ACCESS_POINT.
124 // IMPORTANT: These are the access_points the product is removing as part
125 // of the uninstallation, not necessarily all the access points passed to
126 // SendFinancialPing() and GetPingParams().
127 // access_points can be NULL if no points are being uninstalled.
128 // No return value - this is best effort. Will assert in debug mode on
129 // failed attempts.
130 // Access: HKCU write.
131 void RLZ_LIB_API ClearProductState(Product product,
132                                    const AccessPoint* access_points);
133 
134 // Get the RLZ value of the access point. If the access point is not Google, the
135 // RLZ will be the empty string and the function will return false.
136 // Access: HKCU read.
137 bool RLZ_LIB_API GetAccessPointRlz(AccessPoint point, char* rlz,
138                                    size_t rlz_size);
139 
140 // Set the RLZ for the access-point. Fails and asserts if called when the access
141 // point is not set to Google.
142 // new_rlz should come from a server-response. Client applications should not
143 // create their own RLZ values.
144 // Access: HKCU write.
145 bool RLZ_LIB_API SetAccessPointRlz(AccessPoint point, const char* new_rlz);
146 
147 // Financial Server pinging functions.
148 // These functions deal with pinging the RLZ financial server and parsing and
149 // acting upon the response. Clients should SendFinancialPing() to avoid needing
150 // these functions. However, these functions allow clients to split the various
151 // parts of the pinging process up as needed (to avoid firewalls, etc).
152 
153 // Forms the HTTP request to send to the RLZ financial server.
154 //
155 // product            : The product to ping for.
156 // access_points      : The access points this product affects. Array must be
157 //                      terminated with NO_ACCESS_POINT.
158 // product_signature  : The signature sent with daily pings (e.g. swg, ietb)
159 // product_brand      : The brand of the pinging product, if any.
160 // product_id         : The product-specific installation ID (can be NULL).
161 // product_lang       : The language for the product (used to determine cohort).
162 // exclude_machine_id : Whether the Machine ID should be explicitly excluded
163 //                      based on the products privacy policy.
164 // request            : The buffer where the function returns the HTTP request.
165 // request_buffer_size: The size of the request buffer in bytes. The buffer
166 //                      size (kMaxCgiLength+1) is guaranteed to be enough.
167 //
168 // Access: HKCU read.
169 bool RLZ_LIB_API FormFinancialPingRequest(Product product,
170                                           const AccessPoint* access_points,
171                                           const char* product_signature,
172                                           const char* product_brand,
173                                           const char* product_id,
174                                           const char* product_lang,
175                                           bool exclude_machine_id,
176                                           char* request,
177                                           size_t request_buffer_size);
178 
179 // Pings the financial server and returns the HTTP response. This will fail
180 // if it is too early to ping the server since the last ping.
181 //
182 // If RLZ_NETWORK_IMPLEMENTATION_CHROME_NET is set, SetURLRequestContext() needs
183 // to be called before calling this function.
184 //
185 // product              : The product to ping for.
186 // request              : The HTTP request (for example, returned by
187 //                        FormFinancialPingRequest).
188 // response             : The buffer in which the HTTP response is returned.
189 // response_buffer_size : The size of the response buffer in bytes. The buffer
190 //                        size (kMaxPingResponseLength+1) is enough for all
191 //                        legitimate server responses (any response that is
192 //                        bigger should be considered the same way as a general
193 //                        network problem).
194 //
195 // Access: HKCU read.
196 bool RLZ_LIB_API PingFinancialServer(Product product,
197                                      const char* request,
198                                      char* response,
199                                      size_t response_buffer_size);
200 
201 // Checks if a ping response is valid - ie. it has a checksum line which
202 // is the CRC-32 checksum of the message uptil the checksum. If
203 // checksum_idx is not NULL, it will get the index of the checksum, i.e. -
204 // the effective end of the message.
205 // Access: No restrictions.
206 bool RLZ_LIB_API IsPingResponseValid(const char* response,
207                                      int* checksum_idx);
208 
209 
210 // Complex helpers built on top of other functions.
211 
212 // Parses the responses from the financial server and updates product state
213 // and access point RLZ's in registry. Like ParsePingResponse(), but also
214 // updates the last ping time.
215 // Access: HKCU write.
216 bool RLZ_LIB_API ParseFinancialPingResponse(Product product,
217                                             const char* response);
218 
219 // Send the ping with RLZs and events to the PSO server.
220 // This ping method should be called daily. (More frequent calls will fail).
221 // Also, if there are no events, the call will succeed only once a week.
222 //
223 // If RLZ_NETWORK_IMPLEMENTATION_CHROME_NET is set, SetURLRequestContext() needs
224 // to be called before calling this function.
225 //
226 // product            : The product to ping for.
227 // access_points      : The access points this product affects. Array must be
228 //                      terminated with NO_ACCESS_POINT.
229 // product_signature  : The signature sent with daily pings (e.g. swg, ietb)
230 // product_brand      : The brand of the pinging product, if any.
231 // product_id         : The product-specific installation ID (can be NULL).
232 // product_lang       : The language for the product (used to determine cohort).
233 // exclude_machine_id : Whether the Machine ID should be explicitly excluded
234 //                      based on the products privacy policy.
235 //
236 // Returns true on successful ping and response, false otherwise.
237 // Access: HKCU write.
238 bool RLZ_LIB_API SendFinancialPing(Product product,
239                                    const AccessPoint* access_points,
240                                    const char* product_signature,
241                                    const char* product_brand,
242                                    const char* product_id,
243                                    const char* product_lang,
244                                    bool exclude_machine_id);
245 
246 // An alternate implementations of SendFinancialPing with the same behavior,
247 // except the caller can optionally choose to skip the timing check.
248 bool RLZ_LIB_API SendFinancialPing(Product product,
249                                    const AccessPoint* access_points,
250                                    const char* product_signature,
251                                    const char* product_brand,
252                                    const char* product_id,
253                                    const char* product_lang,
254                                    bool exclude_machine_id,
255                                    const bool skip_time_check);
256 
257 // Parses RLZ related ping response information from the server.
258 // Updates stored RLZ values and clears stored events accordingly.
259 // Access: HKCU write.
260 bool RLZ_LIB_API ParsePingResponse(Product product, const char* response);
261 
262 
263 // Copies the events associated with the product and the RLZ's for each access
264 // point in access_points into cgi. This string can be directly appended
265 // to a ping (will need an & if not first paramter).
266 // access_points must be an array of AccessPoints terminated with
267 // NO_ACCESS_POINT.
268 // Access: HKCU read.
269 bool RLZ_LIB_API GetPingParams(Product product,
270                                const AccessPoint* access_points,
271                                char* unescaped_cgi, size_t unescaped_cgi_size);
272 
273 #if defined(OS_WIN)
274 // OEM Deal confirmation storage functions. OEM Deals are windows-only.
275 
276 // Makes the OEM Deal Confirmation code writable by all users on the machine.
277 // This should be called before calling SetMachineDealCode from a non-admin
278 // account.
279 // Access: HKLM write.
280 bool RLZ_LIB_API CreateMachineState(void);
281 
282 // Set the OEM Deal Confirmation Code (DCC). This information is used for RLZ
283 // initalization.
284 // Access: HKLM write, or
285 // HKCU read if rlz_lib::CreateMachineState() has been sucessfully called.
286 bool RLZ_LIB_API SetMachineDealCode(const char* dcc);
287 
288 // Get the DCC cgi argument string to append to a daily ping.
289 // Should be used only by OEM deal trackers. Applications should use the
290 // GetMachineDealCode method which has an AccessPoint paramter.
291 // Access: HKLM read.
292 bool RLZ_LIB_API GetMachineDealCodeAsCgi(char* cgi, size_t cgi_size);
293 
294 // Get the DCC value stored in registry.
295 // Should be used only by OEM deal trackers. Applications should use the
296 // GetMachineDealCode method which has an AccessPoint paramter.
297 // Access: HKLM read.
298 bool RLZ_LIB_API GetMachineDealCode(char* dcc, size_t dcc_size);
299 
300 // Parses a ping response, checks if it is valid and sets the machine DCC
301 // from the response. The ping must also contain the current DCC value in
302 // order to be considered valid.
303 // Access: HKLM write;
304 //         HKCU write if CreateMachineState() has been successfully called.
305 bool RLZ_LIB_API SetMachineDealCodeFromPingResponse(const char* response);
306 
307 #endif
308 
309 // Segment RLZ persistence based on branding information.
310 // All information for a given product is persisted under keys with the either
311 // product's name or its access point's name.  This assumes that only
312 // one instance of the product is installed on the machine, and that only one
313 // product brand is associated with it.
314 //
315 // In some cases, a given product may be using supplementary brands.  The RLZ
316 // information must be kept separately for each of these brands.  To achieve
317 // this segmentation, scope all RLZ library calls that deal with supplementary
318 // brands within the lifetime of an rlz_lib::ProductBranding instance.
319 //
320 // For example, to record events for a supplementary brand, do the following:
321 //
322 //  {
323 //    rlz_lib::SupplementaryBranding branding("AAAA");
324 //    // This call to RecordProductEvent is scoped to the AAAA brand.
325 //    rlz_lib::RecordProductEvent(rlz_lib::DESKTOP, rlz_lib::GD_DESKBAND,
326 //                                rlz_lib::INSTALL);
327 //  }
328 //
329 //  // This call to RecordProductEvent is not scoped to any supplementary brand.
330 //  rlz_lib::RecordProductEvent(rlz_lib::DESKTOP, rlz_lib::GD_DESKBAND,
331 //                              rlz_lib::INSTALL);
332 //
333 // In particular, this affects the recording of stateful events and the sending
334 // of financial pings.  In the former case, a stateful event recorded while
335 // scoped to a supplementary brand will be recorded again when scoped to a
336 // different supplementary brand (or not scoped at all).  In the latter case,
337 // the time skip check is specific to each supplementary brand.
338 class SupplementaryBranding {
339  public:
340   SupplementaryBranding(const char* brand);
341   ~SupplementaryBranding();
342 
343   static const std::string& GetBrand();
344 
345  private:
346   ScopedRlzValueStoreLock* lock_;
347 };
348 
349 }  // namespace rlz_lib
350 
351 #endif  // RLZ_LIB_RLZ_LIB_H_
352