1// Copyright (c) 2011 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#include "chrome/browser/extensions/extension_rlz_module.h"
6
7#include "base/memory/scoped_ptr.h"
8#include "base/threading/thread_restrictions.h"
9#include "base/values.h"
10#include "chrome/common/extensions/extension.h"
11#include "rlz/win/lib/lib_values.h"
12
13namespace {
14
15bool GetProductFromName(const std::string& product_name,
16                        rlz_lib::Product* product) {
17  bool success = true;
18  switch (product_name[0]) {
19    case 'B':
20      *product = rlz_lib::FF_TOOLBAR;
21      break;
22    case 'C':
23      *product = rlz_lib::CHROME;
24      break;
25    case 'D':
26      *product = rlz_lib::DESKTOP;
27      break;
28    case 'K':
29      *product = rlz_lib::QSB_WIN;
30      break;
31    case 'N':
32      *product = rlz_lib::PINYIN_IME;
33      break;
34    case 'P':
35      *product = rlz_lib::TOOLBAR_NOTIFIER;
36      break;
37    case 'T':
38      *product = rlz_lib::IE_TOOLBAR;
39      break;
40    case 'U':
41      *product = rlz_lib::PACK;
42      break;
43    case 'W':
44      *product = rlz_lib::WEBAPPS;
45      break;
46    default:
47      success = false;
48      break;
49  }
50
51  return success;
52}
53
54bool GetEventFromName(const std::string& event_name,
55                      rlz_lib::Event* event_id) {
56  *event_id = rlz_lib::INVALID_EVENT;
57
58  if (event_name == "install") {
59    *event_id = rlz_lib::INSTALL;
60  } else if (event_name == "set-to-google") {
61    *event_id = rlz_lib::SET_TO_GOOGLE;
62  } else if (event_name == "first-search") {
63    *event_id = rlz_lib::FIRST_SEARCH;
64  } else if (event_name == "activate") {
65    *event_id = rlz_lib::ACTIVATE;
66  }
67
68  return *event_id != rlz_lib::INVALID_EVENT;
69}
70
71}  // namespace
72
73bool RlzRecordProductEventFunction::RunImpl() {
74  // This can be slow if registry access goes to disk. Should preferably
75  // perform registry operations on the File thread.
76  //   http://code.google.com/p/chromium/issues/detail?id=62098
77  base::ThreadRestrictions::ScopedAllowIO allow_io;
78
79  std::string product_name;
80  EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &product_name));
81  rlz_lib::Product product;
82  EXTENSION_FUNCTION_VALIDATE(GetProductFromName(product_name, &product));
83
84  std::string ap_name;
85  EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &ap_name));
86  rlz_lib::AccessPoint access_point;
87  EXTENSION_FUNCTION_VALIDATE(rlz_lib::GetAccessPointFromName(ap_name.c_str(),
88                                                              &access_point));
89
90  std::string event_name;
91  EXTENSION_FUNCTION_VALIDATE(args_->GetString(2, &event_name));
92  rlz_lib::Event event_id;
93  EXTENSION_FUNCTION_VALIDATE(GetEventFromName(event_name, &event_id));
94
95  return rlz_lib::RecordProductEvent(product, access_point, event_id);
96}
97
98bool RlzGetAccessPointRlzFunction::RunImpl() {
99  // This can be slow if registry access goes to disk. Should preferably
100  // perform registry operations on the File thread.
101  //   http://code.google.com/p/chromium/issues/detail?id=62098
102  base::ThreadRestrictions::ScopedAllowIO allow_io;
103
104  std::string ap_name;
105  EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &ap_name));
106  rlz_lib::AccessPoint access_point;
107  EXTENSION_FUNCTION_VALIDATE(rlz_lib::GetAccessPointFromName(ap_name.c_str(),
108                                                              &access_point));
109
110  char rlz[rlz_lib::kMaxRlzLength + 1];
111  rlz_lib::GetAccessPointRlz(access_point, rlz, rlz_lib::kMaxRlzLength);
112  result_.reset(Value::CreateStringValue(rlz));
113  return true;
114}
115
116bool RlzSendFinancialPingFunction::RunImpl() {
117  // This can be slow if registry access goes to disk. Should preferably
118  // perform registry operations on the File thread.
119  //   http://code.google.com/p/chromium/issues/detail?id=62098
120  base::ThreadRestrictions::ScopedAllowIO allow_io;
121
122  std::string product_name;
123  EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &product_name));
124  rlz_lib::Product product;
125  EXTENSION_FUNCTION_VALIDATE(GetProductFromName(product_name, &product));
126
127  ListValue* access_points_list;
128  EXTENSION_FUNCTION_VALIDATE(args_->GetList(1, &access_points_list));
129  if (access_points_list->GetSize() < 1) {
130    EXTENSION_FUNCTION_ERROR("Access point array should not be empty.");
131  }
132
133  // Allocate an access point array to pass to ClearProductState().  The array
134  // must be termindated with the value rlz_lib::NO_ACCESS_POINT, hence + 1
135  // when allocating the array.
136  scoped_array<rlz_lib::AccessPoint> access_points(
137      new rlz_lib::AccessPoint[access_points_list->GetSize() + 1]);
138
139  size_t i;
140  for (i = 0; i < access_points_list->GetSize(); ++i) {
141    std::string ap_name;
142    EXTENSION_FUNCTION_VALIDATE(access_points_list->GetString(i, &ap_name));
143    EXTENSION_FUNCTION_VALIDATE(rlz_lib::GetAccessPointFromName(
144        ap_name.c_str(), &access_points[i]));
145  }
146  access_points[i] = rlz_lib::NO_ACCESS_POINT;
147
148  std::string signature;
149  EXTENSION_FUNCTION_VALIDATE(args_->GetString(2, &signature));
150
151  std::string brand;
152  EXTENSION_FUNCTION_VALIDATE(args_->GetString(3, &brand));
153
154  std::string id;
155  EXTENSION_FUNCTION_VALIDATE(args_->GetString(4, &id));
156
157  std::string lang;
158  EXTENSION_FUNCTION_VALIDATE(args_->GetString(5, &lang));
159
160  bool exclude_machine_id;
161  EXTENSION_FUNCTION_VALIDATE(args_->GetBoolean(6, &exclude_machine_id));
162
163  // rlz_lib::SendFinancialPing() will not send a ping more often than once in
164  // any 24-hour period.  Calling it more often has no effect.  If a ping is
165  // not sent false is returned, but this is not an error, so we should not
166  // use the return value of rlz_lib::SendFinancialPing() as the return value
167  // of this function.  Callers interested in the return value can register
168  // an optional callback function.
169  bool sent = rlz_lib::SendFinancialPing(product, access_points.get(),
170                                         signature.c_str(), brand.c_str(),
171                                         id.c_str(), lang.c_str(),
172                                         exclude_machine_id);
173  result_.reset(Value::CreateBooleanValue(sent));
174  return true;
175}
176
177bool RlzClearProductStateFunction::RunImpl() {
178  // This can be slow if registry access goes to disk. Should preferably
179  // perform registry operations on the File thread.
180  //   http://code.google.com/p/chromium/issues/detail?id=62098
181  base::ThreadRestrictions::ScopedAllowIO allow_io;
182
183  std::string product_name;
184  EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &product_name));
185  rlz_lib::Product product;
186  EXTENSION_FUNCTION_VALIDATE(GetProductFromName(product_name, &product));
187
188  ListValue* access_points_list;
189  EXTENSION_FUNCTION_VALIDATE(args_->GetList(1, &access_points_list));
190  if (access_points_list->GetSize() < 1) {
191    EXTENSION_FUNCTION_ERROR("Access point array should not be empty.");
192  }
193
194  // Allocate an access point array to pass to ClearProductState().  The array
195  // must be termindated with the value rlz_lib::NO_ACCESS_POINT, hence + 1
196  // when allocating the array.
197  scoped_array<rlz_lib::AccessPoint> access_points(
198      new rlz_lib::AccessPoint[access_points_list->GetSize() + 1]);
199
200  size_t i;
201  for (i = 0; i < access_points_list->GetSize(); ++i) {
202    std::string ap_name;
203    EXTENSION_FUNCTION_VALIDATE(access_points_list->GetString(i, &ap_name));
204    EXTENSION_FUNCTION_VALIDATE(rlz_lib::GetAccessPointFromName(
205        ap_name.c_str(), &access_points[i]));
206  }
207  access_points[i] = rlz_lib::NO_ACCESS_POINT;
208
209  rlz_lib::ClearProductState(product, access_points.get());
210  return true;
211}
212