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