15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A library to manage RLZ information for access-points shared
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// across different client applications.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "rlz/lib/rlz_lib.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "rlz/lib/assert.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "rlz/lib/crc32.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "rlz/lib/financial_ping.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "rlz/lib/lib_values.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "rlz/lib/rlz_value_store.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "rlz/lib/string_utils.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Event information returned from ping response.
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ReturnedEvent {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rlz_lib::AccessPoint access_point;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rlz_lib::Event event_type;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper functions
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsAccessPointSupported(rlz_lib::AccessPoint point) {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (point) {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case rlz_lib::NO_ACCESS_POINT:
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case rlz_lib::LAST_ACCESS_POINT:
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case rlz_lib::MOBILE_IDLE_SCREEN_BLACKBERRY:
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case rlz_lib::MOBILE_IDLE_SCREEN_WINMOB:
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case rlz_lib::MOBILE_IDLE_SCREEN_SYMBIAN:
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // These AP's are never available on Windows PCs.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case rlz_lib::IE_DEFAULT_SEARCH:
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case rlz_lib::IE_HOME_PAGE:
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case rlz_lib::IETB_SEARCH_BOX:
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case rlz_lib::QUICK_SEARCH_BOX:
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case rlz_lib::GD_DESKBAND:
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case rlz_lib::GD_SEARCH_GADGET:
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case rlz_lib::GD_WEB_SERVER:
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case rlz_lib::GD_OUTLOOK:
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case rlz_lib::CHROME_OMNIBOX:
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  case rlz_lib::CHROME_HOME_PAGE:
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO: Figure out when these settings are set to Google.
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  default:
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Current RLZ can only use [a-zA-Z0-9_\-]
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We will be more liberal and allow some additional chars, but not url meta
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// chars.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsGoodRlzChar(const char ch) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsAsciiAlpha(ch) || IsAsciiDigit(ch))
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (ch) {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case '_':
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case '-':
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case '!':
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case '@':
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case '$':
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case '*':
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case '(':
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ')':
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ';':
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case '.':
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case '<':
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case '>':
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This function will remove bad rlz chars and also limit the max rlz to some
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// reasonable size.  It also assumes that normalized_rlz is at least
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// kMaxRlzLength+1 long.
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NormalizeRlz(const char* raw_rlz, char* normalized_rlz) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t index = 0;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; raw_rlz[index] != 0 && index < rlz_lib::kMaxRlzLength; ++index) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char current = raw_rlz[index];
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (IsGoodRlzChar(current)) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      normalized_rlz[index] = current;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      normalized_rlz[index] = '.';
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  normalized_rlz[index] = 0;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetEventsFromResponseString(
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& response_line,
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& field_header,
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<ReturnedEvent>* event_array) {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the string of events.
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string events = response_line.substr(field_header.size());
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TrimWhitespaceASCII(events, TRIM_LEADING, &events);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int events_length = events.find_first_of("\r\n ");
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (events_length < 0)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_length = events.size();
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  events = events.substr(0, events_length);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Break this up into individual events
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int event_end_index = -1;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int event_begin = event_end_index + 1;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event_end_index = events.find(rlz_lib::kEventsCgiSeparator, event_begin);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int event_end = event_end_index;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (event_end < 0)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event_end = events_length;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string event_string = events.substr(event_begin,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             event_end - event_begin);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (event_string.size() != 3)  // 3 = 2(AP) + 1(E)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rlz_lib::AccessPoint point = rlz_lib::NO_ACCESS_POINT;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rlz_lib::Event event = rlz_lib::INVALID_EVENT;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!GetAccessPointFromName(event_string.substr(0, 2).c_str(), &point) ||
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        point == rlz_lib::NO_ACCESS_POINT) {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!GetEventFromName(event_string.substr(event_string.size() - 1).c_str(),
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          &event) || event == rlz_lib::INVALID_EVENT) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReturnedEvent current_event = {point, event};
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event_array->push_back(current_event);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (event_end_index >= 0);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Event storage functions.
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RecordStatefulEvent(rlz_lib::Product product, rlz_lib::AccessPoint point,
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         rlz_lib::Event event) {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rlz_lib::ScopedRlzValueStoreLock lock;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rlz_lib::RlzValueStore* store = lock.GetStore();
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!store || !store->HasAccess(rlz_lib::RlzValueStore::kWriteAccess))
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Write the new event to the value store.
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* point_name = GetAccessPointName(point);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* event_name = GetEventName(event);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!point_name || !event_name)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!point_name[0] || !event_name[0])
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string new_event_value;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringAppendF(&new_event_value, "%s%s", point_name, event_name);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return store->AddStatefulEvent(product, new_event_value.c_str());
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetProductEventsAsCgiHelper(rlz_lib::Product product, char* cgi,
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 size_t cgi_size,
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 rlz_lib::RlzValueStore* store) {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Prepend the CGI param key to the buffer.
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string cgi_arg;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringAppendF(&cgi_arg, "%s=", rlz_lib::kEventsCgiVariable);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cgi_size <= cgi_arg.size())
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t index;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (index = 0; index < cgi_arg.size(); ++index)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cgi[index] = cgi_arg[index];
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read stored events.
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> events;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!store->ReadProductEvents(product, &events))
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Append the events to the buffer.
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t num_values = 0;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (num_values = 0; num_values < events.size(); ++num_values) {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cgi[index] = '\0';
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int divider = num_values > 0 ? 1 : 0;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int size = cgi_size - (index + divider);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (size <= 0)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return cgi_size >= (rlz_lib::kMaxCgiLength + 1);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    strncpy(cgi + index + divider, events[num_values].c_str(), size);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (divider)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cgi[index] = rlz_lib::kEventsCgiSeparator;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    index += std::min((int)events[num_values].length(), size) + divider;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cgi[index] = '\0';
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return num_values > 0;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace rlz_lib {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(RLZ_NETWORK_IMPLEMENTATION_CHROME_NET)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SetURLRequestContext(net::URLRequestContextGetter* context) {
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return FinancialPing::SetURLRequestContext(context);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetProductEventsAsCgi(Product product, char* cgi, size_t cgi_size) {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!cgi || cgi_size <= 0) {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_STRING("GetProductEventsAsCgi: Invalid buffer");
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cgi[0] = 0;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedRlzValueStoreLock lock;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RlzValueStore* store = lock.GetStore();
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!store || !store->HasAccess(RlzValueStore::kReadAccess))
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t size_local = std::min(
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<size_t>(kMaxCgiLength + 1), cgi_size);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool result = GetProductEventsAsCgiHelper(product, cgi, size_local, store);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result) {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_STRING("GetProductEventsAsCgi: Possibly insufficient buffer size");
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cgi[0] = 0;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RecordProductEvent(Product product, AccessPoint point, Event event) {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedRlzValueStoreLock lock;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RlzValueStore* store = lock.GetStore();
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!store || !store->HasAccess(RlzValueStore::kWriteAccess))
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get this event's value.
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* point_name = GetAccessPointName(point);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* event_name = GetEventName(event);
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!point_name || !event_name)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!point_name[0] || !event_name[0])
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string new_event_value;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringAppendF(&new_event_value, "%s%s", point_name, event_name);
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check whether this event is a stateful event. If so, don't record it.
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (store->IsStatefulEvent(product, new_event_value.c_str())) {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // For a stateful event we skip recording, this function is also
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // considered successful.
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Write the new event to the value store.
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return store->AddProductEvent(product, new_event_value.c_str());
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ClearProductEvent(Product product, AccessPoint point, Event event) {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedRlzValueStoreLock lock;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RlzValueStore* store = lock.GetStore();
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!store || !store->HasAccess(RlzValueStore::kWriteAccess))
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the event's value store value and delete it.
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* point_name = GetAccessPointName(point);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* event_name = GetEventName(event);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!point_name || !event_name)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!point_name[0] || !event_name[0])
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string event_value;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringAppendF(&event_value, "%s%s", point_name, event_name);
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return store->ClearProductEvent(product, event_value.c_str());
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// RLZ storage functions.
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetAccessPointRlz(AccessPoint point, char* rlz, size_t rlz_size) {
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!rlz || rlz_size <= 0) {
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_STRING("GetAccessPointRlz: Invalid buffer");
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rlz[0] = 0;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedRlzValueStoreLock lock;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RlzValueStore* store = lock.GetStore();
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!store || !store->HasAccess(RlzValueStore::kReadAccess))
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsAccessPointSupported(point))
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return store->ReadAccessPointRlz(point, rlz, rlz_size);
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SetAccessPointRlz(AccessPoint point, const char* new_rlz) {
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedRlzValueStoreLock lock;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RlzValueStore* store = lock.GetStore();
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!store || !store->HasAccess(RlzValueStore::kWriteAccess))
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!new_rlz) {
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_STRING("SetAccessPointRlz: Invalid buffer");
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Return false if the access point is not set to Google.
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsAccessPointSupported(point)) {
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_STRING(("SetAccessPointRlz: "
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                "Cannot set RLZ for unsupported access point."));
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify the RLZ length.
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t rlz_length = strlen(new_rlz);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rlz_length > kMaxRlzLength) {
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_STRING("SetAccessPointRlz: RLZ length is exceeds max allowed.");
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char normalized_rlz[kMaxRlzLength + 1];
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NormalizeRlz(new_rlz, normalized_rlz);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VERIFY(strlen(new_rlz) == rlz_length);
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Setting RLZ to empty == clearing.
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (normalized_rlz[0] == 0)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return store->ClearAccessPointRlz(point);
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return store->WriteAccessPointRlz(point, normalized_rlz);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Financial Server pinging functions.
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FormFinancialPingRequest(Product product, const AccessPoint* access_points,
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const char* product_signature,
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const char* product_brand,
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const char* product_id,
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const char* product_lang,
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              bool exclude_machine_id,
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              char* request, size_t request_buffer_size) {
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!request || request_buffer_size == 0)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request[0] = 0;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string request_string;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!FinancialPing::FormRequest(product, access_points, product_signature,
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  product_brand, product_id, product_lang,
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  exclude_machine_id, &request_string))
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request_string.size() >= request_buffer_size)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  strncpy(request, request_string.c_str(), request_buffer_size);
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request[request_buffer_size - 1] = 0;
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PingFinancialServer(Product product, const char* request, char* response,
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         size_t response_buffer_size) {
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!response || response_buffer_size == 0)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response[0] = 0;
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if the time is right to ping.
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!FinancialPing::IsPingTime(product, false))
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send out the ping.
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string response_string;
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!FinancialPing::PingServer(request, &response_string))
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (response_string.size() >= response_buffer_size)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  strncpy(response, response_string.c_str(), response_buffer_size);
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response[response_buffer_size - 1] = 0;
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsPingResponseValid(const char* response, int* checksum_idx) {
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!response || !response[0])
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (checksum_idx)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *checksum_idx = -1;
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (strlen(response) > kMaxPingResponseLength) {
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_STRING("IsPingResponseValid: response is too long to parse.");
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Find the checksum line.
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string response_string(response);
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string checksum_param("\ncrc32: ");
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int calculated_crc;
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int checksum_index = response_string.find(checksum_param);
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (checksum_index >= 0) {
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Calculate checksum of message preceeding checksum line.
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // (+ 1 to include the \n)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string message(response_string.substr(0, checksum_index + 1));
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!Crc32(message.c_str(), &calculated_crc))
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    checksum_param = "crc32: ";  // Empty response case.
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!StartsWithASCII(response_string, checksum_param, true))
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    checksum_index = 0;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!Crc32("", &calculated_crc))
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Find the checksum value on the response.
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int checksum_end = response_string.find("\n", checksum_index + 1);
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (checksum_end < 0)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    checksum_end = response_string.size();
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int checksum_begin = checksum_index + checksum_param.size();
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string checksum = response_string.substr(checksum_begin,
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      checksum_end - checksum_begin + 1);
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TrimWhitespaceASCII(checksum, TRIM_ALL, &checksum);
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (checksum_idx)
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *checksum_idx = checksum_index;
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return calculated_crc == HexStringToInteger(checksum.c_str());
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Complex helpers built on top of other functions.
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ParseFinancialPingResponse(Product product, const char* response) {
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update the last ping time irrespective of success.
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FinancialPing::UpdateLastPingTime(product);
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parse the ping response - update RLZs, clear events.
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ParsePingResponse(product, response);
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SendFinancialPing(Product product, const AccessPoint* access_points,
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const char* product_signature,
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const char* product_brand,
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const char* product_id, const char* product_lang,
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       bool exclude_machine_id) {
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SendFinancialPing(product, access_points, product_signature,
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           product_brand, product_id, product_lang,
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           exclude_machine_id, false);
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SendFinancialPing(Product product, const AccessPoint* access_points,
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const char* product_signature,
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const char* product_brand,
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const char* product_id, const char* product_lang,
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       bool exclude_machine_id,
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const bool skip_time_check) {
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create the financial ping request.
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string request;
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!FinancialPing::FormRequest(product, access_points, product_signature,
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  product_brand, product_id, product_lang,
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  exclude_machine_id, &request))
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if the time is right to ping.
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!FinancialPing::IsPingTime(product, skip_time_check))
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send out the ping, update the last ping time irrespective of success.
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FinancialPing::UpdateLastPingTime(product);
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string response;
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!FinancialPing::PingServer(request.c_str(), &response))
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parse the ping response - update RLZs, clear events.
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ParsePingResponse(product, response.c_str());
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO: Use something like RSA to make sure the response is
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from a Google server.
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ParsePingResponse(Product product, const char* response) {
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rlz_lib::ScopedRlzValueStoreLock lock;
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rlz_lib::RlzValueStore* store = lock.GetStore();
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!store || !store->HasAccess(rlz_lib::RlzValueStore::kWriteAccess))
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string response_string(response);
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int response_length = -1;
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsPingResponseValid(response, &response_length))
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (0 == response_length)
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;  // Empty response - no parsing.
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string events_variable;
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string stateful_events_variable;
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::SStringPrintf(&events_variable, "%s: ", kEventsCgiVariable);
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::SStringPrintf(&stateful_events_variable, "%s: ",
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      kStatefulEventsCgiVariable);
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rlz_cgi_length = strlen(kRlzCgiVariable);
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Split response lines. Expected response format is lines of the form:
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // rlzW1: 1R1_____en__252
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int line_end_index = -1;
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int line_begin = line_end_index + 1;
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    line_end_index = response_string.find("\n", line_begin);
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int line_end = line_end_index;
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (line_end < 0)
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      line_end = response_length;
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (line_end <= line_begin)
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;  // Empty line.
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string response_line;
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    response_line = response_string.substr(line_begin, line_end - line_begin);
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (StartsWithASCII(response_line, kRlzCgiVariable, true)) {  // An RLZ.
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int separator_index = -1;
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((separator_index = response_line.find(": ")) < 0)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;  // Not a valid key-value pair.
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Get the access point.
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string point_name =
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        response_line.substr(3, separator_index - rlz_cgi_length);
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AccessPoint point = NO_ACCESS_POINT;
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!GetAccessPointFromName(point_name.c_str(), &point) ||
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          point == NO_ACCESS_POINT)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;  // Not a valid access point.
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Get the new RLZ.
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string rlz_value(response_line.substr(separator_index + 2));
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TrimWhitespaceASCII(rlz_value, TRIM_LEADING, &rlz_value);
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      size_t rlz_length = rlz_value.find_first_of("\r\n ");
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (rlz_length == std::string::npos)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rlz_length = rlz_value.size();
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (rlz_length > kMaxRlzLength)
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;  // Too long.
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (IsAccessPointSupported(point))
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SetAccessPointRlz(point, rlz_value.substr(0, rlz_length).c_str());
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (StartsWithASCII(response_line, events_variable, true)) {
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Clear events which server parsed.
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::vector<ReturnedEvent> event_array;
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetEventsFromResponseString(response_line, events_variable, &event_array);
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t i = 0; i < event_array.size(); ++i) {
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ClearProductEvent(product, event_array[i].access_point,
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          event_array[i].event_type);
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (StartsWithASCII(response_line, stateful_events_variable, true)) {
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Record any stateful events the server send over.
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::vector<ReturnedEvent> event_array;
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetEventsFromResponseString(response_line, stateful_events_variable,
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  &event_array);
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t i = 0; i < event_array.size(); ++i) {
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RecordStatefulEvent(product, event_array[i].access_point,
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            event_array[i].event_type);
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (line_end_index >= 0);
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update the DCC in registry if needed.
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetMachineDealCodeFromPingResponse(response);
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetPingParams(Product product, const AccessPoint* access_points,
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   char* cgi, size_t cgi_size) {
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!cgi || cgi_size <= 0) {
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_STRING("GetPingParams: Invalid buffer");
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cgi[0] = 0;
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!access_points) {
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_STRING("GetPingParams: access_points is NULL");
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add the RLZ Exchange Protocol version.
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string cgi_string(kProtocolCgiArgument);
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Copy the &rlz= over.
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringAppendF(&cgi_string, "&%s=", kRlzCgiVariable);
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Now add each of the RLZ's. Keep the lock during all GetAccessPointRlz()
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // calls below.
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScopedRlzValueStoreLock lock;
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RlzValueStore* store = lock.GetStore();
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!store || !store->HasAccess(RlzValueStore::kReadAccess))
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool first_rlz = true;  // comma before every RLZ but the first.
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; access_points[i] != NO_ACCESS_POINT; i++) {
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      char rlz[kMaxRlzLength + 1];
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (GetAccessPointRlz(access_points[i], rlz, arraysize(rlz))) {
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const char* access_point = GetAccessPointName(access_points[i]);
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!access_point)
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          continue;
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::StringAppendF(&cgi_string, "%s%s%s%s",
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            first_rlz ? "" : kRlzCgiSeparator,
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            access_point, kRlzCgiIndicator, rlz);
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        first_rlz = false;
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Report the DCC too if not empty. DCCs are windows-only.
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char dcc[kMaxDccLength + 1];
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dcc[0] = 0;
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (GetMachineDealCode(dcc, arraysize(dcc)) && dcc[0])
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::StringAppendF(&cgi_string, "&%s=%s", kDccCgiVariable, dcc);
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cgi_string.size() >= cgi_size)
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  strncpy(cgi, cgi_string.c_str(), cgi_size);
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cgi[cgi_size - 1] = 0;
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace rlz_lib
652