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 |