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 "chrome/grit/generated_resources.h" 16 #include "components/feedback/tracing_manager.h" 17 #include "extensions/browser/event_router.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 if (browser_context_ && EventRouter::Get(browser_context_)) { 72 FeedbackInfo info; 73 info.description = description_template; 74 info.category_tag = make_scoped_ptr(new std::string(category_tag)); 75 info.page_url = make_scoped_ptr(new std::string(page_url.spec())); 76 info.system_information.reset(new SystemInformationList); 77 // The manager is only available if tracing is enabled. 78 if (TracingManager* manager = TracingManager::Get()) { 79 info.trace_id.reset(new int(manager->RequestTrace())); 80 } 81 82 scoped_ptr<base::ListValue> args(new base::ListValue()); 83 args->Append(info.ToValue().release()); 84 85 scoped_ptr<Event> event(new Event( 86 feedback_private::OnFeedbackRequested::kEventName, args.Pass())); 87 event->restrict_to_browser_context = browser_context_; 88 89 EventRouter::Get(browser_context_) 90 ->DispatchEventToExtension(kFeedbackExtensionId, event.Pass()); 91 } 92 } 93 94 // static 95 base::Closure* FeedbackPrivateGetStringsFunction::test_callback_ = NULL; 96 97 bool FeedbackPrivateGetStringsFunction::RunSync() { 98 base::DictionaryValue* dict = new base::DictionaryValue(); 99 SetResult(dict); 100 101 #define SET_STRING(id, idr) \ 102 dict->SetString(id, l10n_util::GetStringUTF16(idr)) 103 SET_STRING("page-title", IDS_FEEDBACK_REPORT_PAGE_TITLE); 104 SET_STRING("page-url", IDS_FEEDBACK_REPORT_URL_LABEL); 105 SET_STRING("screenshot", IDS_FEEDBACK_SCREENSHOT_LABEL); 106 SET_STRING("user-email", IDS_FEEDBACK_USER_EMAIL_LABEL); 107 #if defined(OS_CHROMEOS) 108 SET_STRING("sys-info", 109 IDS_FEEDBACK_INCLUDE_SYSTEM_INFORMATION_AND_METRICS_CHKBOX); 110 #else 111 SET_STRING("sys-info", IDS_FEEDBACK_INCLUDE_SYSTEM_INFORMATION_CHKBOX); 112 #endif 113 SET_STRING("attach-file-label", IDS_FEEDBACK_ATTACH_FILE_LABEL); 114 SET_STRING("attach-file-note", IDS_FEEDBACK_ATTACH_FILE_NOTE); 115 SET_STRING("attach-file-to-big", IDS_FEEDBACK_ATTACH_FILE_TO_BIG); 116 SET_STRING("reading-file", IDS_FEEDBACK_READING_FILE); 117 SET_STRING("send-report", IDS_FEEDBACK_SEND_REPORT); 118 SET_STRING("cancel", IDS_CANCEL); 119 SET_STRING("no-description", IDS_FEEDBACK_NO_DESCRIPTION); 120 SET_STRING("privacy-note", IDS_FEEDBACK_PRIVACY_NOTE); 121 SET_STRING("performance-trace", 122 IDS_FEEDBACK_INCLUDE_PERFORMANCE_TRACE_CHECKBOX); 123 #undef SET_STRING 124 125 webui::SetFontAndTextDirection(dict); 126 127 if (test_callback_ && !test_callback_->is_null()) 128 test_callback_->Run(); 129 130 return true; 131 } 132 133 bool FeedbackPrivateGetUserEmailFunction::RunSync() { 134 FeedbackService* service = 135 FeedbackPrivateAPI::GetFactoryInstance()->Get(GetProfile())->GetService(); 136 DCHECK(service); 137 SetResult(new base::StringValue(service->GetUserEmail())); 138 return true; 139 } 140 141 bool FeedbackPrivateGetSystemInformationFunction::RunAsync() { 142 FeedbackService* service = 143 FeedbackPrivateAPI::GetFactoryInstance()->Get(GetProfile())->GetService(); 144 DCHECK(service); 145 service->GetSystemInformation( 146 base::Bind( 147 &FeedbackPrivateGetSystemInformationFunction::OnCompleted, this)); 148 return true; 149 } 150 151 void FeedbackPrivateGetSystemInformationFunction::OnCompleted( 152 const SystemInformationList& sys_info) { 153 results_ = feedback_private::GetSystemInformation::Results::Create( 154 sys_info); 155 SendResponse(true); 156 } 157 158 bool FeedbackPrivateSendFeedbackFunction::RunAsync() { 159 scoped_ptr<feedback_private::SendFeedback::Params> params( 160 feedback_private::SendFeedback::Params::Create(*args_)); 161 EXTENSION_FUNCTION_VALIDATE(params.get()); 162 163 const FeedbackInfo &feedback_info = params->feedback; 164 165 std::string attached_file_uuid; 166 if (feedback_info.attached_file_blob_uuid.get() && 167 !feedback_info.attached_file_blob_uuid->empty()) 168 attached_file_uuid = *feedback_info.attached_file_blob_uuid; 169 170 std::string screenshot_uuid; 171 if (feedback_info.screenshot_blob_uuid.get() && 172 !feedback_info.screenshot_blob_uuid->empty()) 173 screenshot_uuid = *feedback_info.screenshot_blob_uuid; 174 175 // Populate feedback data. 176 scoped_refptr<FeedbackData> feedback_data(new FeedbackData()); 177 feedback_data->set_context(GetProfile()); 178 feedback_data->set_description(feedback_info.description); 179 180 if (feedback_info.category_tag.get()) 181 feedback_data->set_category_tag(*feedback_info.category_tag.get()); 182 if (feedback_info.page_url.get()) 183 feedback_data->set_page_url(*feedback_info.page_url.get()); 184 if (feedback_info.email.get()) 185 feedback_data->set_user_email(*feedback_info.email.get()); 186 187 if (!attached_file_uuid.empty()) { 188 feedback_data->set_attached_filename( 189 StripFakepath((*feedback_info.attached_file.get()).name)); 190 feedback_data->set_attached_file_uuid(attached_file_uuid); 191 } 192 193 if (!screenshot_uuid.empty()) 194 feedback_data->set_screenshot_uuid(screenshot_uuid); 195 196 if (feedback_info.trace_id.get()) { 197 feedback_data->set_trace_id(*feedback_info.trace_id.get()); 198 } 199 200 scoped_ptr<FeedbackData::SystemLogsMap> sys_logs( 201 new FeedbackData::SystemLogsMap); 202 SystemInformationList* sys_info = feedback_info.system_information.get(); 203 if (sys_info) { 204 for (SystemInformationList::iterator it = sys_info->begin(); 205 it != sys_info->end(); ++it) 206 (*sys_logs.get())[it->get()->key] = it->get()->value; 207 } 208 feedback_data->SetAndCompressSystemInfo(sys_logs.Pass()); 209 210 FeedbackService* service = 211 FeedbackPrivateAPI::GetFactoryInstance()->Get(GetProfile())->GetService(); 212 DCHECK(service); 213 214 if (feedback_info.send_histograms) { 215 scoped_ptr<std::string> histograms(new std::string); 216 service->GetHistograms(histograms.get()); 217 if (!histograms->empty()) 218 feedback_data->SetAndCompressHistograms(histograms.Pass()); 219 } 220 221 service->SendFeedback( 222 GetProfile(), 223 feedback_data, 224 base::Bind(&FeedbackPrivateSendFeedbackFunction::OnCompleted, this)); 225 226 return true; 227 } 228 229 void FeedbackPrivateSendFeedbackFunction::OnCompleted( 230 bool success) { 231 results_ = feedback_private::SendFeedback::Results::Create( 232 success ? feedback_private::STATUS_SUCCESS : 233 feedback_private::STATUS_DELAYED); 234 SendResponse(true); 235 } 236 237 } // namespace extensions 238