diff options
author | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-26 23:55:29 +0000 |
---|---|---|
committer | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-26 23:55:29 +0000 |
commit | 09911bf300f1a419907a9412154760efd0b7abc3 (patch) | |
tree | f131325fb4e2ad12c6d3504ab75b16dd92facfed /chrome/browser/views/bug_report_view.cc | |
parent | 586acc5fe142f498261f52c66862fa417c3d52d2 (diff) | |
download | chromium_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.cc | 510 |
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); +} |