summaryrefslogtreecommitdiffstats
path: root/chrome/browser/views/bug_report_view.cc
diff options
context:
space:
mode:
authorinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 23:55:29 +0000
committerinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 23:55:29 +0000
commit09911bf300f1a419907a9412154760efd0b7abc3 (patch)
treef131325fb4e2ad12c6d3504ab75b16dd92facfed /chrome/browser/views/bug_report_view.cc
parent586acc5fe142f498261f52c66862fa417c3d52d2 (diff)
downloadchromium_src-09911bf300f1a419907a9412154760efd0b7abc3.zip
chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.gz
chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.bz2
Add chrome to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/views/bug_report_view.cc')
-rw-r--r--chrome/browser/views/bug_report_view.cc510
1 files changed, 510 insertions, 0 deletions
diff --git a/chrome/browser/views/bug_report_view.cc b/chrome/browser/views/bug_report_view.cc
new file mode 100644
index 0000000..2977409
--- /dev/null
+++ b/chrome/browser/views/bug_report_view.cc
@@ -0,0 +1,510 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "chrome/browser/views/bug_report_view.h"
+
+#include <iostream>
+#include <fstream>
+
+#include "base/string_util.h"
+#include "chrome/app/locales/locale_settings.h"
+#include "chrome/browser/navigation_controller.h"
+#include "chrome/browser/navigation_entry.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/safe_browsing/safe_browsing_util.h"
+#include "chrome/browser/tab_contents.h"
+#include "chrome/browser/url_fetcher.h"
+#include "chrome/browser/standard_layout.h"
+#include "chrome/common/l10n_util.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/pref_service.h"
+#include "chrome/views/checkbox.h"
+#include "chrome/views/client_view.h"
+#include "chrome/views/grid_layout.h"
+#include "chrome/views/label.h"
+#include "chrome/views/Window.h"
+#include "generated_resources.h"
+#include "net/base/escape.h"
+#include "unicode/locid.h"
+
+using ChromeViews::ColumnSet;
+using ChromeViews::GridLayout;
+
+// Report a bug data version
+static const int kBugReportVersion = 1;
+
+// Number of lines description field can display at one time.
+static const int kDescriptionLines = 5;
+
+// Google's phishing reporting URL.
+static const char kReportPhishingUrl[] =
+ "http://www.google.com/safebrowsing/report_phish/";
+
+class BugReportComboBoxModel : public ChromeViews::ComboBox::Model {
+ public:
+ BugReportComboBoxModel() {}
+
+ enum BugType {
+ PAGE_WONT_LOAD = 0,
+ PAGE_LOOKS_ODD,
+ PHISHING_PAGE,
+ CANT_SIGN_IN,
+ CHROME_MISBEHAVES,
+ SOMETHING_MISSING,
+ BROWSER_CRASH,
+ OTHER_PROBLEM
+ };
+
+ // ChromeViews::ComboBox::Model interface.
+ virtual int GetItemCount(ChromeViews::ComboBox* source) {
+ return OTHER_PROBLEM + 1;
+ }
+
+ virtual std::wstring GetItemAt(ChromeViews::ComboBox* source, int index) {
+ return GetItemAtIndex(index);
+ }
+
+ static std::wstring GetItemAtIndex(int index) {
+ switch (index) {
+ case PAGE_WONT_LOAD:
+ return l10n_util::GetString(IDS_BUGREPORT_PAGE_WONT_LOAD);
+ case PAGE_LOOKS_ODD:
+ return l10n_util::GetString(IDS_BUGREPORT_PAGE_LOOKS_ODD);
+ case PHISHING_PAGE:
+ return l10n_util::GetString(IDS_BUGREPORT_PHISHING_PAGE);
+ case CANT_SIGN_IN:
+ return l10n_util::GetString(IDS_BUGREPORT_CANT_SIGN_IN);
+ case CHROME_MISBEHAVES:
+ return l10n_util::GetString(IDS_BUGREPORT_CHROME_MISBEHAVES);
+ case SOMETHING_MISSING:
+ return l10n_util::GetString(IDS_BUGREPORT_SOMETHING_MISSING);
+ case BROWSER_CRASH:
+ return l10n_util::GetString(IDS_BUGREPORT_BROWSER_CRASH);
+ case OTHER_PROBLEM:
+ return l10n_util::GetString(IDS_BUGREPORT_OTHER_PROBLEM);
+ default:
+ NOTREACHED();
+ return std::wstring();
+ }
+ }
+
+ private:
+ DISALLOW_EVIL_CONSTRUCTORS(BugReportComboBoxModel);
+};
+
+// Simple URLFetcher::Delegate to clean up URLFetcher on completion
+// (since the BugReportView will be gone by then)
+class BugReportView::PostCleanup : public URLFetcher::Delegate {
+ public:
+ PostCleanup();
+ // Overridden from URLFetcher::Delegate
+ virtual void OnURLFetchComplete(const URLFetcher* source,
+ const GURL& url,
+ const URLRequestStatus& status,
+ int response_code,
+ const ResponseCookies& cookies,
+ const std::string& data);
+ private:
+ DISALLOW_EVIL_CONSTRUCTORS(PostCleanup);
+};
+
+BugReportView::PostCleanup::PostCleanup() {
+}
+
+void BugReportView::PostCleanup::OnURLFetchComplete(
+ const URLFetcher* source,
+ const GURL& url,
+ const URLRequestStatus& status,
+ int response_code,
+ const ResponseCookies& cookies,
+ const std::string& data) {
+ // delete the URLFetcher
+ delete source;
+ // and then delete ourselves
+ delete this;
+}
+
+// BugReportView - create and submit a bug report from the user.
+// This is separate from crash reporting, which is handled by Breakpad.
+//
+BugReportView::BugReportView(Profile* profile, TabContents* tab)
+ : dialog_(NULL),
+ include_page_source_checkbox_(NULL),
+ include_page_image_checkbox_(NULL),
+ profile_(profile),
+ post_url_(l10n_util::GetString(IDS_BUGREPORT_POST_URL)),
+ tab_(tab),
+ problem_type_(0) {
+ DCHECK(profile);
+ SetupControl();
+}
+
+BugReportView::~BugReportView() {
+}
+
+void BugReportView::SetupControl() {
+ bug_type_model_.reset(new BugReportComboBoxModel);
+
+ // Adds all controls.
+ bug_type_label_ = new ChromeViews::Label(
+ l10n_util::GetString(IDS_BUGREPORT_BUG_TYPE));
+ bug_type_combo_ = new ChromeViews::ComboBox(bug_type_model_.get());
+ bug_type_combo_->SetListener(this);
+
+ page_title_label_ = new ChromeViews::Label(
+ l10n_util::GetString(IDS_BUGREPORT_REPORT_PAGE_TITLE));
+ page_title_text_ = new ChromeViews::Label(tab_->GetTitle());
+ page_url_label_ = new ChromeViews::Label(
+ l10n_util::GetString(IDS_BUGREPORT_REPORT_URL_LABEL));
+ // page_url_text_'s text (if any) is filled in after dialog creation
+ page_url_text_ = new ChromeViews::TextField;
+ page_url_text_->SetController(this);
+
+ description_label_ = new ChromeViews::Label(
+ l10n_util::GetString(IDS_BUGREPORT_DESCRIPTION_LABEL));
+ description_text_ =
+ new ChromeViews::TextField(ChromeViews::TextField::STYLE_MULTILINE);
+ description_text_->SetHeightInLines(kDescriptionLines);
+
+ include_page_source_checkbox_ = new ChromeViews::CheckBox(
+ l10n_util::GetString(IDS_BUGREPORT_INCLUDE_PAGE_SOURCE_CHKBOX));
+ include_page_source_checkbox_->SetIsSelected(true);
+ include_page_image_checkbox_ = new ChromeViews::CheckBox(
+ l10n_util::GetString(IDS_BUGREPORT_INCLUDE_PAGE_IMAGE_CHKBOX));
+ include_page_image_checkbox_->SetIsSelected(true);
+
+ // Arranges controls by using GridLayout.
+ const int column_set_id = 0;
+ GridLayout* layout = CreatePanelGridLayout(this);
+ SetLayoutManager(layout);
+ ColumnSet* column_set = layout->AddColumnSet(column_set_id);
+ column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, 0,
+ GridLayout::USE_PREF, 0, 0);
+ column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing * 2);
+ column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
+ GridLayout::USE_PREF, 0, 0);
+
+ // Page Title and text.
+ layout->StartRow(0, column_set_id);
+ layout->AddView(page_title_label_);
+ layout->AddView(page_title_text_, 1, 1, GridLayout::LEADING,
+ GridLayout::FILL);
+ layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+
+ // Bug type and combo box.
+ layout->StartRow(0, column_set_id);
+ layout->AddView(bug_type_label_, 1, 1, GridLayout::LEADING, GridLayout::FILL);
+ layout->AddView(bug_type_combo_);
+ layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+
+ // Page URL and text field.
+ layout->StartRow(0, column_set_id);
+ layout->AddView(page_url_label_);
+ layout->AddView(page_url_text_);
+ layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+
+ // Description label and text field.
+ layout->StartRow(0, column_set_id);
+ layout->AddView(description_label_, 1, 1, GridLayout::LEADING,
+ GridLayout::LEADING);
+ layout->AddView(description_text_, 1, 1, GridLayout::FILL,
+ GridLayout::LEADING);
+ layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);
+
+ // Checkboxes.
+ // The include page source checkbox is hidden until we can make it work.
+ // layout->StartRow(0, column_set_id);
+ // layout->SkipColumns(1);
+ // layout->AddView(include_page_source_checkbox_);
+ // layout->AddPaddingRow(0, kRelatedControlVerticalSpacing);
+ layout->StartRow(0, column_set_id);
+ layout->SkipColumns(1);
+ layout->AddView(include_page_image_checkbox_);
+ layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing);
+}
+
+void BugReportView::GetPreferredSize(CSize *out) {
+ DCHECK(out);
+ *out = ChromeViews::Window::GetLocalizedContentsSize(
+ IDS_BUGREPORT_DIALOG_WIDTH_CHARS,
+ IDS_BUGREPORT_DIALOG_HEIGHT_LINES).ToSIZE();
+}
+
+void BugReportView::ItemChanged(ChromeViews::ComboBox* combo_box,
+ int prev_index,
+ int new_index) {
+ if (new_index == prev_index)
+ return;
+
+ problem_type_ = new_index;
+ bool is_phishing_report = new_index == BugReportComboBoxModel::PHISHING_PAGE;
+
+ description_text_->SetEnabled(!is_phishing_report);
+ description_text_->SetReadOnly(is_phishing_report);
+ if (is_phishing_report) {
+ old_report_text_ = description_text_->GetText();
+ description_text_->SetText(std::wstring());
+ } else if (!old_report_text_.empty()) {
+ description_text_->SetText(old_report_text_);
+ old_report_text_.clear();
+ }
+ include_page_source_checkbox_->SetEnabled(!is_phishing_report);
+ include_page_source_checkbox_->SetIsSelected(!is_phishing_report);
+ include_page_image_checkbox_->SetEnabled(!is_phishing_report);
+ include_page_image_checkbox_->SetIsSelected(!is_phishing_report);
+
+ dialog_->UpdateDialogButtons();
+}
+
+void BugReportView::ContentsChanged(ChromeViews::TextField* sender,
+ const std::wstring& new_contents) {
+}
+
+void BugReportView::HandleKeystroke(ChromeViews::TextField* sender,
+ UINT message, TCHAR key,
+ UINT repeat_count, UINT flags) {
+}
+
+std::wstring BugReportView::GetDialogButtonLabel(DialogButton button) const {
+ if (button == DIALOGBUTTON_OK) {
+ if (problem_type_ == BugReportComboBoxModel::PHISHING_PAGE)
+ return l10n_util::GetString(IDS_BUGREPORT_SEND_PHISHING_REPORT);
+ else
+ return l10n_util::GetString(IDS_BUGREPORT_SEND_REPORT);
+ } else {
+ return std::wstring();
+ }
+}
+
+int BugReportView::GetDefaultDialogButton() const {
+ return DIALOGBUTTON_NONE;
+}
+
+bool BugReportView::CanResize() const {
+ return false;
+}
+
+bool BugReportView::CanMaximize() const {
+ return false;
+}
+
+bool BugReportView::IsAlwaysOnTop() const {
+ return false;
+}
+
+bool BugReportView::HasAlwaysOnTopMenu() const {
+ return false;
+}
+
+bool BugReportView::IsModal() const {
+ return true;
+}
+
+std::wstring BugReportView::GetWindowTitle() const {
+ return l10n_util::GetString(IDS_BUGREPORT_TITLE);
+}
+
+bool BugReportView::Accept() {
+ if (IsDialogButtonEnabled(DIALOGBUTTON_OK)) {
+ if (problem_type_ == BugReportComboBoxModel::PHISHING_PAGE)
+ ReportPhishing();
+ else
+ SendReport();
+ }
+ return true;
+}
+
+void BugReportView::SetUrl(const GURL& url) {
+ page_url_text_->SetText(UTF8ToWide(url.spec()));
+}
+
+// SetOSVersion copies the maj.minor.build + servicePack_string
+// into a string (for Windows only). This should probably be
+// in a util somewhere. We currently have
+// win_util::GetWinVersion returns WinVersion, which is just
+// an enum of 2000, XP, 2003, or VISTA. Not enough detail for
+// bug reports
+// env_util::GetOperatingSystemVersion returns an std::string
+// but doesn't include the build or service pack. That function
+// is probably the right one to extend, but will require changing
+// all the call sites or making it a wrapper around another util.
+void BugReportView::SetOSVersion(std::string *os_version) {
+ OSVERSIONINFO osvi;
+ ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+
+ if (GetVersionEx(&osvi)) {
+ *os_version = StringPrintf("%d.%d.%d %S",
+ osvi.dwMajorVersion,
+ osvi.dwMinorVersion,
+ osvi.dwBuildNumber,
+ osvi.szCSDVersion);
+ } else {
+ *os_version = "unknown";
+ }
+}
+
+// Create a MIME boundary marker (27 '-' characters followed by 16 hex digits)
+void BugReportView::CreateMimeBoundary(std::string *out) {
+ int r1 = rand();
+ int r2 = rand();
+ SStringPrintf(out, "---------------------------%08X%08X", r1, r2);
+}
+
+void BugReportView::SendReport() {
+ std::wstring post_url = l10n_util::GetString(IDS_BUGREPORT_POST_URL);
+ std::string mime_boundary;
+ CreateMimeBoundary(&mime_boundary);
+
+ // create a request body and add the mandatory parameters
+ std::string post_body;
+
+ // If this is an internal Google user, include user name for followup
+ // TODO: revisit for public release
+
+ if (!strcmp(getenv("USERDOMAIN"), "GOOGLE") && getenv("USERNAME")) {
+ std::string user_name(getenv("USERNAME"));
+ post_body.append("--" + mime_boundary + "\r\n");
+ post_body.append("Content-Disposition: form-data; "
+ "name=\"username\"\r\n\r\n");
+ post_body.append(user_name + "\r\n");
+ }
+
+ // Add the protocol version:
+ post_body.append("--" + mime_boundary + "\r\n");
+ post_body.append("Content-Disposition: form-data; "
+ "name=\"data_version\"\r\n\r\n");
+ post_body.append(StringPrintf("%d\r\n", kBugReportVersion));
+
+ // Add the page title
+ post_body.append("--" + mime_boundary + "\r\n");
+ std::string page_title = WideToUTF8(page_title_text_->GetText());
+ post_body.append("Content-Disposition: form-data; "
+ "name=\"title\"\r\n\r\n");
+ post_body.append(page_title + "\r\n");
+
+ // Add the problem type
+ post_body.append("--" + mime_boundary + "\r\n");
+ post_body.append("Content-Disposition: form-data; "
+ "name=\"problem\"\r\n\r\n");
+ post_body.append(StringPrintf("%d\r\n", problem_type_));
+
+ // Add in the URL, if we have one
+ post_body.append("--" + mime_boundary + "\r\n");
+ post_body.append("Content-Disposition: form-data; "
+ "name=\"url\"\r\n\r\n");
+
+ // convert URL to UTF8
+ std::string report_url = WideToUTF8(page_url_text_->GetText());
+ if (report_url.empty()) {
+ post_body.append("n/a\r\n");
+ } else {
+ post_body.append(report_url + "\r\n");
+ }
+
+ // Add Chrome version
+ post_body.append("--" + mime_boundary + "\r\n");
+ post_body.append("Content-Disposition: form-data; "
+ "name=\"chrome_version\"\r\n\r\n");
+
+ std::string version = WideToUTF8(version_);
+ if (version.empty()) {
+ post_body.append("n/a\r\n");
+ } else {
+ post_body.append(version + "\r\n");
+ }
+
+ // Add OS version (eg, for WinXP SP2: "5.1.2600 Service Pack 2")
+ std::string os_version = "";
+ post_body.append("--" + mime_boundary + "\r\n");
+ post_body.append("Content-Disposition: form-data; "
+ "name=\"os_version\"\r\n\r\n");
+ SetOSVersion(&os_version);
+ post_body.append(os_version + "\r\n");
+
+ // Add locale
+ Locale locale = Locale::getDefault();
+ const char *lang = locale.getLanguage();
+ std::string chrome_locale = (lang)? lang:"en";
+ post_body.append("--" + mime_boundary + "\r\n");
+ post_body.append("Content-Disposition: form-data; "
+ "name=\"chrome_locale\"\r\n\r\n");
+ post_body.append(chrome_locale + "\r\n");
+
+ // Add a description if we have one
+ post_body.append("--" + mime_boundary + "\r\n");
+ post_body.append("Content-Disposition: form-data; "
+ "name=\"description\"\r\n\r\n");
+
+ std::string description = WideToUTF8(description_text_->GetText());
+ if (description.empty()) {
+ post_body.append("n/a\r\n");
+ } else {
+ post_body.append(description + "\r\n");
+ }
+
+ // include the page image if we have one
+ if (include_page_image_checkbox_->IsSelected() && png_data_.get()) {
+ post_body.append("--" + mime_boundary + "\r\n");
+ post_body.append("Content-Disposition: form-data; name=\"screenshot\"; "
+ "filename=\"screenshot.png\"\r\n");
+ post_body.append("Content-Type: application/octet-stream\r\n");
+ post_body.append(StringPrintf("Content-Length: %lu\r\n\r\n",
+ png_data_->size()));
+ // the following relies on the fact that STL vectors are guaranteed to
+ // be stored contiguously.
+ post_body.append(reinterpret_cast<const char *>(&((*png_data_)[0])),
+ png_data_->size());
+ post_body.append("\r\n");
+ }
+
+ // TODO(awalker): include the page source if we can get it
+ if (include_page_source_checkbox_->IsSelected()) {
+ }
+
+ // terminate the body
+ post_body.append("--" + mime_boundary + "--\r\n");
+
+ // We have the body of our POST, so send it off to the server
+
+ URLFetcher* fetcher = new URLFetcher(post_url_, URLFetcher::POST,
+ new BugReportView::PostCleanup);
+ fetcher->set_request_context(profile_->GetRequestContext());
+ std::string mime_type("multipart/form-data; boundary=");
+ mime_type += mime_boundary;
+ fetcher->set_upload_data(mime_type, post_body);
+ fetcher->Start();
+}
+
+void BugReportView::ReportPhishing() {
+ tab_->controller()->LoadURL(
+ safe_browsing_util::GeneratePhishingReportUrl(
+ kReportPhishingUrl, WideToNativeMB(page_url_text_->GetText())),
+ PageTransition::LINK);
+}