Home | History | Annotate | Download | only in feedback_private
      1 // Copyright 2013 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/api/feedback_private/feedback_private_api.h"
      6 
      7 #include "base/lazy_instance.h"
      8 #include "base/memory/scoped_ptr.h"
      9 #include "base/strings/string_number_conversions.h"
     10 #include "base/strings/string_util.h"
     11 #include "base/strings/utf_string_conversions.h"
     12 #include "base/values.h"
     13 #include "chrome/browser/extensions/api/feedback_private/feedback_service.h"
     14 #include "chrome/browser/profiles/profile.h"
     15 #include "components/feedback/tracing_manager.h"
     16 #include "extensions/browser/event_router.h"
     17 #include "grit/generated_resources.h"
     18 #include "ui/base/l10n/l10n_util.h"
     19 #include "ui/base/webui/web_ui_util.h"
     20 #include "url/url_util.h"
     21 
     22 using feedback::FeedbackData;
     23 
     24 namespace {
     25 
     26 // Getting the filename of a blob prepends a "C:\fakepath" to the filename.
     27 // This is undesirable, strip it if it exists.
     28 std::string StripFakepath(const std::string& path) {
     29   const char kFakePathStr[] = "C:\\fakepath\\";
     30   if (StartsWithASCII(path, kFakePathStr, false))
     31     return path.substr(arraysize(kFakePathStr) - 1);
     32   return path;
     33 }
     34 
     35 }  // namespace
     36 
     37 namespace extensions {
     38 
     39 namespace feedback_private = api::feedback_private;
     40 
     41 using feedback_private::SystemInformation;
     42 using feedback_private::FeedbackInfo;
     43 
     44 char kFeedbackExtensionId[] = "gfdkimpbcpahaombhbimeihdjnejgicl";
     45 
     46 static base::LazyInstance<BrowserContextKeyedAPIFactory<FeedbackPrivateAPI> >
     47     g_factory = LAZY_INSTANCE_INITIALIZER;
     48 
     49 // static
     50 BrowserContextKeyedAPIFactory<FeedbackPrivateAPI>*
     51 FeedbackPrivateAPI::GetFactoryInstance() {
     52   return g_factory.Pointer();
     53 }
     54 
     55 FeedbackPrivateAPI::FeedbackPrivateAPI(content::BrowserContext* context)
     56     : browser_context_(context), service_(FeedbackService::CreateInstance()) {}
     57 
     58 FeedbackPrivateAPI::~FeedbackPrivateAPI() {
     59   delete service_;
     60   service_ = NULL;
     61 }
     62 
     63 FeedbackService* FeedbackPrivateAPI::GetService() const {
     64   return service_;
     65 }
     66 
     67 void FeedbackPrivateAPI::RequestFeedback(
     68     const std::string& description_template,
     69     const std::string& category_tag,
     70     const GURL& page_url) {
     71   // TODO(rkc): Remove logging once crbug.com/284662 is closed.
     72   LOG(WARNING) << "FEEDBACK_DEBUG: Feedback requested.";
     73   if (browser_context_ && EventRouter::Get(browser_context_)) {
     74     FeedbackInfo info;
     75     info.description = description_template;
     76     info.category_tag = make_scoped_ptr(new std::string(category_tag));
     77     info.page_url = make_scoped_ptr(new std::string(page_url.spec()));
     78     info.system_information.reset(new SystemInformationList);
     79     // The manager is only available if tracing is enabled.
     80     if (TracingManager* manager = TracingManager::Get()) {
     81       info.trace_id.reset(new int(manager->RequestTrace()));
     82     }
     83 
     84     scoped_ptr<base::ListValue> args(new base::ListValue());
     85     args->Append(info.ToValue().release());
     86 
     87     scoped_ptr<Event> event(new Event(
     88         feedback_private::OnFeedbackRequested::kEventName, args.Pass()));
     89     event->restrict_to_browser_context = browser_context_;
     90 
     91     // TODO(rkc): Remove logging once crbug.com/284662 is closed.
     92     LOG(WARNING) << "FEEDBACK_DEBUG: Dispatching onFeedbackRequested event.";
     93     EventRouter::Get(browser_context_)
     94         ->DispatchEventToExtension(kFeedbackExtensionId, event.Pass());
     95   }
     96 }
     97 
     98 // static
     99 base::Closure* FeedbackPrivateGetStringsFunction::test_callback_ = NULL;
    100 
    101 bool FeedbackPrivateGetStringsFunction::RunSync() {
    102   base::DictionaryValue* dict = new base::DictionaryValue();
    103   SetResult(dict);
    104 
    105 #define SET_STRING(id, idr) \
    106   dict->SetString(id, l10n_util::GetStringUTF16(idr))
    107   SET_STRING("page-title", IDS_FEEDBACK_REPORT_PAGE_TITLE);
    108   SET_STRING("page-url", IDS_FEEDBACK_REPORT_URL_LABEL);
    109   SET_STRING("screenshot", IDS_FEEDBACK_SCREENSHOT_LABEL);
    110   SET_STRING("user-email", IDS_FEEDBACK_USER_EMAIL_LABEL);
    111 #if defined(OS_CHROMEOS)
    112   SET_STRING("sys-info",
    113              IDS_FEEDBACK_INCLUDE_SYSTEM_INFORMATION_AND_METRICS_CHKBOX);
    114 #else
    115   SET_STRING("sys-info", IDS_FEEDBACK_INCLUDE_SYSTEM_INFORMATION_CHKBOX);
    116 #endif
    117   SET_STRING("attach-file-label", IDS_FEEDBACK_ATTACH_FILE_LABEL);
    118   SET_STRING("attach-file-note", IDS_FEEDBACK_ATTACH_FILE_NOTE);
    119   SET_STRING("attach-file-to-big", IDS_FEEDBACK_ATTACH_FILE_TO_BIG);
    120   SET_STRING("reading-file", IDS_FEEDBACK_READING_FILE);
    121   SET_STRING("send-report", IDS_FEEDBACK_SEND_REPORT);
    122   SET_STRING("cancel", IDS_CANCEL);
    123   SET_STRING("no-description", IDS_FEEDBACK_NO_DESCRIPTION);
    124   SET_STRING("privacy-note", IDS_FEEDBACK_PRIVACY_NOTE);
    125   SET_STRING("performance-trace",
    126              IDS_FEEDBACK_INCLUDE_PERFORMANCE_TRACE_CHECKBOX);
    127 #undef SET_STRING
    128 
    129   webui::SetFontAndTextDirection(dict);
    130 
    131   if (test_callback_ && !test_callback_->is_null())
    132     test_callback_->Run();
    133 
    134   return true;
    135 }
    136 
    137 bool FeedbackPrivateGetUserEmailFunction::RunSync() {
    138   // TODO(rkc): Remove logging once crbug.com/284662 is closed.
    139   LOG(WARNING) << "FEEDBACK_DEBUG: User e-mail requested.";
    140   FeedbackService* service =
    141       FeedbackPrivateAPI::GetFactoryInstance()->Get(GetProfile())->GetService();
    142   DCHECK(service);
    143   SetResult(new base::StringValue(service->GetUserEmail()));
    144   return true;
    145 }
    146 
    147 bool FeedbackPrivateGetSystemInformationFunction::RunAsync() {
    148   // TODO(rkc): Remove logging once crbug.com/284662 is closed.
    149   LOG(WARNING) << "FEEDBACK_DEBUG: System information requested.";
    150   FeedbackService* service =
    151       FeedbackPrivateAPI::GetFactoryInstance()->Get(GetProfile())->GetService();
    152   DCHECK(service);
    153   service->GetSystemInformation(
    154       base::Bind(
    155           &FeedbackPrivateGetSystemInformationFunction::OnCompleted, this));
    156   return true;
    157 }
    158 
    159 void FeedbackPrivateGetSystemInformationFunction::OnCompleted(
    160     const SystemInformationList& sys_info) {
    161   results_ = feedback_private::GetSystemInformation::Results::Create(
    162       sys_info);
    163   SendResponse(true);
    164 }
    165 
    166 bool FeedbackPrivateSendFeedbackFunction::RunAsync() {
    167   scoped_ptr<feedback_private::SendFeedback::Params> params(
    168       feedback_private::SendFeedback::Params::Create(*args_));
    169   EXTENSION_FUNCTION_VALIDATE(params.get());
    170 
    171   const FeedbackInfo &feedback_info = params->feedback;
    172 
    173   std::string attached_file_uuid;
    174   if (feedback_info.attached_file_blob_uuid.get() &&
    175       !feedback_info.attached_file_blob_uuid->empty())
    176     attached_file_uuid = *feedback_info.attached_file_blob_uuid;
    177 
    178   std::string screenshot_uuid;
    179   if (feedback_info.screenshot_blob_uuid.get() &&
    180       !feedback_info.screenshot_blob_uuid->empty())
    181     screenshot_uuid = *feedback_info.screenshot_blob_uuid;
    182 
    183   // Populate feedback data.
    184   scoped_refptr<FeedbackData> feedback_data(new FeedbackData());
    185   feedback_data->set_context(GetProfile());
    186   feedback_data->set_description(feedback_info.description);
    187 
    188   if (feedback_info.category_tag.get())
    189     feedback_data->set_category_tag(*feedback_info.category_tag.get());
    190   if (feedback_info.page_url.get())
    191     feedback_data->set_page_url(*feedback_info.page_url.get());
    192   if (feedback_info.email.get())
    193     feedback_data->set_user_email(*feedback_info.email.get());
    194 
    195   if (!attached_file_uuid.empty()) {
    196     feedback_data->set_attached_filename(
    197         StripFakepath((*feedback_info.attached_file.get()).name));
    198     feedback_data->set_attached_file_uuid(attached_file_uuid);
    199   }
    200 
    201   if (!screenshot_uuid.empty())
    202     feedback_data->set_screenshot_uuid(screenshot_uuid);
    203 
    204   if (feedback_info.trace_id.get()) {
    205     feedback_data->set_trace_id(*feedback_info.trace_id.get());
    206   }
    207 
    208   scoped_ptr<FeedbackData::SystemLogsMap> sys_logs(
    209       new FeedbackData::SystemLogsMap);
    210   SystemInformationList* sys_info = feedback_info.system_information.get();
    211   if (sys_info) {
    212     for (SystemInformationList::iterator it = sys_info->begin();
    213          it != sys_info->end(); ++it)
    214       (*sys_logs.get())[it->get()->key] = it->get()->value;
    215   }
    216   feedback_data->SetAndCompressSystemInfo(sys_logs.Pass());
    217 
    218   FeedbackService* service =
    219       FeedbackPrivateAPI::GetFactoryInstance()->Get(GetProfile())->GetService();
    220   DCHECK(service);
    221 
    222   if (feedback_info.send_histograms) {
    223     scoped_ptr<std::string> histograms(new std::string);
    224     service->GetHistograms(histograms.get());
    225     if (!histograms->empty())
    226       feedback_data->SetAndCompressHistograms(histograms.Pass());
    227   }
    228 
    229   service->SendFeedback(
    230       GetProfile(),
    231       feedback_data,
    232       base::Bind(&FeedbackPrivateSendFeedbackFunction::OnCompleted, this));
    233 
    234   return true;
    235 }
    236 
    237 void FeedbackPrivateSendFeedbackFunction::OnCompleted(
    238     bool success) {
    239   results_ = feedback_private::SendFeedback::Results::Create(
    240       success ? feedback_private::STATUS_SUCCESS :
    241                 feedback_private::STATUS_DELAYED);
    242   SendResponse(true);
    243 }
    244 
    245 }  // namespace extensions
    246