| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/bug_report_util.h" | 5 #include "chrome/browser/bug_report_util.h" |
| 6 | 6 |
| 7 #include <sstream> |
| 7 #include <string> | 8 #include <string> |
| 8 | 9 |
| 10 #include "app/l10n_util.h" |
| 11 #include "base/command_line.h" |
| 9 #include "base/file_version_info.h" | 12 #include "base/file_version_info.h" |
| 13 #include "base/file_util.h" |
| 14 #include "base/singleton.h" |
| 10 #include "base/string_util.h" | 15 #include "base/string_util.h" |
| 11 #include "base/utf_string_conversions.h" | 16 #include "base/utf_string_conversions.h" |
| 17 #include "chrome/browser/browser_list.h" |
| 12 #include "chrome/browser/browser_process_impl.h" | 18 #include "chrome/browser/browser_process_impl.h" |
| 13 #include "chrome/browser/profile.h" | 19 #include "chrome/browser/profile.h" |
| 14 #include "chrome/browser/safe_browsing/safe_browsing_util.h" | 20 #include "chrome/browser/safe_browsing/safe_browsing_util.h" |
| 15 #include "chrome/browser/tab_contents/tab_contents.h" | 21 #include "chrome/browser/tab_contents/tab_contents.h" |
| 16 #include "chrome/common/chrome_version_info.h" | 22 #include "chrome/common/chrome_version_info.h" |
| 23 #include "chrome/common/chrome_switches.h" |
| 17 #include "chrome/common/net/url_fetcher.h" | 24 #include "chrome/common/net/url_fetcher.h" |
| 18 #include "googleurl/src/gurl.h" | 25 #include "googleurl/src/gurl.h" |
| 19 #include "grit/locale_settings.h" | 26 #include "grit/locale_settings.h" |
| 27 #include "grit/theme_resources.h" |
| 20 #include "net/url_request/url_request_status.h" | 28 #include "net/url_request/url_request_status.h" |
| 21 #include "unicode/locid.h" | 29 #include "unicode/locid.h" |
| 22 | 30 |
| 31 #if defined(OS_CHROMEOS) |
| 32 #include "chrome/browser/chromeos/notifications/system_notification.h" |
| 33 #endif |
| 34 |
| 23 namespace { | 35 namespace { |
| 24 | 36 |
| 25 const int kBugReportVersion = 1; | 37 const int kBugReportVersion = 1; |
| 26 | 38 |
| 27 const char kReportPhishingUrl[] = | 39 const char kReportPhishingUrl[] = |
| 28 "http://www.google.com/safebrowsing/report_phish/"; | 40 "http://www.google.com/safebrowsing/report_phish/"; |
| 29 | 41 |
| 30 // URL to post bug reports to. | 42 // URL to post bug reports to. |
| 31 const char* const kBugReportPostUrl = | 43 static char const kBugReportPostUrl[] = |
| 32 "https://www.google.com/tools/feedback/chrome/__submit"; | 44 "https://www.google.com/tools/feedback/chrome/__submit"; |
| 33 | 45 |
| 34 const char* const kProtBufMimeType = "application/x-protobuf"; | 46 static char const kProtBufMimeType[] = "application/x-protobuf"; |
| 35 const char* const kPngMimeType = "image/png"; | 47 static char const kPngMimeType[] = "image/png"; |
| 36 | 48 |
| 37 // Tags we use in product specific data | 49 // Tags we use in product specific data |
| 38 const char* const kPageTitleTag = "PAGE TITLE"; | 50 static char const kPageTitleTag[] = "PAGE TITLE"; |
| 39 const char* const kProblemTypeIdTag = "PROBLEM TYPE ID"; | 51 static char const kProblemTypeIdTag[] = "PROBLEM TYPE ID"; |
| 40 const char* const kProblemTypeTag = "PROBLEM TYPE"; | 52 static char const kProblemTypeTag[] = "PROBLEM TYPE"; |
| 41 const char* const kChromeVersionTag = "CHROME VERSION"; | 53 static char const kChromeVersionTag[] = "CHROME VERSION"; |
| 42 const char* const kOsVersionTag = "OS VERSION"; | 54 static char const kOsVersionTag[] = "OS VERSION"; |
| 55 |
| 56 static char const kNotificationId[] = "feedback.chromeos"; |
| 57 |
| 58 static int const kHttpPostSuccessNoContent = 204; |
| 59 static int const kHttpPostFailNoConnection = -1; |
| 60 static int const kHttpPostFailClientError = 400; |
| 61 static int const kHttpPostFailServerError = 500; |
| 62 |
| 63 } // namespace |
| 43 | 64 |
| 44 | 65 |
| 45 } // namespace | 66 #if defined(OS_CHROMEOS) |
| 67 class FeedbackNotification { |
| 68 public: |
| 69 // Previous notification cleanup is handled by scoped_ptr. |
| 70 // Note: notification will show only on one profile at a time. |
| 71 void Show(Profile* profile, const string16& message, bool urgent) { |
| 72 notification_.reset( |
| 73 new chromeos::SystemNotification(profile, kNotificationId, |
| 74 IDR_STATUSBAR_FEEDBACK, |
| 75 l10n_util::GetStringUTF16( |
| 76 IDS_BUGREPORT_NOTIFICATION_TITLE))); |
| 77 notification_->Show(message, urgent); |
| 78 } |
| 79 |
| 80 private: |
| 81 FeedbackNotification() {} |
| 82 friend struct DefaultSingletonTraits<FeedbackNotification>; |
| 83 |
| 84 scoped_ptr<chromeos::SystemNotification> notification_; |
| 85 DISALLOW_COPY_AND_ASSIGN(FeedbackNotification); |
| 86 }; |
| 87 #endif |
| 46 | 88 |
| 47 // Simple URLFetcher::Delegate to clean up URLFetcher on completion. | 89 // Simple URLFetcher::Delegate to clean up URLFetcher on completion. |
| 48 class BugReportUtil::PostCleanup : public URLFetcher::Delegate { | 90 class BugReportUtil::PostCleanup : public URLFetcher::Delegate { |
| 49 public: | 91 public: |
| 92 #if defined(OS_CHROMEOS) |
| 93 explicit PostCleanup(Profile* profile); |
| 94 #else |
| 50 PostCleanup(); | 95 PostCleanup(); |
| 51 | 96 #endif |
| 52 // Overridden from URLFetcher::Delegate. | 97 // Overridden from URLFetcher::Delegate. |
| 53 virtual void OnURLFetchComplete(const URLFetcher* source, | 98 virtual void OnURLFetchComplete(const URLFetcher* source, |
| 54 const GURL& url, | 99 const GURL& url, |
| 55 const URLRequestStatus& status, | 100 const URLRequestStatus& status, |
| 56 int response_code, | 101 int response_code, |
| 57 const ResponseCookies& cookies, | 102 const ResponseCookies& cookies, |
| 58 const std::string& data); | 103 const std::string& data); |
| 59 | 104 |
| 60 protected: | 105 protected: |
| 61 virtual ~PostCleanup() {} | 106 virtual ~PostCleanup() {} |
| 62 | 107 |
| 63 private: | 108 private: |
| 109 Profile* profile_; |
| 110 |
| 64 DISALLOW_COPY_AND_ASSIGN(PostCleanup); | 111 DISALLOW_COPY_AND_ASSIGN(PostCleanup); |
| 65 }; | 112 }; |
| 66 | 113 |
| 67 BugReportUtil::PostCleanup::PostCleanup() { | 114 #if defined(OS_CHROMEOS) |
| 115 BugReportUtil::PostCleanup::PostCleanup(Profile* profile) |
| 116 : profile_(profile) { |
| 117 #else |
| 118 BugReportUtil::PostCleanup::PostCleanup() { |
| 119 #endif |
| 68 } | 120 } |
| 69 | 121 |
| 70 void BugReportUtil::PostCleanup::OnURLFetchComplete( | 122 void BugReportUtil::PostCleanup::OnURLFetchComplete( |
| 71 const URLFetcher* source, | 123 const URLFetcher* source, |
| 72 const GURL& url, | 124 const GURL& url, |
| 73 const URLRequestStatus& status, | 125 const URLRequestStatus& status, |
| 74 int response_code, | 126 int response_code, |
| 75 const ResponseCookies& cookies, | 127 const ResponseCookies& cookies, |
| 76 const std::string& data) { | 128 const std::string& data) { |
| 77 // if not 204, something went wrong | 129 |
| 78 if (response_code != 204) | 130 std::stringstream error_stream; |
| 79 LOG(WARNING) << "Submission to feedback server failed. Response code: " << | 131 if (response_code == kHttpPostSuccessNoContent) { |
| 80 response_code << std::endl; | 132 error_stream << "Success"; |
| 133 } else if (response_code == kHttpPostFailNoConnection) { |
| 134 error_stream << "No connection to server."; |
| 135 } else if ((response_code > kHttpPostFailClientError) && |
| 136 (response_code < kHttpPostFailServerError)) { |
| 137 error_stream << "Client error: HTTP response code " << response_code; |
| 138 } else if (response_code > kHttpPostFailServerError) { |
| 139 error_stream << "Server error: HTTP response code " << response_code; |
| 140 } else { |
| 141 error_stream << "Unknown error: HTTP response code " << response_code; |
| 142 } |
| 143 |
| 144 LOG(WARNING) << "Submission to feedback server (" << url << |
| 145 ") status: " << error_stream.str() << std::endl; |
| 146 |
| 147 #if defined(OS_CHROMEOS) |
| 148 // Show the notification to the user; this notification will stay active till |
| 149 // either the user closes it, or we display another notification. |
| 150 if (response_code == kHttpPostSuccessNoContent) { |
| 151 Singleton<FeedbackNotification>()->Show(profile_, l10n_util::GetStringUTF16( |
| 152 IDS_BUGREPORT_FEEDBACK_STATUS_SUCCESS), false); |
| 153 } else { |
| 154 Singleton<FeedbackNotification>()->Show(profile_, |
| 155 l10n_util::GetStringFUTF16(IDS_BUGREPORT_FEEDBACK_STATUS_FAIL, |
| 156 ASCIIToUTF16(error_stream.str())), |
| 157 true); |
| 158 } |
| 159 #endif |
| 160 |
| 81 // Delete the URLFetcher. | 161 // Delete the URLFetcher. |
| 82 delete source; | 162 delete source; |
| 83 // And then delete ourselves. | 163 // And then delete ourselves. |
| 84 delete this; | 164 delete this; |
| 85 } | 165 } |
| 86 | 166 |
| 87 // static | 167 // static |
| 88 void BugReportUtil::SetOSVersion(std::string *os_version) { | 168 void BugReportUtil::SetOSVersion(std::string *os_version) { |
| 89 #if defined(OS_WIN) | 169 #if defined(OS_WIN) |
| 90 OSVERSIONINFO osvi; | 170 OSVERSIONINFO osvi; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 105 int32 minor; | 185 int32 minor; |
| 106 int32 bugFix; | 186 int32 bugFix; |
| 107 base::SysInfo::OperatingSystemVersionNumbers(&major, &minor, &bugFix); | 187 base::SysInfo::OperatingSystemVersionNumbers(&major, &minor, &bugFix); |
| 108 *os_version = StringPrintf("%d.%d.%d", major, minor, bugFix); | 188 *os_version = StringPrintf("%d.%d.%d", major, minor, bugFix); |
| 109 #else | 189 #else |
| 110 *os_version = "unknown"; | 190 *os_version = "unknown"; |
| 111 #endif | 191 #endif |
| 112 } | 192 } |
| 113 | 193 |
| 114 // static | 194 // static |
| 195 std::string BugReportUtil::feedback_server_(""); |
| 196 |
| 197 // static |
| 198 void BugReportUtil::SetFeedbackServer(const std::string& server) { |
| 199 feedback_server_ = server; |
| 200 } |
| 201 |
| 202 |
| 203 // static |
| 115 void BugReportUtil::AddFeedbackData( | 204 void BugReportUtil::AddFeedbackData( |
| 116 userfeedback::ExternalExtensionSubmit* feedback_data, | 205 userfeedback::ExternalExtensionSubmit* feedback_data, |
| 117 const std::string& key, const std::string& value) { | 206 const std::string& key, const std::string& value) { |
| 207 // We have no reason to log any empty values - gives us no data |
| 208 if (value == "") return; |
| 118 // Create log_value object and add it to the web_data object | 209 // Create log_value object and add it to the web_data object |
| 119 userfeedback::ProductSpecificData log_value; | 210 userfeedback::ProductSpecificData log_value; |
| 120 log_value.set_key(key); | 211 log_value.set_key(key); |
| 121 log_value.set_value(value); | 212 log_value.set_value(value); |
| 122 userfeedback::WebData* web_data = feedback_data->mutable_web_data(); | 213 userfeedback::WebData* web_data = feedback_data->mutable_web_data(); |
| 123 *(web_data->add_product_specific_data()) = log_value; | 214 *(web_data->add_product_specific_data()) = log_value; |
| 124 } | 215 } |
| 125 | 216 |
| 126 // static | 217 // static |
| 127 void BugReportUtil::SendReport(Profile* profile, | 218 void BugReportUtil::SendReport(Profile* profile, |
| 128 const std::string& page_title_text, | 219 const std::string& page_title_text, |
| 129 int problem_type, | 220 int problem_type, |
| 130 const std::string& page_url_text, | 221 const std::string& page_url_text, |
| 131 const std::string& user_email_text, | |
| 132 const std::string& description, | 222 const std::string& description, |
| 133 const char* png_data, | 223 const char* png_data, |
| 134 int png_data_length, | 224 int png_data_length, |
| 135 int png_width, | 225 int png_width, |
| 136 #if defined(OS_CHROMEOS) | 226 #if defined(OS_CHROMEOS) |
| 137 int png_height, | 227 int png_height, |
| 138 const std::string& problem_type_text, | 228 const std::string& user_email_text, |
| 139 const chromeos::LogDictionaryType* const sys_info) { | 229 const chromeos::LogDictionaryType* const sys_info) { |
| 140 #else | 230 #else |
| 141 int png_height) { | 231 int png_height) { |
| 142 #endif | 232 #endif |
| 143 GURL post_url(kBugReportPostUrl); | 233 GURL post_url; |
| 234 |
| 235 if (CommandLine::ForCurrentProcess()-> |
| 236 HasSwitch(switches::kFeedbackServer)) |
| 237 post_url = GURL(CommandLine::ForCurrentProcess()-> |
| 238 GetSwitchValueASCII(switches::kFeedbackServer)); |
| 239 else |
| 240 post_url = GURL(kBugReportPostUrl); |
| 144 | 241 |
| 145 // Create google feedback protocol buffer objects | 242 // Create google feedback protocol buffer objects |
| 146 userfeedback::ExternalExtensionSubmit feedback_data; | 243 userfeedback::ExternalExtensionSubmit feedback_data; |
| 147 // type id set to 0, unused field but needs to be initialized to 0 | 244 // type id set to 0, unused field but needs to be initialized to 0 |
| 148 feedback_data.set_type_id(0); | 245 feedback_data.set_type_id(0); |
| 149 | 246 |
| 150 userfeedback::CommonData* common_data = feedback_data.mutable_common_data(); | 247 userfeedback::CommonData* common_data = feedback_data.mutable_common_data(); |
| 151 userfeedback::WebData* web_data = feedback_data.mutable_web_data(); | 248 userfeedback::WebData* web_data = feedback_data.mutable_web_data(); |
| 152 | 249 |
| 153 // Set GAIA id to 0. We're not using gaia id's for recording | 250 // Set GAIA id to 0. We're not using gaia id's for recording |
| 154 // use feedback - we're using the e-mail field, allows users to | 251 // use feedback - we're using the e-mail field, allows users to |
| 155 // submit feedback from incognito mode and specify any mail id | 252 // submit feedback from incognito mode and specify any mail id |
| 156 // they wish | 253 // they wish |
| 157 common_data->set_gaia_id(0); | 254 common_data->set_gaia_id(0); |
| 158 | 255 |
| 159 // Add the page title. | 256 // Add the page title. |
| 160 AddFeedbackData(&feedback_data, std::string(kPageTitleTag), | 257 AddFeedbackData(&feedback_data, std::string(kPageTitleTag), |
| 161 page_title_text); | 258 page_title_text); |
| 162 | 259 |
| 163 AddFeedbackData(&feedback_data, std::string(kProblemTypeIdTag), | |
| 164 StringPrintf("%d\r\n", problem_type)); | |
| 165 | |
| 166 #if defined(OS_CHROMEOS) | 260 #if defined(OS_CHROMEOS) |
| 167 AddFeedbackData(&feedback_data, std::string(kProblemTypeTag), | |
| 168 problem_type_text); | |
| 169 #endif | |
| 170 | |
| 171 // Add the user e-mail to the feedback object | 261 // Add the user e-mail to the feedback object |
| 172 common_data->set_user_email(user_email_text); | 262 common_data->set_user_email(user_email_text); |
| 263 #endif |
| 173 | 264 |
| 174 // Add the description to the feedback object | 265 // Add the description to the feedback object |
| 175 common_data->set_description(description); | 266 common_data->set_description(description); |
| 176 | 267 |
| 177 // Add the language | 268 // Add the language |
| 178 std::string chrome_locale = g_browser_process->GetApplicationLocale(); | 269 std::string chrome_locale = g_browser_process->GetApplicationLocale(); |
| 179 common_data->set_source_descripton_language(chrome_locale); | 270 common_data->set_source_description_language(chrome_locale); |
| 180 | 271 |
| 181 // Set the url | 272 // Set the url |
| 182 web_data->set_url(page_url_text); | 273 web_data->set_url(page_url_text); |
| 183 | 274 |
| 184 // Add the Chrome version | 275 // Add the Chrome version |
| 185 std::string chrome_version; | 276 std::string chrome_version; |
| 186 scoped_ptr<FileVersionInfo> version_info(chrome::GetChromeVersionInfo()); | 277 scoped_ptr<FileVersionInfo> version_info(chrome::GetChromeVersionInfo()); |
| 187 if (version_info.get()) { | 278 if (version_info.get()) { |
| 188 chrome_version = WideToUTF8(version_info->product_name()) + " - " + | 279 chrome_version = WideToUTF8(version_info->product_name()) + " - " + |
| 189 WideToUTF8(version_info->file_version()) + | 280 WideToUTF8(version_info->file_version()) + |
| (...skipping 25 matching lines...) Expand all Loading... |
| 215 userfeedback::Dimensions dimensions; | 306 userfeedback::Dimensions dimensions; |
| 216 dimensions.set_width(static_cast<float>(png_width)); | 307 dimensions.set_width(static_cast<float>(png_width)); |
| 217 dimensions.set_height(static_cast<float>(png_height)); | 308 dimensions.set_height(static_cast<float>(png_height)); |
| 218 *(screenshot.mutable_dimensions()) = dimensions; | 309 *(screenshot.mutable_dimensions()) = dimensions; |
| 219 screenshot.set_binary_content(std::string(png_data, png_data_length)); | 310 screenshot.set_binary_content(std::string(png_data, png_data_length)); |
| 220 | 311 |
| 221 // Set the screenshot object in feedback | 312 // Set the screenshot object in feedback |
| 222 *(feedback_data.mutable_screenshot()) = screenshot; | 313 *(feedback_data.mutable_screenshot()) = screenshot; |
| 223 } | 314 } |
| 224 | 315 |
| 316 // Set our Chrome specific data |
| 317 userfeedback::ChromeData chrome_data; |
| 318 #if defined(OS_CHROMEOS) |
| 319 chrome_data.set_chrome_platform( |
| 320 userfeedback::ChromeData_ChromePlatform_CHROME_OS); |
| 321 userfeedback::ChromeOsData chrome_os_data; |
| 322 chrome_os_data.set_category( |
| 323 (userfeedback::ChromeOsData_ChromeOsCategory) problem_type); |
| 324 *(chrome_data.mutable_chrome_os_data()) = chrome_os_data; |
| 325 #else |
| 326 chrome_data.set_chrome_platform( |
| 327 userfeedback::ChromeData_ChromePlatform_CHROME_BROWSER); |
| 328 userfeedback::ChromeBrowserData chrome_browser_data; |
| 329 chrome_browser_data.set_category( |
| 330 (userfeedback::ChromeBrowserData_ChromeBrowserCategory) problem_type); |
| 331 *(chrome_data.mutable_chrome_browser_data()) = chrome_browser_data; |
| 332 #endif |
| 333 |
| 334 *(feedback_data.mutable_chrome_data()) = chrome_data; |
| 335 |
| 225 // We have the body of our POST, so send it off to the server. | 336 // We have the body of our POST, so send it off to the server. |
| 226 URLFetcher* fetcher = new URLFetcher(post_url, URLFetcher::POST, | 337 URLFetcher* fetcher = new URLFetcher(post_url, URLFetcher::POST, |
| 227 new BugReportUtil::PostCleanup); | 338 #if defined(OS_CHROMEOS) |
| 339 new BugReportUtil::PostCleanup(profile)); |
| 340 #else |
| 341 new BugReportUtil::PostCleanup()); |
| 342 #endif |
| 228 fetcher->set_request_context(profile->GetRequestContext()); | 343 fetcher->set_request_context(profile->GetRequestContext()); |
| 229 | 344 |
| 230 std::string post_body; | 345 std::string post_body; |
| 231 feedback_data.SerializeToString(&post_body); | 346 feedback_data.SerializeToString(&post_body); |
| 232 fetcher->set_upload_data(std::string(kProtBufMimeType), post_body); | 347 fetcher->set_upload_data(std::string(kProtBufMimeType), post_body); |
| 233 fetcher->Start(); | 348 fetcher->Start(); |
| 234 } | 349 } |
| 235 | 350 |
| 236 // static | 351 // static |
| 237 void BugReportUtil::ReportPhishing(TabContents* currentTab, | 352 void BugReportUtil::ReportPhishing(TabContents* currentTab, |
| 238 const std::string& phishing_url) { | 353 const std::string& phishing_url) { |
| 239 currentTab->controller().LoadURL( | 354 currentTab->controller().LoadURL( |
| 240 safe_browsing_util::GeneratePhishingReportUrl( | 355 safe_browsing_util::GeneratePhishingReportUrl( |
| 241 kReportPhishingUrl, phishing_url), | 356 kReportPhishingUrl, phishing_url), |
| 242 GURL(), | 357 GURL(), |
| 243 PageTransition::LINK); | 358 PageTransition::LINK); |
| 244 } | 359 } |
| OLD | NEW |