• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
StripFakepath(const std::string & path)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>*
GetFactoryInstance()51 FeedbackPrivateAPI::GetFactoryInstance() {
52   return g_factory.Pointer();
53 }
54 
FeedbackPrivateAPI(content::BrowserContext * context)55 FeedbackPrivateAPI::FeedbackPrivateAPI(content::BrowserContext* context)
56     : browser_context_(context), service_(FeedbackService::CreateInstance()) {}
57 
~FeedbackPrivateAPI()58 FeedbackPrivateAPI::~FeedbackPrivateAPI() {
59   delete service_;
60   service_ = NULL;
61 }
62 
GetService() const63 FeedbackService* FeedbackPrivateAPI::GetService() const {
64   return service_;
65 }
66 
RequestFeedback(const std::string & description_template,const std::string & category_tag,const GURL & page_url)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 
RunSync()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 
RunSync()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 
RunAsync()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 
OnCompleted(const SystemInformationList & sys_info)159 void FeedbackPrivateGetSystemInformationFunction::OnCompleted(
160     const SystemInformationList& sys_info) {
161   results_ = feedback_private::GetSystemInformation::Results::Create(
162       sys_info);
163   SendResponse(true);
164 }
165 
RunAsync()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 
OnCompleted(bool success)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