| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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/views/bug_report_view.h" | 5 #include "chrome/browser/views/bug_report_view.h" |
| 6 | 6 |
| 7 #include "app/combobox_model.h" | 7 #include "app/combobox_model.h" |
| 8 #include "app/l10n_util.h" | 8 #include "app/l10n_util.h" |
| 9 #include "app/win_util.h" | 9 #include "app/win_util.h" |
| 10 #include "base/file_version_info.h" | 10 #include "base/file_version_info.h" |
| 11 #include "base/string_util.h" | 11 #include "base/string_util.h" |
| 12 #include "chrome/browser/bug_report_util.h" |
| 12 #include "chrome/browser/net/url_fetcher.h" | 13 #include "chrome/browser/net/url_fetcher.h" |
| 13 #include "chrome/browser/profile.h" | 14 #include "chrome/browser/profile.h" |
| 14 #include "chrome/browser/safe_browsing/safe_browsing_util.h" | 15 #include "chrome/browser/safe_browsing/safe_browsing_util.h" |
| 15 #include "chrome/browser/tab_contents/navigation_controller.h" | 16 #include "chrome/browser/tab_contents/navigation_controller.h" |
| 16 #include "chrome/browser/tab_contents/navigation_entry.h" | 17 #include "chrome/browser/tab_contents/navigation_entry.h" |
| 17 #include "chrome/browser/tab_contents/tab_contents.h" | 18 #include "chrome/browser/tab_contents/tab_contents.h" |
| 18 #include "chrome/common/pref_names.h" | 19 #include "chrome/common/pref_names.h" |
| 19 #include "chrome/common/pref_service.h" | 20 #include "chrome/common/pref_service.h" |
| 20 #include "grit/chromium_strings.h" | 21 #include "grit/chromium_strings.h" |
| 21 #include "grit/generated_resources.h" | 22 #include "grit/generated_resources.h" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 32 | 33 |
| 33 using views::ColumnSet; | 34 using views::ColumnSet; |
| 34 using views::GridLayout; | 35 using views::GridLayout; |
| 35 | 36 |
| 36 // Report a bug data version. | 37 // Report a bug data version. |
| 37 static const int kBugReportVersion = 1; | 38 static const int kBugReportVersion = 1; |
| 38 | 39 |
| 39 // Number of lines description field can display at one time. | 40 // Number of lines description field can display at one time. |
| 40 static const int kDescriptionLines = 5; | 41 static const int kDescriptionLines = 5; |
| 41 | 42 |
| 42 // Google's phishing reporting URL. | |
| 43 static const char kReportPhishingUrl[] = | |
| 44 "http://www.google.com/safebrowsing/report_phish/"; | |
| 45 | |
| 46 class BugReportComboBoxModel : public ComboboxModel { | 43 class BugReportComboBoxModel : public ComboboxModel { |
| 47 public: | 44 public: |
| 48 BugReportComboBoxModel() {} | 45 BugReportComboBoxModel() {} |
| 49 | 46 |
| 50 enum BugType { | 47 enum BugType { |
| 51 PAGE_WONT_LOAD = 0, | 48 PAGE_WONT_LOAD = 0, |
| 52 PAGE_LOOKS_ODD, | 49 PAGE_LOOKS_ODD, |
| 53 PHISHING_PAGE, | 50 PHISHING_PAGE, |
| 54 CANT_SIGN_IN, | 51 CANT_SIGN_IN, |
| 55 CHROME_MISBEHAVES, | 52 CHROME_MISBEHAVES, |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 88 default: | 85 default: |
| 89 NOTREACHED(); | 86 NOTREACHED(); |
| 90 return std::wstring(); | 87 return std::wstring(); |
| 91 } | 88 } |
| 92 } | 89 } |
| 93 | 90 |
| 94 private: | 91 private: |
| 95 DISALLOW_COPY_AND_ASSIGN(BugReportComboBoxModel); | 92 DISALLOW_COPY_AND_ASSIGN(BugReportComboBoxModel); |
| 96 }; | 93 }; |
| 97 | 94 |
| 98 // Simple URLFetcher::Delegate to clean up URLFetcher on completion | |
| 99 // (since the BugReportView will be gone by then). | |
| 100 class BugReportView::PostCleanup : public URLFetcher::Delegate { | |
| 101 public: | |
| 102 PostCleanup(); | |
| 103 // Overridden from URLFetcher::Delegate. | |
| 104 virtual void OnURLFetchComplete(const URLFetcher* source, | |
| 105 const GURL& url, | |
| 106 const URLRequestStatus& status, | |
| 107 int response_code, | |
| 108 const ResponseCookies& cookies, | |
| 109 const std::string& data); | |
| 110 private: | |
| 111 DISALLOW_COPY_AND_ASSIGN(PostCleanup); | |
| 112 }; | |
| 113 | |
| 114 namespace browser { | 95 namespace browser { |
| 115 | 96 |
| 116 // Global "display this dialog" function declared in browser_dialogs.h. | 97 // Global "display this dialog" function declared in browser_dialogs.h. |
| 117 void ShowBugReportView(views::Widget* parent, | 98 void ShowBugReportView(views::Widget* parent, |
| 118 Profile* profile, | 99 Profile* profile, |
| 119 TabContents* tab) { | 100 TabContents* tab) { |
| 120 BugReportView* view = new BugReportView(profile, tab); | 101 BugReportView* view = new BugReportView(profile, tab); |
| 121 | 102 |
| 122 // Grab an exact snapshot of the window that the user is seeing (i.e. as | 103 // Grab an exact snapshot of the window that the user is seeing (i.e. as |
| 123 // rendered--do not re-render, and include windowed plugins). | 104 // rendered--do not re-render, and include windowed plugins). |
| 124 std::vector<unsigned char> *screenshot_png = new std::vector<unsigned char>; | 105 std::vector<unsigned char> *screenshot_png = new std::vector<unsigned char>; |
| 125 win_util::GrabWindowSnapshot(parent->GetNativeView(), screenshot_png); | 106 win_util::GrabWindowSnapshot(parent->GetNativeView(), screenshot_png); |
| 126 // The BugReportView takes ownership of the png data, and will dispose of | 107 // The BugReportView takes ownership of the png data, and will dispose of |
| 127 // it in its destructor. | 108 // it in its destructor. |
| 128 view->set_png_data(screenshot_png); | 109 view->set_png_data(screenshot_png); |
| 129 | 110 |
| 130 // Create and show the dialog. | 111 // Create and show the dialog. |
| 131 views::Window::CreateChromeWindow(parent->GetNativeView(), gfx::Rect(), | 112 views::Window::CreateChromeWindow(parent->GetNativeView(), gfx::Rect(), |
| 132 view)->Show(); | 113 view)->Show(); |
| 133 } | 114 } |
| 134 | 115 |
| 135 } // namespace browser | 116 } // namespace browser |
| 136 | 117 |
| 137 BugReportView::PostCleanup::PostCleanup() { | |
| 138 } | |
| 139 | |
| 140 void BugReportView::PostCleanup::OnURLFetchComplete( | |
| 141 const URLFetcher* source, | |
| 142 const GURL& url, | |
| 143 const URLRequestStatus& status, | |
| 144 int response_code, | |
| 145 const ResponseCookies& cookies, | |
| 146 const std::string& data) { | |
| 147 // Delete the URLFetcher. | |
| 148 delete source; | |
| 149 // And then delete ourselves. | |
| 150 delete this; | |
| 151 } | |
| 152 | |
| 153 // BugReportView - create and submit a bug report from the user. | 118 // BugReportView - create and submit a bug report from the user. |
| 154 // This is separate from crash reporting, which is handled by Breakpad. | 119 // This is separate from crash reporting, which is handled by Breakpad. |
| 155 // | 120 // |
| 156 BugReportView::BugReportView(Profile* profile, TabContents* tab) | 121 BugReportView::BugReportView(Profile* profile, TabContents* tab) |
| 157 : include_page_source_checkbox_(NULL), | 122 : include_page_source_checkbox_(NULL), |
| 158 include_page_image_checkbox_(NULL), | 123 include_page_image_checkbox_(NULL), |
| 159 profile_(profile), | 124 profile_(profile), |
| 160 post_url_(l10n_util::GetString(IDS_BUGREPORT_POST_URL)), | 125 post_url_(l10n_util::GetString(IDS_BUGREPORT_POST_URL)), |
| 161 tab_(tab), | 126 tab_(tab), |
| 162 problem_type_(0) { | 127 problem_type_(0) { |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 341 return true; | 306 return true; |
| 342 } | 307 } |
| 343 | 308 |
| 344 std::wstring BugReportView::GetWindowTitle() const { | 309 std::wstring BugReportView::GetWindowTitle() const { |
| 345 return l10n_util::GetString(IDS_BUGREPORT_TITLE); | 310 return l10n_util::GetString(IDS_BUGREPORT_TITLE); |
| 346 } | 311 } |
| 347 | 312 |
| 348 bool BugReportView::Accept() { | 313 bool BugReportView::Accept() { |
| 349 if (IsDialogButtonEnabled(MessageBoxFlags::DIALOGBUTTON_OK)) { | 314 if (IsDialogButtonEnabled(MessageBoxFlags::DIALOGBUTTON_OK)) { |
| 350 if (problem_type_ == BugReportComboBoxModel::PHISHING_PAGE) | 315 if (problem_type_ == BugReportComboBoxModel::PHISHING_PAGE) |
| 351 ReportPhishing(); | 316 BugReportUtil::ReportPhishing(tab_, |
| 317 WideToUTF8(page_url_text_->text())); |
| 352 else | 318 else |
| 353 SendReport(); | 319 BugReportUtil::SendReport(profile_, |
| 320 WideToUTF8(page_title_text_->GetText()), |
| 321 problem_type_, |
| 322 WideToUTF8(page_url_text_->text()), |
| 323 WideToUTF8(description_text_->text()), |
| 324 include_page_image_checkbox_->checked() && png_data_.get() ? |
| 325 reinterpret_cast<const char *>(&((*png_data_.get())[0])) : NULL, |
| 326 png_data_->size()); |
| 354 } | 327 } |
| 355 return true; | 328 return true; |
| 356 } | 329 } |
| 357 | 330 |
| 358 views::View* BugReportView::GetContentsView() { | 331 views::View* BugReportView::GetContentsView() { |
| 359 return this; | 332 return this; |
| 360 } | 333 } |
| 361 | |
| 362 // SetOSVersion copies the maj.minor.build + servicePack_string | |
| 363 // into a string (for Windows only). This should probably be | |
| 364 // in a util somewhere. We currently have: | |
| 365 // win_util::GetWinVersion returns WinVersion, which is just | |
| 366 // an enum of 2000, XP, 2003, or VISTA. Not enough detail for | |
| 367 // bug reports. | |
| 368 // base::SysInfo::OperatingSystemVersion returns an std::string | |
| 369 // but doesn't include the build or service pack. That function | |
| 370 // is probably the right one to extend, but will require changing | |
| 371 // all the call sites or making it a wrapper around another util. | |
| 372 void BugReportView::SetOSVersion(std::string *os_version) { | |
| 373 OSVERSIONINFO osvi; | |
| 374 ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); | |
| 375 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); | |
| 376 | |
| 377 if (GetVersionEx(&osvi)) { | |
| 378 *os_version = StringPrintf("%d.%d.%d %S", | |
| 379 osvi.dwMajorVersion, | |
| 380 osvi.dwMinorVersion, | |
| 381 osvi.dwBuildNumber, | |
| 382 osvi.szCSDVersion); | |
| 383 } else { | |
| 384 *os_version = "unknown"; | |
| 385 } | |
| 386 } | |
| 387 | |
| 388 // Create a MIME boundary marker (27 '-' characters followed by 16 hex digits). | |
| 389 void BugReportView::CreateMimeBoundary(std::string *out) { | |
| 390 int r1 = rand(); | |
| 391 int r2 = rand(); | |
| 392 SStringPrintf(out, "---------------------------%08X%08X", r1, r2); | |
| 393 } | |
| 394 | |
| 395 void BugReportView::SendReport() { | |
| 396 std::wstring post_url = l10n_util::GetString(IDS_BUGREPORT_POST_URL); | |
| 397 std::string mime_boundary; | |
| 398 CreateMimeBoundary(&mime_boundary); | |
| 399 | |
| 400 // Create a request body and add the mandatory parameters. | |
| 401 std::string post_body; | |
| 402 | |
| 403 // Add the protocol version: | |
| 404 post_body.append("--" + mime_boundary + "\r\n"); | |
| 405 post_body.append("Content-Disposition: form-data; " | |
| 406 "name=\"data_version\"\r\n\r\n"); | |
| 407 post_body.append(StringPrintf("%d\r\n", kBugReportVersion)); | |
| 408 | |
| 409 // Add the page title. | |
| 410 post_body.append("--" + mime_boundary + "\r\n"); | |
| 411 std::string page_title = WideToUTF8(page_title_text_->GetText()); | |
| 412 post_body.append("Content-Disposition: form-data; " | |
| 413 "name=\"title\"\r\n\r\n"); | |
| 414 post_body.append(page_title + "\r\n"); | |
| 415 | |
| 416 // Add the problem type. | |
| 417 post_body.append("--" + mime_boundary + "\r\n"); | |
| 418 post_body.append("Content-Disposition: form-data; " | |
| 419 "name=\"problem\"\r\n\r\n"); | |
| 420 post_body.append(StringPrintf("%d\r\n", problem_type_)); | |
| 421 | |
| 422 // Add in the URL, if we have one. | |
| 423 post_body.append("--" + mime_boundary + "\r\n"); | |
| 424 post_body.append("Content-Disposition: form-data; " | |
| 425 "name=\"url\"\r\n\r\n"); | |
| 426 | |
| 427 // Convert URL to UTF8. | |
| 428 std::string report_url = WideToUTF8(page_url_text_->text()); | |
| 429 if (report_url.empty()) { | |
| 430 post_body.append("n/a\r\n"); | |
| 431 } else { | |
| 432 post_body.append(report_url + "\r\n"); | |
| 433 } | |
| 434 | |
| 435 // Add Chrome version. | |
| 436 post_body.append("--" + mime_boundary + "\r\n"); | |
| 437 post_body.append("Content-Disposition: form-data; " | |
| 438 "name=\"chrome_version\"\r\n\r\n"); | |
| 439 | |
| 440 std::string version = WideToUTF8(version_); | |
| 441 if (version.empty()) { | |
| 442 post_body.append("n/a\r\n"); | |
| 443 } else { | |
| 444 post_body.append(version + "\r\n"); | |
| 445 } | |
| 446 | |
| 447 // Add OS version (eg, for WinXP SP2: "5.1.2600 Service Pack 2"). | |
| 448 std::string os_version = ""; | |
| 449 post_body.append("--" + mime_boundary + "\r\n"); | |
| 450 post_body.append("Content-Disposition: form-data; " | |
| 451 "name=\"os_version\"\r\n\r\n"); | |
| 452 SetOSVersion(&os_version); | |
| 453 post_body.append(os_version + "\r\n"); | |
| 454 | |
| 455 // Add locale. | |
| 456 icu::Locale locale = icu::Locale::getDefault(); | |
| 457 const char *lang = locale.getLanguage(); | |
| 458 std::string chrome_locale = (lang)? lang:"en"; | |
| 459 post_body.append("--" + mime_boundary + "\r\n"); | |
| 460 post_body.append("Content-Disposition: form-data; " | |
| 461 "name=\"chrome_locale\"\r\n\r\n"); | |
| 462 post_body.append(chrome_locale + "\r\n"); | |
| 463 | |
| 464 // Add a description if we have one. | |
| 465 post_body.append("--" + mime_boundary + "\r\n"); | |
| 466 post_body.append("Content-Disposition: form-data; " | |
| 467 "name=\"description\"\r\n\r\n"); | |
| 468 | |
| 469 std::string description = WideToUTF8(description_text_->text()); | |
| 470 if (description.empty()) { | |
| 471 post_body.append("n/a\r\n"); | |
| 472 } else { | |
| 473 post_body.append(description + "\r\n"); | |
| 474 } | |
| 475 | |
| 476 // Include the page image if we have one. | |
| 477 if (include_page_image_checkbox_->checked() && png_data_.get()) { | |
| 478 post_body.append("--" + mime_boundary + "\r\n"); | |
| 479 post_body.append("Content-Disposition: form-data; name=\"screenshot\"; " | |
| 480 "filename=\"screenshot.png\"\r\n"); | |
| 481 post_body.append("Content-Type: application/octet-stream\r\n"); | |
| 482 post_body.append(StringPrintf("Content-Length: %lu\r\n\r\n", | |
| 483 png_data_->size())); | |
| 484 // The following relies on the fact that STL vectors are guaranteed to | |
| 485 // be stored contiguously. | |
| 486 post_body.append(reinterpret_cast<const char *>(&((*png_data_)[0])), | |
| 487 png_data_->size()); | |
| 488 post_body.append("\r\n"); | |
| 489 } | |
| 490 | |
| 491 // TODO(awalker): include the page source if we can get it. | |
| 492 if (include_page_source_checkbox_->checked()) { | |
| 493 } | |
| 494 | |
| 495 // Terminate the body. | |
| 496 post_body.append("--" + mime_boundary + "--\r\n"); | |
| 497 | |
| 498 // We have the body of our POST, so send it off to the server. | |
| 499 URLFetcher* fetcher = new URLFetcher(post_url_, URLFetcher::POST, | |
| 500 new BugReportView::PostCleanup); | |
| 501 fetcher->set_request_context(profile_->GetRequestContext()); | |
| 502 std::string mime_type("multipart/form-data; boundary="); | |
| 503 mime_type += mime_boundary; | |
| 504 fetcher->set_upload_data(mime_type, post_body); | |
| 505 fetcher->Start(); | |
| 506 } | |
| 507 | |
| 508 void BugReportView::ReportPhishing() { | |
| 509 tab_->controller().LoadURL( | |
| 510 safe_browsing_util::GeneratePhishingReportUrl( | |
| 511 kReportPhishingUrl, WideToUTF8(page_url_text_->text())), | |
| 512 GURL(), | |
| 513 PageTransition::LINK); | |
| 514 } | |
| OLD | NEW |