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