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