diff options
author | phajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-19 18:14:30 +0000 |
---|---|---|
committer | phajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-19 18:14:30 +0000 |
commit | 7316a48f3e4c3ab1892d696e17cafb795ed93aaf (patch) | |
tree | eb8578b0bf7e49a7b97ac70fba6f91441a47e4bc /chrome/browser | |
parent | 8b8e7c9bce4198a4ee2865d9dfce6e8baa173ad3 (diff) | |
download | chromium_src-7316a48f3e4c3ab1892d696e17cafb795ed93aaf.zip chromium_src-7316a48f3e4c3ab1892d696e17cafb795ed93aaf.tar.gz chromium_src-7316a48f3e4c3ab1892d696e17cafb795ed93aaf.tar.bz2 |
Revert "Checkin for CL: http://codereview.chromium.org/3061044/show"
Broke compile.
TBR=rkc
Review URL: http://codereview.chromium.org/3199006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@56717 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
24 files changed, 845 insertions, 1603 deletions
diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc index e07d701..9d98076 100644 --- a/chrome/browser/browser.cc +++ b/chrome/browser/browser.cc @@ -1728,8 +1728,15 @@ void Browser::OpenTaskManager() { } void Browser::OpenBugReportDialog() { +#if defined(OS_CHROMEOS) UserMetrics::RecordAction(UserMetricsAction("ReportBug"), profile_); window_->ShowReportBugDialog(); +#else + TabContents* contents = GetSelectedTabContents(); + if (!contents) + return; + ShowBrokenPageTab(contents); +#endif } void Browser::ToggleBookmarkBar() { diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 22e76d1..3c277f7 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd @@ -60,11 +60,9 @@ without changes to the corresponding grd file. eadee --> <include name="IDR_REMOTING_SETUP_FLOW_HTML" file="remoting\resources\setup_flow.html" flattenhtml="true" type="BINDATA" /> <include name="IDR_REMOTING_SETUP_DONE_HTML" file="remoting\resources\setup_done.html" flattenhtml="true" type="BINDATA" /> <include name="IDR_TRANSLATE_JS" file="resources\translate.js" type="BINDATA" /> - <include name="IDR_BUGREPORT_HTML" file="resources\bug_report.html" flattenhtml="true" type="BINDATA" /> - <include name="IDR_BUGREPORT_HTML_INVALID" file="resources\bug_report_invalid.html" flattenhtml="true" type="BINDATA" /> + <if expr="pp_ifdef('chromeos')"> <include name="IDR_ABOUT_SYS_HTML" file="resources\about_sys.html" flattenhtml="true" type="BINDATA" /> - <include name="IDR_BUGREPORT_HTML_CHROMEOS" file="resources\bug_report_cros.html" flattenhtml="true" type="BINDATA" /> <include name="IDR_FILEBROWSE_HTML" file="resources\filebrowse.html" flattenhtml="true" type="BINDATA" /> <include name="IDR_HOST_REGISTRATION_PAGE_HTML" file="resources\host_registration_page.html" flattenhtml="true" type="BINDATA" /> <include name="IDR_MEDIAPLAYER_HTML" file="resources\mediaplayer.html" flattenhtml="true" type="BINDATA" /> diff --git a/chrome/browser/bug_report_util.cc b/chrome/browser/bug_report_util.cc index 85f7ac1..d60ef4e 100644 --- a/chrome/browser/bug_report_util.cc +++ b/chrome/browser/bug_report_util.cc @@ -4,34 +4,22 @@ #include "chrome/browser/bug_report_util.h" -#include <sstream> #include <string> -#include "app/l10n_util.h" -#include "base/command_line.h" #include "base/file_version_info.h" -#include "base/file_util.h" -#include "base/singleton.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process_impl.h" #include "chrome/browser/profile.h" #include "chrome/browser/safe_browsing/safe_browsing_util.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/common/chrome_version_info.h" -#include "chrome/common/chrome_switches.h" #include "chrome/common/net/url_fetcher.h" #include "googleurl/src/gurl.h" #include "grit/locale_settings.h" -#include "grit/theme_resources.h" #include "net/url_request/url_request_status.h" #include "unicode/locid.h" -#if defined(OS_CHROMEOS) -#include "chrome/browser/chromeos/notifications/system_notification.h" -#endif - namespace { const int kBugReportVersion = 1; @@ -40,60 +28,27 @@ const char kReportPhishingUrl[] = "http://www.google.com/safebrowsing/report_phish/"; // URL to post bug reports to. -static char const kBugReportPostUrl[] = +const char* const kBugReportPostUrl = "https://www.google.com/tools/feedback/chrome/__submit"; -static char const kProtBufMimeType[] = "application/x-protobuf"; -static char const kPngMimeType[] = "image/png"; +const char* const kProtBufMimeType = "application/x-protobuf"; +const char* const kPngMimeType = "image/png"; // Tags we use in product specific data -static char const kPageTitleTag[] = "PAGE TITLE"; -static char const kProblemTypeIdTag[] = "PROBLEM TYPE ID"; -static char const kProblemTypeTag[] = "PROBLEM TYPE"; -static char const kChromeVersionTag[] = "CHROME VERSION"; -static char const kOsVersionTag[] = "OS VERSION"; - -static char const kNotificationId[] = "feedback.chromeos"; - -static int const kHttpPostSuccessNoContent = 204; -static int const kHttpPostFailNoConnection = -1; -static int const kHttpPostFailClientError = 400; -static int const kHttpPostFailServerError = 500; - -} // namespace - +const char* const kPageTitleTag = "PAGE TITLE"; +const char* const kProblemTypeIdTag = "PROBLEM TYPE ID"; +const char* const kProblemTypeTag = "PROBLEM TYPE"; +const char* const kChromeVersionTag = "CHROME VERSION"; +const char* const kOsVersionTag = "OS VERSION"; -#if defined(OS_CHROMEOS) -class FeedbackNotification { - public: - // Previous notification cleanup is handled by scoped_ptr. - // Note: notification will show only on one profile at a time. - void Show(Profile* profile, const string16& message, bool urgent) { - notification_.reset( - new chromeos::SystemNotification(profile, kNotificationId, - IDR_STATUSBAR_FEEDBACK, - l10n_util::GetStringUTF16( - IDS_BUGREPORT_NOTIFICATION_TITLE))); - notification_->Show(message, urgent); - } - private: - FeedbackNotification() {} - friend struct DefaultSingletonTraits<FeedbackNotification>; - - scoped_ptr<chromeos::SystemNotification> notification_; - DISALLOW_COPY_AND_ASSIGN(FeedbackNotification); -}; -#endif +} // namespace // Simple URLFetcher::Delegate to clean up URLFetcher on completion. class BugReportUtil::PostCleanup : public URLFetcher::Delegate { public: -#if defined(OS_CHROMEOS) - explicit PostCleanup(Profile* profile); -#else PostCleanup(); -#endif + // Overridden from URLFetcher::Delegate. virtual void OnURLFetchComplete(const URLFetcher* source, const GURL& url, @@ -106,17 +61,10 @@ class BugReportUtil::PostCleanup : public URLFetcher::Delegate { virtual ~PostCleanup() {} private: - Profile* profile_; - DISALLOW_COPY_AND_ASSIGN(PostCleanup); }; -#if defined(OS_CHROMEOS) - BugReportUtil::PostCleanup::PostCleanup(Profile* profile) - : profile_(profile) { -#else - BugReportUtil::PostCleanup::PostCleanup() { -#endif +BugReportUtil::PostCleanup::PostCleanup() { } void BugReportUtil::PostCleanup::OnURLFetchComplete( @@ -126,38 +74,10 @@ void BugReportUtil::PostCleanup::OnURLFetchComplete( int response_code, const ResponseCookies& cookies, const std::string& data) { - - std::stringstream error_stream; - if (response_code == kHttpPostSuccessNoContent) { - error_stream << "Success"; - } else if (response_code == kHttpPostFailNoConnection) { - error_stream << "No connection to server."; - } else if ((response_code > kHttpPostFailClientError) && - (response_code < kHttpPostFailServerError)) { - error_stream << "Client error: HTTP response code " << response_code; - } else if (response_code > kHttpPostFailServerError) { - error_stream << "Server error: HTTP response code " << response_code; - } else { - error_stream << "Unknown error: HTTP response code " << response_code; - } - - LOG(WARNING) << "Submission to feedback server (" << url << - ") status: " << error_stream.str() << std::endl; - -#if defined(OS_CHROMEOS) - // Show the notification to the user; this notification will stay active till - // either the user closes it, or we display another notification. - if (response_code == kHttpPostSuccessNoContent) { - Singleton<FeedbackNotification>()->Show(profile_, l10n_util::GetStringUTF16( - IDS_BUGREPORT_FEEDBACK_STATUS_SUCCESS), false); - } else { - Singleton<FeedbackNotification>()->Show(profile_, - l10n_util::GetStringFUTF16(IDS_BUGREPORT_FEEDBACK_STATUS_FAIL, - ASCIIToUTF16(error_stream.str())), - true); - } -#endif - + // if not 204, something went wrong + if (response_code != 204) + LOG(WARNING) << "Submission to feedback server failed. Response code: " << + response_code << std::endl; // Delete the URLFetcher. delete source; // And then delete ourselves. @@ -192,20 +112,9 @@ void BugReportUtil::SetOSVersion(std::string *os_version) { } // static -std::string BugReportUtil::feedback_server_(""); - -// static -void BugReportUtil::SetFeedbackServer(const std::string& server) { - feedback_server_ = server; -} - - -// static void BugReportUtil::AddFeedbackData( userfeedback::ExternalExtensionSubmit* feedback_data, const std::string& key, const std::string& value) { - // We have no reason to log any empty values - gives us no data - if (value == "") return; // Create log_value object and add it to the web_data object userfeedback::ProductSpecificData log_value; log_value.set_key(key); @@ -219,25 +128,19 @@ void BugReportUtil::SendReport(Profile* profile, const std::string& page_title_text, int problem_type, const std::string& page_url_text, + const std::string& user_email_text, const std::string& description, const char* png_data, int png_data_length, int png_width, #if defined(OS_CHROMEOS) int png_height, - const std::string& user_email_text, + const std::string& problem_type_text, const chromeos::LogDictionaryType* const sys_info) { #else int png_height) { #endif - GURL post_url; - - if (CommandLine::ForCurrentProcess()-> - HasSwitch(switches::kFeedbackServer)) - post_url = GURL(CommandLine::ForCurrentProcess()-> - GetSwitchValueASCII(switches::kFeedbackServer)); - else - post_url = GURL(kBugReportPostUrl); + GURL post_url(kBugReportPostUrl); // Create google feedback protocol buffer objects userfeedback::ExternalExtensionSubmit feedback_data; @@ -257,17 +160,23 @@ void BugReportUtil::SendReport(Profile* profile, AddFeedbackData(&feedback_data, std::string(kPageTitleTag), page_title_text); + AddFeedbackData(&feedback_data, std::string(kProblemTypeIdTag), + StringPrintf("%d\r\n", problem_type)); + #if defined(OS_CHROMEOS) + AddFeedbackData(&feedback_data, std::string(kProblemTypeTag), + problem_type_text); +#endif + // Add the user e-mail to the feedback object common_data->set_user_email(user_email_text); -#endif // Add the description to the feedback object common_data->set_description(description); // Add the language std::string chrome_locale = g_browser_process->GetApplicationLocale(); - common_data->set_source_description_language(chrome_locale); + common_data->set_source_descripton_language(chrome_locale); // Set the url web_data->set_url(page_url_text); @@ -313,33 +222,9 @@ void BugReportUtil::SendReport(Profile* profile, *(feedback_data.mutable_screenshot()) = screenshot; } - // Set our Chrome specific data - userfeedback::ChromeData chrome_data; -#if defined(OS_CHROMEOS) - chrome_data.set_chrome_platform( - userfeedback::ChromeData_ChromePlatform_CHROME_OS); - userfeedback::ChromeOsData chrome_os_data; - chrome_os_data.set_category( - (userfeedback::ChromeOsData_ChromeOsCategory) problem_type); - *(chrome_data.mutable_chrome_os_data()) = chrome_os_data; -#else - chrome_data.set_chrome_platform( - userfeedback::ChromeData_ChromePlatform_CHROME_BROWSER); - userfeedback::ChromeBrowserData chrome_browser_data; - chrome_browser_data.set_category( - (userfeedback::ChromeBrowserData_ChromeBrowserCategory) problem_type); - *(chrome_data.mutable_chrome_browser_data()) = chrome_browser_data; -#endif - - *(feedback_data.mutable_chrome_data()) = chrome_data; - // We have the body of our POST, so send it off to the server. URLFetcher* fetcher = new URLFetcher(post_url, URLFetcher::POST, -#if defined(OS_CHROMEOS) - new BugReportUtil::PostCleanup(profile)); -#else - new BugReportUtil::PostCleanup()); -#endif + new BugReportUtil::PostCleanup); fetcher->set_request_context(profile->GetRequestContext()); std::string post_body; diff --git a/chrome/browser/bug_report_util.h b/chrome/browser/bug_report_util.h index e11a22c..22f3d7e 100644 --- a/chrome/browser/bug_report_util.h +++ b/chrome/browser/bug_report_util.h @@ -63,21 +63,19 @@ class BugReportUtil { // all the call sites or making it a wrapper around another util. static void SetOSVersion(std::string *os_version); - // This sets the address of the feedback server to be used by SendReport - static void SetFeedbackServer(const std::string& server); - // Generates bug report data. static void SendReport(Profile* profile, const std::string& page_title_text, int problem_type, const std::string& page_url_text, + const std::string& user_email_text, const std::string& description, const char* png_data, int png_data_length, int png_width, #if defined(OS_CHROMEOS) int png_height, - const std::string& user_email_text, + const std::string& problem_type_text, const chromeos::LogDictionaryType* const sys_info); #else int png_height); @@ -95,8 +93,6 @@ class BugReportUtil { userfeedback::ExternalExtensionSubmit* feedback_data, const std::string& key, const std::string& value); - static std::string feedback_server_; - DISALLOW_IMPLICIT_CONSTRUCTORS(BugReportUtil); }; diff --git a/chrome/browser/cocoa/bug_report_window_controller.mm b/chrome/browser/cocoa/bug_report_window_controller.mm index df29f99..c7e920da 100644 --- a/chrome/browser/cocoa/bug_report_window_controller.mm +++ b/chrome/browser/cocoa/bug_report_window_controller.mm @@ -113,6 +113,7 @@ base::SysNSStringToUTF8(pageTitle_), [self bugTypeFromIndex], base::SysNSStringToUTF8(pageURL_), + std::string(), base::SysNSStringToUTF8(bugDescription_), sendScreenshot_ && !pngData_.empty() ? reinterpret_cast<const char *>(&(pngData_[0])) : NULL, diff --git a/chrome/browser/dom_ui/bug_report_ui.cc b/chrome/browser/dom_ui/bug_report_ui.cc deleted file mode 100644 index 45f06e2..0000000 --- a/chrome/browser/dom_ui/bug_report_ui.cc +++ /dev/null @@ -1,632 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/dom_ui/bug_report_ui.h" - -#include "app/l10n_util.h" -#include "app/resource_bundle.h" -#include "base/callback.h" -#include "base/file_util.h" -#include "base/logging.h" -#include "base/message_loop.h" -#include "base/path_service.h" -#include "base/singleton.h" -#include "base/string_piece.h" -#include "base/string_util.h" -#include "base/string_number_conversions.h" -#include "base/thread.h" -#include "base/time.h" -#include "base/values.h" -#include "base/weak_ptr.h" -#include "chrome/browser/bookmarks/bookmark_model.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_list.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/browser_window.h" -#include "chrome/browser/bug_report_util.h" -#include "chrome/browser/chrome_thread.h" -#include "chrome/browser/dom_ui/dom_ui_screenshot_source.h" -#include "chrome/browser/download/download_manager.h" -#include "chrome/browser/download/download_util.h" -#include "chrome/browser/history/history_types.h" -#include "chrome/browser/metrics/user_metrics.h" -#include "chrome/browser/profile.h" -#include "chrome/browser/tab_contents/tab_contents.h" -#include "chrome/browser/tab_contents/thumbnail_generator.h" -#include "chrome/common/chrome_paths.h" -#include "chrome/common/jstemplate_builder.h" -#include "chrome/common/time_format.h" -#include "chrome/common/url_constants.h" -#include "chrome/common/net/url_fetcher.h" -#include "gfx/codec/png_codec.h" -#include "net/base/escape.h" -#include "views/window/window.h" - -#include "grit/browser_resources.h" -#include "grit/chromium_strings.h" -#include "grit/generated_resources.h" -#include "grit/locale_settings.h" - -#if defined(OS_LINUX) -#include "app/x11_util.h" -#elif defined(OS_MACOSX) -#include "base/mac_util.h" -#else -#include "app/win_util.h" -#endif - -#if defined(OS_CHROMEOS) -#include "chrome/browser/chromeos/cros/cros_library.h" -#include "chrome/browser/chromeos/cros/syslogs_library.h" -#include "chrome/browser/chromeos/login/user_manager.h" -#endif - -static const char kScreenshotBaseUrl[] = "chrome://screenshots/"; -static const char kCurrentScreenshotUrl[] = "chrome://screenshots/current"; -#if defined(OS_CHROMEOS) -static const char kSavedScreenshotsUrl[] = "chrome://screenshots/saved/"; - -static const char kScreenshotPattern[] = "*.png"; -static const char kScreenshotsRelativePath[] = "/Screenshots"; -#endif - -namespace { -#if defined(OS_CHROMEOS) - -void GetSavedScreenshots(std::vector<std::string>* saved_screenshots, - base::WaitableEvent* done) { - saved_screenshots->clear(); - - FilePath fileshelf_path; - if (!PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, - &fileshelf_path)) { - done->Signal(); - return; - } - - // TODO(rkc): Change this to use FilePath.Append() once the cros - // issue with it is fixed - FilePath screenshots_path(fileshelf_path.value() + - std::string(kScreenshotsRelativePath)); - file_util::FileEnumerator screenshots(screenshots_path, false, - file_util::FileEnumerator::FILES, - std::string(kScreenshotPattern)); - FilePath screenshot = screenshots.Next(); - while (!screenshot.empty()) { - saved_screenshots->push_back(std::string(kSavedScreenshotsUrl) + - screenshot.BaseName().value()); - screenshot = screenshots.Next(); - } - done->Signal(); -} - -// This fuction posts a task to the file thread to create/list all the current -// and saved screenshots. -void GetScreenshotUrls(std::vector<std::string>* saved_screenshots) { - base::WaitableEvent done(true, false); - ChromeThread::PostTask(ChromeThread::FILE, FROM_HERE, - NewRunnableFunction(&GetSavedScreenshots, - saved_screenshots, &done)); - done.Wait(); -} - -std::string GetUserEmail() { - chromeos::UserManager* manager = chromeos::UserManager::Get(); - if (!manager) - return std::string(); - else - return manager->logged_in_user().email(); -} - -chromeos::LogDictionaryType* GetSystemInformation() { - chromeos::LogDictionaryType* sys_info = NULL; - chromeos::SyslogsLibrary* syslogs_lib = - chromeos::CrosLibrary::Get()->GetSyslogsLibrary(); - - if (syslogs_lib) - sys_info = syslogs_lib->GetSyslogs(NULL); - - return sys_info; -} -#endif - - -} // namespace - - -namespace browser { - -// TODO(rkc): Eventually find a better way to do this -std::vector<unsigned char>* last_screenshot_png = 0; -gfx::Rect screen_size; - -void RefreshLastScreenshot(views::Window* parent) { - // Grab an exact snapshot of the window that the user is seeing (i.e. as - // rendered--do not re-render, and include windowed plugins). - if (last_screenshot_png) - last_screenshot_png->clear(); - else - last_screenshot_png = new std::vector<unsigned char>; - -#if defined(OS_LINUX) || defined(OS_CHROMEOS) - screen_size = parent->GetBounds(); - x11_util::GrabWindowSnapshot(parent->GetNativeWindow(), last_screenshot_png); -#elif defined(OS_MACOSX) - int width = 0, height = 0; - mac_util::GrabWindowSnapshot(parent->GetNativeWindow(), last_screenshot_png, - &width, &height); -#else - screen_size = parent->GetBounds(); - win_util::GrabWindowSnapshot(parent->GetNativeWindow(), last_screenshot_png); -#endif -} - -// Global "display this dialog" function declared in browser_dialogs.h. -void ShowHtmlBugReportView(views::Window* parent, Browser* browser) { - std::string bug_report_url = std::string(chrome::kChromeUIBugReportURL) + - base::IntToString(browser->selected_index()); - - RefreshLastScreenshot(parent); - browser->ShowSingletonTab(GURL(bug_report_url)); -} - -} // namespace browser - - -class BugReportUIHTMLSource : public ChromeURLDataManager::DataSource { - public: - explicit BugReportUIHTMLSource(base::StringPiece html); - - // Called when the network layer has requested a resource underneath - // the path we registered. - virtual void StartDataRequest(const std::string& path, - bool is_off_the_record, - int request_id); - virtual std::string GetMimeType(const std::string&) const { - return "text/html"; - } - - private: - base::StringPiece bug_report_html_; - ~BugReportUIHTMLSource() {} - - DISALLOW_COPY_AND_ASSIGN(BugReportUIHTMLSource); -}; - -class TaskProxy; - -// The handler for Javascript messages related to the "bug report" dialog -class BugReportHandler : public DOMMessageHandler, - public base::SupportsWeakPtr<BugReportHandler> { - public: - explicit BugReportHandler(TabContents* tab); - virtual ~BugReportHandler(); - - // Init work after Attach. - base::StringPiece Init(); - - // DOMMessageHandler implementation. - virtual DOMMessageHandler* Attach(DOMUI* dom_ui); - virtual void RegisterMessages(); - void OnURLFetchComplete(const URLFetcher* source, - const GURL& url, - const URLRequestStatus& status, - int response_code, - const ResponseCookies& cookies, - const std::string& data); - - void HandleGetDialogDefaults(const Value* value); - void HandleRefreshScreenshots(const Value* value); - void HandleSendReport(const Value* value); - void HandleCancel(const Value* value); - - void SetupScreenshotsSource(); - void ClobberScreenshotsSource(); - - private: - Browser* browser_; - std::string page_url_; - Profile* profile_; - TabContents* tab_; - TabContents* target_tab_; - DOMUIScreenshotSource* screenshot_source_; -#if defined (OS_CHROMEOS) - chromeos::LogDictionaryType* sys_info_; -#endif - - DISALLOW_COPY_AND_ASSIGN(BugReportHandler); -}; - -//////////////////////////////////////////////////////////////////////////////// -// -// BugReportHTMLSource -// -//////////////////////////////////////////////////////////////////////////////// - -BugReportUIHTMLSource::BugReportUIHTMLSource(base::StringPiece html) - : DataSource(chrome::kChromeUIBugReportHost, MessageLoop::current()) { - bug_report_html_ = html; -} - -void BugReportUIHTMLSource::StartDataRequest(const std::string& path, - bool is_off_the_record, - int request_id) { - DictionaryValue localized_strings; - localized_strings.SetString(std::string("title"), - l10n_util::GetStringUTF8(IDS_BUGREPORT_TITLE)); - localized_strings.SetString(std::string("issue-with"), - l10n_util::GetStringUTF8(IDS_BUGREPORT_ISSUE_WITH)); - localized_strings.SetString(std::string("page-url"), - l10n_util::GetStringUTF8(IDS_BUGREPORT_REPORT_URL_LABEL)); - localized_strings.SetString(std::string("description"), - l10n_util::GetStringUTF8(IDS_BUGREPORT_DESCRIPTION_LABEL)); - localized_strings.SetString(std::string("screenshot"), - l10n_util::GetStringUTF8(IDS_BUGREPORT_SCREENSHOT_LABEL)); -#if defined(OS_CHROMEOS) - localized_strings.SetString(std::string("user-email"), - l10n_util::GetStringUTF8(IDS_BUGREPORT_USER_EMAIL_LABEL)); - localized_strings.SetString(std::string("currentscreenshots"), - l10n_util::GetStringUTF8(IDS_BUGREPORT_CURRENT_SCREENSHOTS)); - localized_strings.SetString(std::string("savedscreenshots"), - l10n_util::GetStringUTF8(IDS_BUGREPORT_SAVED_SCREENSHOTS)); - localized_strings.SetString(std::string("sysinfo"), - l10n_util::GetStringUTF8( - IDS_BUGREPORT_INCLUDE_SYSTEM_INFORMATION_CHKBOX)); -#else - localized_strings.SetString(std::string("currentscreenshots"), - l10n_util::GetStringUTF8(IDS_BUGREPORT_INCLUDE_NEW_SCREEN_IMAGE)); -#endif - localized_strings.SetString(std::string("noscreenshot"), - l10n_util::GetStringUTF8(IDS_BUGREPORT_INCLUDE_NO_SCREENSHOT)); - - localized_strings.SetString(std::string("send-report"), - l10n_util::GetStringUTF8(IDS_BUGREPORT_SEND_REPORT)); - localized_strings.SetString(std::string("cancel"), - l10n_util::GetStringUTF8(IDS_CANCEL)); - - // Option strings for the "issue with" drop-down. - localized_strings.SetString(std::string("issue-choose"), - l10n_util::GetStringUTF8(IDS_BUGREPORT_CHOOSE_ISSUE)); - - localized_strings.SetString(std::string("no-issue-selected"), - l10n_util::GetStringUTF8(IDS_BUGREPORT_NO_ISSUE_SELECTED)); - - - // TODO(rkc): Find some way to ensure this order of dropdowns is in sync - // with the order in the userfeedback ChromeData proto buffer -#if defined(OS_CHROMEOS) - // Dropdown for ChromeOS: - // - // Connectivity - // Sync - // Crash - // Page Formatting - // Extensions or Apps - // Standby or Resume - // Phishing Page - // General Feedback/Other - - localized_strings.SetString(std::string("issue-connectivity"), - l10n_util::GetStringUTF8(IDS_BUGREPORT_CONNECTIVITY)); - localized_strings.SetString(std::string("issue-sync"), - l10n_util::GetStringUTF8(IDS_BUGREPORT_SYNC)); - localized_strings.SetString(std::string("issue-crashes"), - l10n_util::GetStringUTF8(IDS_BUGREPORT_CRASHES)); - localized_strings.SetString(std::string("issue-page-formatting"), - l10n_util::GetStringUTF8(IDS_BUGREPORT_PAGE_FORMATTING)); - localized_strings.SetString(std::string("issue-extensions"), - l10n_util::GetStringUTF8(IDS_BUGREPORT_EXTENSIONS)); - localized_strings.SetString(std::string("issue-standby"), - l10n_util::GetStringUTF8(IDS_BUGREPORT_STANDBY_RESUME)); - localized_strings.SetString(std::string("issue-phishing"), - l10n_util::GetStringUTF8(IDS_BUGREPORT_PHISHING_PAGE)); - localized_strings.SetString(std::string("issue-other"), - l10n_util::GetStringUTF8(IDS_BUGREPORT_GENERAL)); -#else - // Dropdown for Chrome: - // - // Page formatting or layout - // Pages not loading - // Plug-ins (e.g. Adobe Flash Player, Quicktime, etc) - // Tabs or windows - // Synced preferences - // Crashes - // Extensions or apps - // Phishing - // Other - - localized_strings.SetString(std::string("issue-page-formatting"), - l10n_util::GetStringUTF8(IDS_BUGREPORT_PAGE_FORMATTING)); - localized_strings.SetString(std::string("issue-page-load"), - l10n_util::GetStringUTF8(IDS_BUGREPORT_PAGE_LOAD)); - localized_strings.SetString(std::string("issue-plugins"), - l10n_util::GetStringUTF8(IDS_BUGREPORT_PLUGINS)); - localized_strings.SetString(std::string("issue-tabs"), - l10n_util::GetStringUTF8(IDS_BUGREPORT_TABS)); - localized_strings.SetString(std::string("issue-sync"), - l10n_util::GetStringUTF8(IDS_BUGREPORT_SYNC)); - localized_strings.SetString(std::string("issue-crashes"), - l10n_util::GetStringUTF8(IDS_BUGREPORT_CRASHES)); - localized_strings.SetString(std::string("issue-extensions"), - l10n_util::GetStringUTF8(IDS_BUGREPORT_EXTENSIONS)); - localized_strings.SetString(std::string("issue-phishing"), - l10n_util::GetStringUTF8(IDS_BUGREPORT_PHISHING_PAGE)); - localized_strings.SetString(std::string("issue-other"), - l10n_util::GetStringUTF8(IDS_BUGREPORT_OTHER)); -#endif - - SetFontAndTextDirection(&localized_strings); - - const std::string full_html = jstemplate_builder::GetI18nTemplateHtml( - bug_report_html_, &localized_strings); - - scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes); - html_bytes->data.resize(full_html.size()); - std::copy(full_html.begin(), full_html.end(), html_bytes->data.begin()); - - SendResponse(request_id, html_bytes); -} - -//////////////////////////////////////////////////////////////////////////////// -// -// BugErportHandler -// -//////////////////////////////////////////////////////////////////////////////// -BugReportHandler::BugReportHandler(TabContents* tab) - : profile_(NULL), tab_(tab), screenshot_source_(NULL) { - browser_ = BrowserList::GetLastActive(); -} - -BugReportHandler::~BugReportHandler() { -} - -void BugReportHandler::ClobberScreenshotsSource() { - // Re-create our screenshots data source (this clobbers the last source) - // setting the screenshot to NULL, effectively disabling the source - // TODO(rkc): Once there is a method to 'remove' a source, change this code - ChromeThread::PostTask( - ChromeThread::IO, FROM_HERE, - NewRunnableMethod( - Singleton<ChromeURLDataManager>::get(), - &ChromeURLDataManager::AddDataSource, - make_scoped_refptr(new DOMUIScreenshotSource(NULL)))); - - // clobber last screenshot - if (browser::last_screenshot_png) - browser::last_screenshot_png->clear(); -} - -void BugReportHandler::SetupScreenshotsSource() { - // If we don't already have a screenshot source object created, create one. - if (!screenshot_source_) - screenshot_source_ = new DOMUIScreenshotSource( - browser::last_screenshot_png); - - // Add the source to the data manager. - ChromeThread::PostTask( - ChromeThread::IO, FROM_HERE, - NewRunnableMethod( - Singleton<ChromeURLDataManager>::get(), - &ChromeURLDataManager::AddDataSource, - make_scoped_refptr(screenshot_source_))); -} - -DOMMessageHandler* BugReportHandler::Attach(DOMUI* dom_ui) { - SetupScreenshotsSource(); - return DOMMessageHandler::Attach(dom_ui); -} - -base::StringPiece BugReportHandler::Init() { - std::string page_url; - if (tab_->controller().GetActiveEntry()) { - page_url = tab_->controller().GetActiveEntry()->url().spec(); - } - - std::string params = page_url.substr(strlen(chrome::kChromeUIBugReportURL)); - - int index = 0; - if (!base::StringToInt(params, &index)) { - ClobberScreenshotsSource(); - return base::StringPiece( - ResourceBundle::GetSharedInstance().GetRawDataResource( - IDR_BUGREPORT_HTML_INVALID)); - } - - // Sanity checks. - if (((index == 0) && (params != "0")) || (index >= browser_->tab_count())) { - ClobberScreenshotsSource(); - return base::StringPiece( - ResourceBundle::GetSharedInstance().GetRawDataResource( - IDR_BUGREPORT_HTML_INVALID)); - } - - if (browser_) - target_tab_ = browser_->GetTabContentsAt(index); - else - LOG(FATAL) << "Failed to get last active browser."; - - return base::StringPiece( - ResourceBundle::GetSharedInstance().GetRawDataResource( -#if defined(OS_CHROMEOS) - IDR_BUGREPORT_HTML_CHROMEOS)); -#else - IDR_BUGREPORT_HTML)); -#endif -} - -void BugReportHandler::RegisterMessages() { - dom_ui_->RegisterMessageCallback("getDialogDefaults", - NewCallback(this, &BugReportHandler::HandleGetDialogDefaults)); - dom_ui_->RegisterMessageCallback("refreshScreenshots", - NewCallback(this, &BugReportHandler::HandleRefreshScreenshots)); - dom_ui_->RegisterMessageCallback("sendReport", - NewCallback(this, &BugReportHandler::HandleSendReport)); - dom_ui_->RegisterMessageCallback("cancel", - NewCallback(this, &BugReportHandler::HandleCancel)); -} - -void BugReportHandler::HandleGetDialogDefaults(const Value* value) { - // send back values which the dialog js needs initially - ListValue dialog_defaults; - - // 0: current url - if (target_tab_) - dialog_defaults.Append(new StringValue( - target_tab_->controller().GetActiveEntry()->url().spec())); - else - dialog_defaults.Append(new StringValue("")); - -#if defined(OS_CHROMEOS) - // 1: user e-mail - sys_info_ = GetSystemInformation(); - dialog_defaults.Append(new StringValue(chrome::kAboutSystemURL)); - - // 2: user e-mail - dialog_defaults.Append(new StringValue(GetUserEmail())); -#endif - - dom_ui_->CallJavascriptFunction(L"setupDialogDefaults", dialog_defaults); -} - -void BugReportHandler::HandleRefreshScreenshots(const Value* value) { - ListValue screenshots; - screenshots.Append(new StringValue(std::string(kCurrentScreenshotUrl))); - - -#if defined(OS_CHROMEOS) - std::vector<std::string> saved_screenshots; - GetScreenshotUrls(&saved_screenshots); - - ListValue* saved_screenshot_list = new ListValue(); - for (size_t i = 0; i < saved_screenshots.size(); ++i) - saved_screenshot_list->Append(new StringValue(saved_screenshots[i])); - screenshots.Append(saved_screenshot_list); -#endif - dom_ui_->CallJavascriptFunction(L"setupScreenshots", screenshots); -} - -void BugReportHandler::HandleSendReport(const Value* value) { - if (value && value->GetType() == Value::TYPE_LIST) { - const ListValue* list_value = static_cast<const ListValue*>(value); - - ListValue::const_iterator i = list_value->begin(); - if (i == list_value->end()) { - LOG(ERROR) << "Incorrect data passed to sendReport."; - return; - } - - // #0 - Problem type. - std::string problem_type_str; - int problem_type = 0; - (*i)->GetAsString(&problem_type_str); - if (!base::StringToInt(problem_type_str, &problem_type)) { - LOG(ERROR) << "Incorrect data passed to sendReport."; - return; - } - if (++i == list_value->end()) { - LOG(ERROR) << "Incorrect data passed to sendReport."; - return; - } - - // #1 - Page url. - std::string page_url; - (*i)->GetAsString(&page_url); - if (++i == list_value->end()) { - LOG(ERROR) << "Incorrect data passed to sendReport."; - return; - } - - // #2 - Description. - std::string description; - (*i)->GetAsString(&description); - if (++i == list_value->end()) { - LOG(ERROR) << "Incorrect data passed to sendReport."; - return; - } - - // #3 - Screenshot to send. - std::string screenshot_path; - (*i)->GetAsString(&screenshot_path); - screenshot_path.erase(0, strlen(kScreenshotBaseUrl)); -#if defined(OS_CHROMEOS) - if (++i == list_value->end()) { - LOG(ERROR) << "Incorrect data passed to sendReport."; - return; - } - - // #4 - User e-mail - std::string user_email; - (*i)->GetAsString(&user_email); - if (++i == list_value->end()) { - LOG(ERROR) << "Incorrect data passed to sendReport."; - return; - } - - // #5 - System info checkbox. - std::string sys_info_checkbox; - (*i)->GetAsString(&sys_info_checkbox); -#endif - - // Get the image to send in the report. - char* image_data = NULL; - int image_data_size = 0; - // Make sure this object remains in scope till SendReport returns. - std::vector<unsigned char> image; - if (screenshot_path.size() > 0) { - image = screenshot_source_->GetScreenshot(screenshot_path); - image_data = reinterpret_cast<char*>(&(image.front())); - image_data_size = image.size(); - } - - BugReportUtil::SendReport(browser_->profile(), - UTF16ToUTF8(target_tab_->GetTitle()), - problem_type, - page_url, - description, - image_data, - image_data_size, browser::screen_size.width(), -#if defined(OS_CHROMEOS) - browser::screen_size.height(), - user_email, - ((sys_info_checkbox == "true") ? - GetSystemInformation() : NULL)); -#else - browser::screen_size.height()); -#endif - - } else { - LOG(ERROR) << "Incorrect data passed from bug report dialog."; - } - browser_->CloseTabContents(tab_); - ClobberScreenshotsSource(); -} - -void BugReportHandler::HandleCancel(const Value* value) { - browser_->CloseTabContents(tab_); - ClobberScreenshotsSource(); -} - - - -//////////////////////////////////////////////////////////////////////////////// -// -// BugReportUI -// -//////////////////////////////////////////////////////////////////////////////// -BugReportUI::BugReportUI(TabContents* tab) : HtmlDialogUI(tab) { - BugReportHandler* handler = new BugReportHandler(tab); - AddMessageHandler((handler)->Attach(this)); - - // The handler's init will specify which html - // resource we'll display to the user - BugReportUIHTMLSource* html_source = - new BugReportUIHTMLSource(handler->Init()); - // Set up the chrome://bugreport/ source. - ChromeThread::PostTask( - ChromeThread::IO, FROM_HERE, - NewRunnableMethod( - Singleton<ChromeURLDataManager>::get(), - &ChromeURLDataManager::AddDataSource, - make_scoped_refptr(html_source))); -} diff --git a/chrome/browser/dom_ui/bug_report_ui.h b/chrome/browser/dom_ui/bug_report_ui.h deleted file mode 100644 index 907dbb2..0000000 --- a/chrome/browser/dom_ui/bug_report_ui.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_DOM_UI_BUG_REPORT_UI_H_ -#define CHROME_BROWSER_DOM_UI_BUG_REPORT_UI_H_ - -#include "chrome/browser/dom_ui/html_dialog_ui.h" - -class TabContents; - -class BugReportUI : public HtmlDialogUI { - public: - explicit BugReportUI(TabContents* contents); - private: - - DISALLOW_COPY_AND_ASSIGN(BugReportUI); -}; - -#endif // CHROME_BROWSER_DOM_UI_BUG_REPORT_UI_H_ diff --git a/chrome/browser/dom_ui/dom_ui_factory.cc b/chrome/browser/dom_ui/dom_ui_factory.cc index 3288d08..5c50067 100644 --- a/chrome/browser/dom_ui/dom_ui_factory.cc +++ b/chrome/browser/dom_ui/dom_ui_factory.cc @@ -7,7 +7,6 @@ #include "base/command_line.h" #include "chrome/browser/chrome_thread.h" #include "chrome/browser/dom_ui/bookmarks_ui.h" -#include "chrome/browser/dom_ui/bug_report_ui.h" #include "chrome/browser/dom_ui/downloads_ui.h" #include "chrome/browser/dom_ui/devtools_ui.h" #include "chrome/browser/dom_ui/history_ui.h" @@ -103,8 +102,6 @@ static DOMUIFactoryFunction GetDOMUIFactoryFunction(const GURL& url) { // after the host name. if (url.host() == chrome::kChromeUIBookmarksHost) return &NewDOMUI<BookmarksUI>; - if (url.host() == chrome::kChromeUIBugReportHost) - return &NewDOMUI<BugReportUI>; if (url.host() == chrome::kChromeUIDevToolsHost) return &NewDOMUI<DevToolsUI>; if (url.host() == chrome::kChromeUIDownloadsHost) diff --git a/chrome/browser/dom_ui/dom_ui_screenshot_source.cc b/chrome/browser/dom_ui/dom_ui_screenshot_source.cc deleted file mode 100644 index 3810f4d..0000000 --- a/chrome/browser/dom_ui/dom_ui_screenshot_source.cc +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/dom_ui/dom_ui_screenshot_source.h" - -#include "base/callback.h" -#include "base/file_util.h" -#include "base/path_service.h" -#include "base/ref_counted_memory.h" -#include "base/task.h" -#include "base/thread.h" -#include "base/waitable_event.h" -#include "chrome/browser/chrome_thread.h" -#include "chrome/common/chrome_paths.h" -#include "chrome/common/url_constants.h" -#include "gfx/codec/jpeg_codec.h" -#include "googleurl/src/gurl.h" -#include "third_party/skia/include/core/SkBitmap.h" - -static const char kCurrentScreenshot[] = "current"; -#if defined(OS_CHROMEOS) -static const char kSavedScreenshots[] = "saved/"; -#endif - -static const char kScreenshotsRelativePath[] = "/Screenshots/"; - -#if defined(OS_CHROMEOS) -// Read the file from the screenshots directory into the read_bytes vector. -void ReadScreenshot(const std::string& filename, - std::vector<unsigned char>* read_bytes, - base::WaitableEvent* read_complete) { - read_bytes->clear(); - - FilePath fileshelf_path; - if (!PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, &fileshelf_path)) { - read_complete->Signal(); - return; - } - - FilePath file(fileshelf_path.value() + std::string(kScreenshotsRelativePath) + - filename); - - int64 file_size = 0; - if (!file_util::GetFileSize(file, &file_size)) { - read_complete->Signal(); - return; - } - - // expand vector to file size - read_bytes->resize(file_size); - // read file into the vector - int bytes_read = 0; - if (!(bytes_read = file_util::ReadFile(file, - reinterpret_cast<char*>( - &read_bytes->front()), - static_cast<int>(file_size)))) - read_bytes->clear(); - - // We're done, if successful, read_bytes will have the data - // otherwise, it'll be empty. - read_complete->Signal(); -} - -// Get a saved screenshot - read on the FILE thread. -std::vector<unsigned char> GetSavedScreenshot(std::string filename) { - base::WaitableEvent read_complete(true, false); - std::vector<unsigned char> bytes; - ChromeThread::PostTask(ChromeThread::FILE, FROM_HERE, - NewRunnableFunction(&ReadScreenshot, filename, - &bytes, &read_complete)); - read_complete.Wait(); - return bytes; -} -#endif - -std::vector<unsigned char> DOMUIScreenshotSource::GetScreenshot( - const std::string& path) { - if (path == kCurrentScreenshot) { - return current_screenshot_; -#if defined(OS_CHROMEOS) - } else if (path.compare(0, strlen(kSavedScreenshots), - kSavedScreenshots) == 0) { - // Split the saved screenshot filename from the path - std::string filename = path.substr(strlen(kSavedScreenshots)); - - return GetSavedScreenshot(filename); -#endif - } else { - std::vector<unsigned char> ret; - // TODO(rkc): Weird vc bug, return std::vector<unsigned char>() causes - // the object assigned to the return value of this function magically - // change it's address 0x0; look into this eventually. - return ret; - } -} - -DOMUIScreenshotSource::DOMUIScreenshotSource( - std::vector<unsigned char>* current_screenshot) - : DataSource(chrome::kChromeUIScreenshotPath, MessageLoop::current()) { - // Setup the last screenshot taken. - if (current_screenshot) - current_screenshot_ = *current_screenshot; - else - current_screenshot_.clear(); -} - -void DOMUIScreenshotSource::StartDataRequest(const std::string& path, - bool is_off_the_record, - int request_id) { - SendResponse(request_id, new RefCountedBytes(GetScreenshot(path))); -} diff --git a/chrome/browser/dom_ui/dom_ui_screenshot_source.h b/chrome/browser/dom_ui/dom_ui_screenshot_source.h deleted file mode 100644 index be4e280..0000000 --- a/chrome/browser/dom_ui/dom_ui_screenshot_source.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_DOM_UI_DOM_UI_SCREENSHOT_SOURCE_H_ -#define CHROME_BROWSER_DOM_UI_DOM_UI_SCREENSHOT_SOURCE_H_ - -#include <string> -#include <utility> -#include <vector> - -#include "base/basictypes.h" -#include "base/scoped_ptr.h" -#include "chrome/browser/dom_ui/chrome_url_data_manager.h" -#include "chrome/browser/dom_ui/html_dialog_ui.h" - -// ScreenshotSource is the data source that serves screenshots (saved -// or current) to the bug report html ui -class DOMUIScreenshotSource : public ChromeURLDataManager::DataSource { - public: - explicit DOMUIScreenshotSource( - std::vector<unsigned char>* current_screenshot); - - // Called when the network layer has requested a resource underneath - // the path we registered. - virtual void StartDataRequest(const std::string& path, - bool is_off_the_record, - int request_id); - - virtual std::string GetMimeType(const std::string&) const { - // We need to explicitly return a mime type, otherwise if the user tries to - // drag the image they get no extension. - return "image/png"; - } - - std::vector<unsigned char> GetScreenshot(const std::string& path); - - private: - ~DOMUIScreenshotSource() {} - -// scoped_refptr<RefCountedBytes> current_screenshot_; - std::vector<unsigned char> current_screenshot_; - DISALLOW_COPY_AND_ASSIGN(DOMUIScreenshotSource); -}; - -#endif // CHROME_BROWSER_DOM_UI_DOM_UI_SCREENSHOT_SOURCE_H_ diff --git a/chrome/browser/resources/bug_report.css b/chrome/browser/resources/bug_report.css deleted file mode 100644 index 09230c1..0000000 --- a/chrome/browser/resources/bug_report.css +++ /dev/null @@ -1,99 +0,0 @@ -.bug-report-label { - text-align: start; - vertical-align: text-top; -} - -.bug-report-text { - width: 40em; - resize: none; -} - -.bug-report-button { - width: 8em; -} - -hr { - border: none; - height: 1px; - background: #cccccc; - margin-top: 10px; - margin-bottom: 10px; - width: 33.5em; -} - -.thumbnail-list { - -webkit-margin-start: 1em; - width: 33.5em; - display: block; - margin-top: 0.5em; - margin-bottom: 1em; -} - -.image-thumbnail-container { - display: inline-block; - border: 2px solid white; - -webkit-border-radius: 3px; - z-index: 0; -} - -.image-thumbnail-container-selected { - display: inline-block; - border: 2px solid green; - -webkit-border-radius: 3px; - z-index: 0; -} - -.image-thumbnail-container:hover { - border: 2px solid #B8DAB0; - z-index: 0; -} - -.image-popup { - width: 50%; -} - -.image-thumbnail { - position: relative; - z-index: 1; - display: inline-block; - padding: 0px; - border: 2px solid white; -} - -.image-thumbnail:hover { - z-index: 2; -} - -.image-thumbnail div { - display: none; -} - -.image-thumbnail img { - display: block; - width: 75px; -} - -.image-thumbnail:hover div { - display: block; - position: absolute; - top: 130%; - left:0; - padding: 1px; - border: 1px dashed blue; - background-color: transparent; - text-align: center -} - -.image-thumbnail:hover div img { - position: absolute; - width: 400px; -} - -th { - padding-top: 10px; - color: #233478; -} - -body { - -webkit-user-select: none; -} diff --git a/chrome/browser/resources/bug_report.html b/chrome/browser/resources/bug_report.html deleted file mode 100644 index c3b53ce..0000000 --- a/chrome/browser/resources/bug_report.html +++ /dev/null @@ -1,135 +0,0 @@ -<!DOCTYPE HTML> -<html i18n-values="dir:textdirection;"> -<head> -<meta charset="utf-8"/> -<title i18n-content="title"></title> -<link rel="stylesheet" href="bug_report.css"/> - -<script src="shared/js/local_strings.js"></script> -<script src="shared/js/util.js"></script> -<script src="bug_report.js"></script> -<script> - -/////////////////////////////////////////////////////////////////////////////// -// Document Functions: -/** - * Window onload handler, sets up the page. - */ -function load() {
- // textContent on description-text textarea seems to default
- // to several spaces, this resets it to empty.
- $('description-text').textContent = '';
-
- $('current-screenshot').nextSibling.textContent =
- localStrings.getString('currentscreenshots');
- $('no-screenshot').nextSibling.textContent =
- localStrings.getString('noscreenshot');
-
- // Get a list of issues that we allow the user to select from.
- // Note, the order and the issues types themselves are different
- // between Chromium and Chromium OS, so this code needs to be
- // maintained individually between the bug_report.html and
- // bug_report_cros.html files.
- var issueTypeText = []; - issueTypeText[0] = localStrings.getString('issue-choose');
- issueTypeText[1] = localStrings.getString('issue-page-formatting');
- issueTypeText[2] = localStrings.getString('issue-page-load');
- issueTypeText[3] = localStrings.getString('issue-plugins');
- issueTypeText[4] = localStrings.getString('issue-tabs');
- issueTypeText[5] = localStrings.getString('issue-sync');
- issueTypeText[6] = localStrings.getString('issue-crashes');
- issueTypeText[7] = localStrings.getString('issue-extensions');
- issueTypeText[8] = localStrings.getString('issue-phishing');
- issueTypeText[9] = localStrings.getString('issue-other');
-
- // Add all the issues to the selection box.
- for (var i = 0; i < issueTypeText.length; i++) {
- var option = document.createElement('option');
- option.className = 'bug-report-text';
- option.textContent = issueTypeText[i];
- $('issue-with-combo').add(option);
- }
-
- chrome.send('getDialogDefaults', []);
- chrome.send('refreshScreenshots', []);
-};
-
-function setupScreenshots(screenshots) { - if (screenshots.length > 0) - addScreenshot('current-screenshots', screenshots[0]); -} - -function setupDialogDefaults(defaults) { - if (defaults.length > 0) - $('page-url-text').value = defaults[0];
-}
-
-window.addEventListener('DOMContentLoaded', load); -</script> -</head> -<body> -<table> - <!-- Issue type dropdown --> - <tr> - <th id="issue-with" class="bug-report-label" i18n-content="issue-with"> - </th> - </tr> - <tr> - <td> - <select id="issue-with-combo" class="bug-report-text"> - </select> - </td> - </tr> - <!-- Page URL text box --> - <tr> - <th colspan="2" id="page-url" class="bug-report-label" - i18n-content="page-url"> - </th> - </tr> - <tr> - <td colspan="2"> - <input id='page-url-text' maxlength=200 class="bug-report-text"> - </td> - </tr> - <!-- Description --> - <tr> - <th id="description" colspan="2" class="bug-report-label" - i18n-content="description"> - </th> - </tr> - <tr> - <td colspan="2"> - <textarea id='description-text' rows="10" class="bug-report-text"> - </textarea> - </td> - </tr> - <!-- Screenshot radio buttons --> - <tr> - <th id="screenshot" class="bug-report-label" i18n-content="screenshot"> - </th> - </tr> - <tr> - <td> - <input id="no-screenshot" type="radio" name="screenshot-group" - value="none" onclick="noneSelected()"> - <br> - <input id="current-screenshot" type="radio" name="screenshot-group" - value="current" checked onclick="currentSelected()"> - <br> - <div id="current-screenshots" class="thumbnail-list"> - </div> - </td> - </tr> - <!-- Buttons --> - <tr> - <td> - <hr> - <input id='send-report-button' type="submit" class="bug-report-button" - i18n-values="value:send-report" onclick="sendReport()"> - <input id='cancel-button' type="submit" class="bug-report-button" - i18n-values="value:cancel" onclick="cancel()"> - </td> - </tr> -</table> -</body> -</html> diff --git a/chrome/browser/resources/bug_report.js b/chrome/browser/resources/bug_report.js deleted file mode 100644 index 508a954..0000000 --- a/chrome/browser/resources/bug_report.js +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Constants. -var FEEDBACK_LANDING_PAGE = - 'http://www.google.com/support/chrome/go/feedback_confirmation' - -var selectedThumbnailDivId = ''; -var selectedThumbnailId = ''; -var selectedImageUrl; - -var savedThumbnailIds = []; -savedThumbnailIds['current-screenshots'] = ''; -savedThumbnailIds['saved-screenshots'] = ''; - -var localStrings = new LocalStrings(); - -/** - * Selects an image thumbnail in the specified div. - */ -function selectImage(divId, thumbnailId) { - var thumbnailDivs = $(divId).children; - selectedThumbnailDivId = divId; - for (var i = 0; i < thumbnailDivs.length; i++) { - // If the the current div matches the thumbnail id provided, - // or there is no thumbnail id given, and we're at the first thumbnail. - if ((thumbnailDivs[i].id == thumbnailId) || (!thumbnailId && !i)) { - thumbnailDivs[i].className = 'image-thumbnail-container-selected'; - selectedThumbnailId = thumbnailId; - savedThumbnailIds[divId] = thumbnailId; - } else { - thumbnailDivs[i].className = 'image-thumbnail-container'; - } - } -} - -/** - * Adds an image thumbnail to the specified div. - */ -function addScreenshot(divId, screenshot) { - var thumbnailDiv = document.createElement('div'); - thumbnailDiv.className = 'image-thumbnail-container'; - - thumbnailDiv.id = divId + '-thumbnailDiv-' + $(divId).children.length; - thumbnailDiv.onclick = function() { - selectImage(divId, thumbnailDiv.id); - }; - - var innerDiv = document.createElement('div'); - innerDiv.className = 'image-thumbnail'; - - var thumbnail = document.createElement('img'); - thumbnail.id = thumbnailDiv.id + '-image'; - thumbnail.src = screenshot; - innerDiv.appendChild(thumbnail); - - var largeImage = document.createElement('img'); - largeImage.src = screenshot; - - var popupDiv = document.createElement('div'); - popupDiv.appendChild(largeImage); - innerDiv.appendChild(popupDiv); - - thumbnailDiv.appendChild(innerDiv); - $(divId).appendChild(thumbnailDiv); - - if (!selectedThumbnailId) - selectImage(divId, thumbnailDiv.id); -} - -/** - * Send's the report; after the report is sent, we need to be redirected to - * the landing page, but we shouldn't be able to navigate back, hence - * we open the landing page in a new tab and sendReport closes this tab. - */ -function sendReport() { - if (!$('issue-with-combo').selectedIndex) { - alert(localStrings.getString('no-issue-selected')); - return false; - } - - var imagePath = ''; - if (selectedThumbnailId) - imagePath = $(selectedThumbnailId + '-image').src; - - // Note, categories are based from 1 in our protocol buffers, so no - // adjustment is needed on selectedIndex. - var reportArray = [String($('issue-with-combo').selectedIndex), - $('page-url-text').value, - $('description-text').value, - imagePath]; - - // Add chromeos data if it exists. - if ($('user-email-text') && $('sys-info-checkbox')) { - reportArray = reportArray.concat([$('user-email-text').value, - String($('sys-info-checkbox').checked)]); - } - - // open the landing page in a new tab, sendReport will close this one. - window.open(FEEDBACK_LANDING_PAGE, '_blank'); - chrome.send('sendReport', reportArray); - return true; -} - -function cancel() { - chrome.send('cancel', []); - return true; -} - -/** - * Select the current screenshots div, restoring the image that was - * selected when we had this div open previously. - */ -function currentSelected() { - $('current-screenshots').style.display = 'block'; - if ($('saved-screenshots')) - $('saved-screenshots').style.display = 'none'; - - if (selectedThumbnailDivId != 'current-screenshots') - selectImage('current-screenshots', - savedThumbnailIds['current-screenshots']); - - return true; -} - -/** - * Select the saved screenshots div, restoring the image that was - * selected when we had this div open previously. - */ -function savedSelected() { - $('current-screenshots').style.display = 'none'; - $('saved-screenshots').style.display = 'block'; - - if (selectedThumbnailDivId != 'saved-screenshots') - selectImage('saved-screenshots', savedThumbnailIds['saved-screenshots']); - - return true; -} - -/** - * Unselect all screenshots divs. - */ -function noneSelected() { - $('current-screenshots').style.display = 'none'; - if ($('saved-screenshots')) - $('saved-screenshots').style.display = 'none'; - - selectedThumbnailDivId = ''; - selectedThumbnailId = ''; - return true; -} diff --git a/chrome/browser/resources/bug_report_cros.html b/chrome/browser/resources/bug_report_cros.html deleted file mode 100644 index d001c7e..0000000 --- a/chrome/browser/resources/bug_report_cros.html +++ /dev/null @@ -1,169 +0,0 @@ -<!DOCTYPE HTML> -<html i18n-values="dir:textdirection;"> -<head> -<meta charset="utf-8"/> -<title i18n-content="title"></title> -<link rel="stylesheet" href="bug_report.css"/> - -<script src="shared/js/local_strings.js"></script> -<script src="shared/js/util.js"></script> -<script src="bug_report.js"></script> -<script> - -/////////////////////////////////////////////////////////////////////////////// -// Document Functions: -/** - * Window onload handler, sets up the page. - */ -function load() { - // textContent on description-text textarea seems to default - // to several spaces, this resets it to empty. - $('description-text').textContent = ''; - - $('current-screenshot').nextSibling.textContent = - localStrings.getString('currentscreenshots'); - $('saved-screenshot').nextSibling.textContent = - localStrings.getString('savedscreenshots'); - $('no-screenshot').nextSibling.textContent = - localStrings.getString('noscreenshot'); - - // Get a list of issues that we allow the user to select from. - // Note, the order and the issues types themselves are different - // between Chromium and Chromium OS, so this code needs to be - // maintained individually between the bug_report.html and - // bug_report_cros.html files. - var issueTypeText = []; - issueTypeText[0] = localStrings.getString('issue-choose'); - issueTypeText[1] = localStrings.getString('issue-connectivity'); - issueTypeText[2] = localStrings.getString('issue-sync'); - issueTypeText[3] = localStrings.getString('issue-crashes'); - issueTypeText[4] = localStrings.getString('issue-page-formatting'); - issueTypeText[5] = localStrings.getString('issue-extensions'); - issueTypeText[6] = localStrings.getString('issue-standby'); - issueTypeText[7] = localStrings.getString('issue-phishing'); - issueTypeText[8] = localStrings.getString('issue-other'); - - // Add all the issues to the selection box. - for (var i = 0; i < issueTypeText.length; i++) { - var option = document.createElement('option'); - option.className = 'bug-report-text'; - option.textContent = issueTypeText[i]; - $('issue-with-combo').add(option); - } - - chrome.send('getDialogDefaults', []); - chrome.send('refreshScreenshots', []); -}; - -function setupScreenshots(screenshots) { - if (screenshots.length > 1) { - currentScreenshot = screenshots[0]; - addScreenshot('current-screenshots', currentScreenshot); - - savedScreenshots = screenshots[1]; - for (i = 0; i < savedScreenshots.length; ++i) - addScreenshot('saved-screenshots', savedScreenshots[i]); - } -} - -function setupDialogDefaults(defaults) { - if (defaults.length > 2) { - $('page-url-text').value = defaults[0]; - $('sysinfo-url').href = defaults[1]; - $('user-email-text').value = defaults[2]; - } -} - -window.addEventListener('DOMContentLoaded', load); -</script> -</head> -<body> -<table> - <!-- Issue type dropdown --> - <tr> - <th id="issue-with" class="bug-report-label" i18n-content="issue-with"> - </th> - </tr> - <tr> - <td> - <select id="issue-with-combo" class="bug-report-text"> - </select> - </td> - </tr> - <!-- Page URL text box --> - <tr> - <th colspan="2" id="page-url" class="bug-report-label" - i18n-content="page-url"> - </th> - </tr> - <tr> - <td colspan="2"> - <input id='page-url-text' maxlength=200 class="bug-report-text"> - </td> - </tr> - <!-- Description --> - <tr> - <th id="description" colspan="2" class="bug-report-label" - i18n-content="description"> - </th> - </tr> - <tr> - <td colspan="2"> - <textarea id='description-text' rows="10" class="bug-report-text"> - </textarea> - </td> - </tr> - <!-- System Information checkbox --> - <tr> - <td> - <input id="sys-info-checkbox" type="checkbox" value="sysinfo" checked> - <span id="sysinfo-label"></span> <a href='about:blank' id="sysinfo-url" - target="_blank" i18n-content="sysinfo">></a> - </td> - </tr> - <!-- Page URL text box --> - <tr> - <th id="user-email" class="bug-report-label" i18n-content="user-email"> - </th> - </tr> - <tr> - <td> - <input id='user-email-text' maxlength=200 class="bug-report-text"> - </td> - </tr> - <!-- Screenshot radio buttons --> - <tr> - <th id="screenshot" class="bug-report-label" i18n-content="screenshot"> - </th> - </tr> - <tr> - <td> - <input id="no-screenshot" type="radio" name="screenshot-group" - value="none" onclick="noneSelected()"> - <br> - <input id="saved-screenshot" type="radio" name="screenshot-group" - value="saved" onclick="savedSelected()"> - <br> - <div id="saved-screenshots" style="display: none;" - class="thumbnail-list"> - </div> - <input id="current-screenshot" type="radio" name="screenshot-group" - value="current" checked onclick="currentSelected()"> - <br> - <div id="current-screenshots" class="thumbnail-list"> - </div> - </td> - </tr> - <!-- Buttons --> - <tr> - <td> - <hr> - <input id='send-report-button' type="submit" class="bug-report-button" - i18n-values="value:send-report" onclick="sendReport()"> - <input id='cancel-button' type="submit" class="bug-report-button" - i18n-values="value:cancel" onclick="cancel()"> - </td> - </tr> -</table> -</body> -</html> diff --git a/chrome/browser/resources/bug_report_invalid.html b/chrome/browser/resources/bug_report_invalid.html deleted file mode 100644 index e6b1605..0000000 --- a/chrome/browser/resources/bug_report_invalid.html +++ /dev/null @@ -1,10 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> -<meta charset="utf-8"> -</head> -<title i18n-content="title"></title> -<body onselectstart='return false'> -Invalid BugReport options - please check. -</body> -</html> diff --git a/chrome/browser/userfeedback/proto/chrome.proto b/chrome/browser/userfeedback/proto/chrome.proto deleted file mode 100644 index 11b8eff..0000000 --- a/chrome/browser/userfeedback/proto/chrome.proto +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// Author: marcinm@google.com (Marcin Mikosik) - -syntax = "proto2"; - -package userfeedback; - -// Chrome Browser and Chrome OS specific data. -message ChromeData { - // Encapsulates the priorities of Buganizer issues. - enum ChromePlatform { - CHROME_OS = 1; - CHROME_BROWSER = 2; - } - - // What platform has a report been sent from. - optional ChromePlatform chrome_platform = 1 [default = CHROME_OS]; - - optional ChromeOsData chrome_os_data = 2; - - optional ChromeBrowserData chrome_browser_data = 3; -} - -message ChromeOsData { - enum ChromeOsCategory { - CONNECTIVITY = 1; - SYNC = 2; - CRASH = 3; - PAGE_FORMATTING_OR_LAYOUT = 4; - EXTENSIONS_OR_APPS = 5; - STANDBY_OR_RESUME = 6; - PHISHING_PAGE = 7; - OTHER = 8; - } - - optional ChromeOsCategory category = 1 [default = OTHER]; -} - -message ChromeBrowserData{ - - enum ChromeBrowserCategory { - PAGE_FORMATTING_OR_LAYOUT = 1; - PAGES_NOT_LOADING = 2; - PLUGINS = 3; - TABS_OR_WINDOWS = 4; - SYNCED_PREFERENCES = 5; - CRASH = 6; - EXTENSIONS_OR_APPS = 7; - PHISHING_PAGE = 8; - OTHER = 9; - } - - optional ChromeBrowserCategory category = 1 [default = OTHER]; -} - diff --git a/chrome/browser/userfeedback/proto/common.proto b/chrome/browser/userfeedback/proto/common.proto index 291e6a1..97c60fb 100644 --- a/chrome/browser/userfeedback/proto/common.proto +++ b/chrome/browser/userfeedback/proto/common.proto @@ -16,13 +16,7 @@ message CommonData { // Description of the problem entered by user. optional string description = 2; optional string description_translated = 4; - optional string source_description_language = 5 [ default = "en" ]; - optional string ui_language = 6 [ default = "en_US" ]; + optional string source_descripton_language = 5 [ default = "en" ]; optional string user_email = 3; - - // Unique identifier of feedback report. If set than only one report - // with the same identifier is stored in the system. - // If you are not sure how to use it leave it not set. - optional string unique_report_identifier = 7; }; diff --git a/chrome/browser/userfeedback/proto/extension.proto b/chrome/browser/userfeedback/proto/extension.proto index 71be3dc..d600f8a 100644 --- a/chrome/browser/userfeedback/proto/extension.proto +++ b/chrome/browser/userfeedback/proto/extension.proto @@ -8,7 +8,6 @@ syntax = "proto2"; package userfeedback; import "common.proto"; -import "chrome.proto"; import "dom.proto"; import "math.proto"; import "web.proto"; @@ -65,8 +64,6 @@ message ExternalExtensionSubmit { optional HtmlDocument html_document_structure = 5; optional ExtensionErrors extension_errors = 13; - - optional ChromeData chrome_data = 14; }; // Sent when user hits final submit button in internal extension. diff --git a/chrome/browser/userfeedback/proto/web.proto b/chrome/browser/userfeedback/proto/web.proto index 71b0b29..fb9f6af 100644 --- a/chrome/browser/userfeedback/proto/web.proto +++ b/chrome/browser/userfeedback/proto/web.proto @@ -8,6 +8,7 @@ package userfeedback; // Data present in Web related feedbacks import "annotations.proto"; +import "config.proto"; import "dom.proto"; import "math.proto"; diff --git a/chrome/browser/views/browser_dialogs.h b/chrome/browser/views/browser_dialogs.h index 8affac9..f775d97 100644 --- a/chrome/browser/views/browser_dialogs.h +++ b/chrome/browser/views/browser_dialogs.h @@ -45,9 +45,6 @@ void ShowBugReportView(views::Window* parent, Profile* profile, TabContents* tab); -// Shows the "Report a problem with this page" page in a new tab -void ShowHtmlBugReportView(views::Window* parent, Browser* browser); - // Shows the "Clear browsing data" dialog box. See ClearBrowsingDataView. void ShowClearBrowsingDataView(gfx::NativeWindow parent, Profile* profile); diff --git a/chrome/browser/views/bug_report_view.cc b/chrome/browser/views/bug_report_view.cc new file mode 100644 index 0000000..03cbc76 --- /dev/null +++ b/chrome/browser/views/bug_report_view.cc @@ -0,0 +1,627 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/views/bug_report_view.h" + +#include <string> +#include <vector> + +#include "app/combobox_model.h" +#include "app/l10n_util.h" +#include "base/file_path.h" +#include "base/file_util.h" +#include "base/file_version_info.h" +#include "base/path_service.h" +#include "base/utf_string_conversions.h" +#include "base/waitable_event.h" +#include "chrome/browser/bug_report_util.h" +#include "chrome/browser/pref_service.h" +#include "chrome/browser/profile.h" +#include "chrome/browser/browser_list.h" +#include "chrome/browser/chrome_thread.h" +#include "chrome/browser/safe_browsing/safe_browsing_util.h" +#include "chrome/browser/tab_contents/navigation_controller.h" +#include "chrome/browser/tab_contents/navigation_entry.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/chrome_version_info.h" +#include "chrome/common/net/url_fetcher.h" +#include "chrome/common/pref_names.h" +#include "chrome/common/url_constants.h" +#include "grit/chromium_strings.h" +#include "grit/generated_resources.h" +#include "grit/locale_settings.h" +#include "net/base/escape.h" +#include "unicode/locid.h" +#include "views/controls/button/checkbox.h" +#include "views/controls/label.h" +#include "views/grid_layout.h" +#include "views/standard_layout.h" +#include "views/widget/widget.h" +#include "views/window/client_view.h" +#include "views/window/window.h" + +#if defined(OS_LINUX) +#include "app/x11_util.h" +#else +#include "app/win_util.h" +#endif + +#if defined(OS_CHROMEOS) +#include "chrome/browser/chromeos/login/user_manager.h" +#endif + +using views::ColumnSet; +using views::GridLayout; + +// Report a bug data version. +static const int kBugReportVersion = 1; +static const int kScreenImageRadioGroup = 2; +static const char kScreenshotsRelativePath[] = "/Screenshots"; +static const char kScreenshotPattern[] = "*.png"; + +// Number of lines description field can display at one time. +static const int kDescriptionLines = 5; + +class BugReportComboBoxModel : public ComboboxModel { + public: + BugReportComboBoxModel() {} + + // ComboboxModel interface. + virtual int GetItemCount() { + return BugReportUtil::OTHER_PROBLEM + 1; + } + + virtual std::wstring GetItemAt(int index) { + return GetItemAtIndex(index); + } + + static std::wstring GetItemAtIndex(int index) { +#if defined(OS_CHROMEOS) + switch (index) { + case BugReportUtil::CONNECTIVITY_ISSUE: + return l10n_util::GetString(IDS_BUGREPORT_CONNECTIVITY_ISSUE); + case BugReportUtil::SYNC_ISSUE: + return l10n_util::GetString(IDS_BUGREPORT_SYNC_ISSUE); + case BugReportUtil::CRASH_ISSUE: + return l10n_util::GetString(IDS_BUGREPORT_CRASH_ISSUE); + case BugReportUtil::PAGE_FORMATTING: + return l10n_util::GetString(IDS_BUGREPORT_PAGE_FORMATTING); + case BugReportUtil::EXTENSION_ISSUE: + return l10n_util::GetString(IDS_BUGREPORT_EXTENSION_ISSUE); + case BugReportUtil::SUSPEND_ISSUE: + return l10n_util::GetString(IDS_BUGREPORT_SUSPEND_ISSUE); + case BugReportUtil::PHISHING_PAGE: + return l10n_util::GetString(IDS_BUGREPORT_PHISHING_PAGE); + case BugReportUtil::OTHER_PROBLEM: + return l10n_util::GetString(IDS_BUGREPORT_OTHER_PROBLEM); + default: + NOTREACHED(); + return std::wstring(); + } +#else + switch (index) { + case BugReportUtil::PAGE_WONT_LOAD: + return l10n_util::GetString(IDS_BUGREPORT_PAGE_WONT_LOAD); + case BugReportUtil::PAGE_LOOKS_ODD: + return l10n_util::GetString(IDS_BUGREPORT_PAGE_LOOKS_ODD); + case BugReportUtil::PHISHING_PAGE: + return l10n_util::GetString(IDS_BUGREPORT_PHISHING_PAGE); + case BugReportUtil::CANT_SIGN_IN: + return l10n_util::GetString(IDS_BUGREPORT_CANT_SIGN_IN); + case BugReportUtil::CHROME_MISBEHAVES: + return l10n_util::GetString(IDS_BUGREPORT_CHROME_MISBEHAVES); + case BugReportUtil::SOMETHING_MISSING: + return l10n_util::GetString(IDS_BUGREPORT_SOMETHING_MISSING); + case BugReportUtil::BROWSER_CRASH: + return l10n_util::GetString(IDS_BUGREPORT_BROWSER_CRASH); + case BugReportUtil::OTHER_PROBLEM: + return l10n_util::GetString(IDS_BUGREPORT_OTHER_PROBLEM); + default: + NOTREACHED(); + return std::wstring(); + } +#endif + } + + private: + DISALLOW_COPY_AND_ASSIGN(BugReportComboBoxModel); +}; + +namespace { + +#if defined(OS_CHROMEOS) +class LastScreenshotTask : public Task { + public: + LastScreenshotTask(std::string* image_str, + base::WaitableEvent* task_waitable) + : image_str_(image_str), + task_waitable_(task_waitable) { + } + + private: + void Run() { + FilePath fileshelf_path; + // TODO(rkc): Change this to use FilePath.Append() once the cros + // issue with with it is fixed + if (!PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, + &fileshelf_path)) { + *image_str_ = ""; + task_waitable_->Signal(); + } + + FilePath screenshots_path(fileshelf_path.value() + + std::string(kScreenshotsRelativePath)); + file_util::FileEnumerator screenshots(screenshots_path, false, + file_util::FileEnumerator::FILES, + std::string(kScreenshotPattern)); + FilePath screenshot = screenshots.Next(); + FilePath latest(""); + time_t last_mtime = 0; + while (!screenshot.empty()) { + file_util::FileEnumerator::FindInfo info; + screenshots.GetFindInfo(&info); + if (info.stat.st_mtime > last_mtime) { + last_mtime = info.stat.st_mtime; + latest = screenshot; + } + screenshot = screenshots.Next(); + } + + if (!file_util::ReadFileToString(latest, image_str_)) + *image_str_ = ""; + task_waitable_->Signal(); + } + private: + std::string* image_str_; + base::WaitableEvent* task_waitable_; +}; +#endif + +bool GetLastScreenshot(std::string* image_str) { +#if defined(OS_CHROMEOS) + base::WaitableEvent task_waitable(true, false); + ChromeThread::PostTask(ChromeThread::FILE, FROM_HERE, + new LastScreenshotTask(image_str, &task_waitable)); + task_waitable.Wait(); + if (*image_str == "") + return false; + else + return true; +#else + return false; +#endif +} + +} // namespace + +namespace browser { + +// Global "display this dialog" function declared in browser_dialogs.h. +void ShowBugReportView(views::Window* parent, + Profile* profile, + TabContents* tab) { + BugReportView* view = new BugReportView(profile, tab); + + // Get the size of the parent window to capture screenshot dimensions + gfx::Rect screen_size = parent->GetBounds(); + view->set_screen_size(screen_size); + + // Grab an exact snapshot of the window that the user is seeing (i.e. as + // rendered--do not re-render, and include windowed plugins). + std::vector<unsigned char> *screenshot_png = new std::vector<unsigned char>; + +#if defined(OS_LINUX) + x11_util::GrabWindowSnapshot(parent->GetNativeWindow(), screenshot_png); +#else + win_util::GrabWindowSnapshot(parent->GetNativeWindow(), screenshot_png); +#endif + + // The BugReportView takes ownership of the image data, and will dispose of + // it in its destructor + view->set_captured_image(screenshot_png); + +#if defined(OS_CHROMEOS) + // Get last screenshot taken + std::string image_str; + bool have_last_image = false; + if (GetLastScreenshot(&image_str)) { + // reuse screenshot_png; previous pointer now owned by BugReportView + screenshot_png = new std::vector<unsigned char>(image_str.begin(), + image_str.end()); + have_last_image = true; + } else { + // else set it to be an empty vector + screenshot_png = new std::vector<unsigned char>; + } + view->set_last_image(screenshot_png); + + // Create and show the dialog + views::Window::CreateChromeWindow(parent->GetNativeWindow(), gfx::Rect(), + view)->Show(); + if (!have_last_image) + view->DisableLastImageRadio(); +#endif +} + +} // namespace browser + +// 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) + : include_page_source_checkbox_(NULL), + include_page_image_checkbox_(NULL), + profile_(profile), + tab_(tab), + problem_type_(0) { + DCHECK(profile); + SetupControl(); + + // We want to use the URL of the current committed entry (the current URL may + // actually be the pending one). + if (tab->controller().GetActiveEntry()) { + page_url_text_->SetText(UTF8ToUTF16( + tab->controller().GetActiveEntry()->url().spec())); + } + +#if defined(OS_CHROMEOS) + // Get and set the gaia e-mail + chromeos::UserManager* manager = chromeos::UserManager::Get(); + if (!manager) { + user_email_text_->SetText(UTF8ToUTF16(std::string(""))); + } else { + const std::string& email = manager->logged_in_user().email(); + user_email_text_->SetText(UTF8ToUTF16(email)); + if (!email.empty()) + user_email_text_->SetEnabled(false); + } +#endif + + // Retrieve the application version info. + scoped_ptr<FileVersionInfo> version_info(chrome::GetChromeVersionInfo()); + if (version_info.get()) { + version_ = version_info->product_name() + L" - " + + version_info->file_version() + + L" (" + version_info->last_change() + L")"; + } + + + FilePath tmpfilename; + +#if defined(OS_CHROMEOS) + chromeos::SyslogsLibrary* syslogs_lib = + chromeos::CrosLibrary::Get()->GetSyslogsLibrary(); + if (syslogs_lib) { + sys_info_.reset(syslogs_lib->GetSyslogs(&tmpfilename)); + } +#endif +} + +BugReportView::~BugReportView() { +} + +void BugReportView::SetupControl() { + bug_type_model_.reset(new BugReportComboBoxModel); + + // Adds all controls. + bug_type_label_ = new views::Label( + l10n_util::GetString(IDS_BUGREPORT_BUG_TYPE)); + bug_type_combo_ = new views::Combobox(bug_type_model_.get()); + bug_type_combo_->set_listener(this); + bug_type_combo_->SetAccessibleName(bug_type_label_->GetText()); + + page_title_label_ = new views::Label( + l10n_util::GetString(IDS_BUGREPORT_REPORT_PAGE_TITLE)); + page_title_text_ = new views::Label(UTF16ToWideHack(tab_->GetTitle())); + page_url_label_ = new views::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 views::Textfield; + page_url_text_->SetController(this); + page_url_text_->SetAccessibleName(page_url_label_->GetText()); + +#if defined(OS_CHROMEOS) + user_email_label_ = new views::Label( + l10n_util::GetString(IDS_BUGREPORT_USER_EMAIL_LABEL)); + // user_email_text_'s text (if any) is filled in after dialog creation. + user_email_text_ = new views::Textfield; + user_email_text_->SetController(this); + user_email_text_->SetAccessibleName(user_email_label_->GetText()); +#endif + + description_label_ = new views::Label( + l10n_util::GetString(IDS_BUGREPORT_DESCRIPTION_LABEL)); + description_text_ = + new views::Textfield(views::Textfield::STYLE_MULTILINE); + description_text_->SetHeightInLines(kDescriptionLines); + description_text_->SetAccessibleName(description_label_->GetText()); + + include_page_source_checkbox_ = new views::Checkbox( + l10n_util::GetString(IDS_BUGREPORT_INCLUDE_PAGE_SOURCE_CHKBOX)); + include_page_source_checkbox_->SetChecked(true); + +#if defined(OS_CHROMEOS) + include_last_screen_image_radio_ = new views::RadioButton( + l10n_util::GetString(IDS_BUGREPORT_INCLUDE_LAST_SCREEN_IMAGE), + kScreenImageRadioGroup); + + include_new_screen_image_radio_ = new views::RadioButton( + l10n_util::GetString(IDS_BUGREPORT_INCLUDE_NEW_SCREEN_IMAGE), + kScreenImageRadioGroup); + + include_no_screen_image_radio_ = new views::RadioButton( + l10n_util::GetString(IDS_BUGREPORT_INCLUDE_NO_SCREEN_IMAGE), + kScreenImageRadioGroup); + + system_information_url_control_ = new views::Link( + l10n_util::GetString(IDS_BUGREPORT_SYSTEM_INFORMATION_URL_TEXT)); + system_information_url_control_->SetController(this); + + include_new_screen_image_radio_->SetChecked(true); +#endif + include_page_image_checkbox_ = new views::Checkbox( + l10n_util::GetString(IDS_BUGREPORT_INCLUDE_PAGE_IMAGE_CHKBOX)); + include_page_image_checkbox_->SetChecked(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); +#if defined(OS_CHROMEOS) + layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); + // Page URL and text field. + layout->StartRow(0, column_set_id); + layout->AddView(user_email_label_); + layout->AddView(user_email_text_); +#endif + 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); +#if defined(OS_CHROMEOS) + // Radio boxes to select last screen shot or, + + // new screenshot + layout->AddView(include_new_screen_image_radio_); + layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); + // last screenshot taken + layout->StartRow(0, column_set_id); + layout->SkipColumns(1); + layout->AddView(include_last_screen_image_radio_); + layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); + // no screenshot + layout->StartRow(0, column_set_id); + layout->SkipColumns(1); + layout->AddView(include_no_screen_image_radio_); + layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing); + + layout->StartRow(0, column_set_id); + layout->SkipColumns(1); + layout->AddView(system_information_url_control_, 1, 1, GridLayout::LEADING, + GridLayout::CENTER); +#else + if (include_page_image_checkbox_) { + layout->StartRow(0, column_set_id); + layout->SkipColumns(1); + layout->AddView(include_page_image_checkbox_); + } +#endif + + layout->AddPaddingRow(0, kUnrelatedControlVerticalSpacing); +} + +gfx::Size BugReportView::GetPreferredSize() { + gfx::Size size = views::Window::GetLocalizedContentsSize( + IDS_BUGREPORT_DIALOG_WIDTH_CHARS, +#if defined(OS_CHROMEOS) + IDS_CHROMEOS_BUGREPORT_DIALOG_HEIGHT_LINES); +#else + IDS_BUGREPORT_DIALOG_HEIGHT_LINES); +#endif + return size; +} + +void BugReportView::UpdateReportingControls(bool is_phishing_report) { + // page source, screen/page images, system information + // are not needed if it's a phishing report + + include_page_source_checkbox_->SetEnabled(!is_phishing_report); + include_page_source_checkbox_->SetChecked(!is_phishing_report); + +#if defined(OS_CHROMEOS) + include_new_screen_image_radio_->SetEnabled(!is_phishing_report); + if (!last_image_->empty()) + include_last_screen_image_radio_->SetEnabled(!is_phishing_report); + include_no_screen_image_radio_->SetEnabled(!is_phishing_report); +#else + if (include_page_image_checkbox_) { + include_page_image_checkbox_->SetEnabled(!is_phishing_report); + include_page_image_checkbox_->SetChecked(!is_phishing_report); + } +#endif +} + +void BugReportView::ItemChanged(views::Combobox* combobox, + int prev_index, + int new_index) { + if (new_index == prev_index) + return; + + problem_type_ = new_index; + bool is_phishing_report = new_index == BugReportUtil::PHISHING_PAGE; + + description_text_->SetEnabled(!is_phishing_report); + description_text_->SetReadOnly(is_phishing_report); + if (is_phishing_report) { + old_report_text_ = UTF16ToWide(description_text_->text()); + description_text_->SetText(string16()); + } else if (!old_report_text_.empty()) { + description_text_->SetText(WideToUTF16Hack(old_report_text_)); + old_report_text_.clear(); + } + + UpdateReportingControls(is_phishing_report); + GetDialogClientView()->UpdateDialogButtons(); +} + +void BugReportView::ContentsChanged(views::Textfield* sender, + const string16& new_contents) { +} + +bool BugReportView::HandleKeystroke(views::Textfield* sender, + const views::Textfield::Keystroke& key) { + return false; +} + +std::wstring BugReportView::GetDialogButtonLabel( + MessageBoxFlags::DialogButton button) const { + if (button == MessageBoxFlags::DIALOGBUTTON_OK) { + if (problem_type_ == BugReportUtil::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 MessageBoxFlags::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(MessageBoxFlags::DIALOGBUTTON_OK)) { + if (problem_type_ == BugReportUtil::PHISHING_PAGE) { + BugReportUtil::ReportPhishing(tab_, + UTF16ToUTF8(page_url_text_->text())); + } else { + char* image_data = NULL; + size_t image_data_size = 0; +#if defined(OS_CHROMEOS) + if (include_new_screen_image_radio_->checked() && + !captured_image_->empty()) { + image_data = reinterpret_cast<char *>(&captured_image_->front()); + image_data_size = captured_image_->size(); + } else if (include_last_screen_image_radio_->checked() && + !last_image_->empty()) { + image_data = reinterpret_cast<char *>(&last_image_->front()); + image_data_size = last_image_->size(); + } +#else + if (include_page_image_checkbox_->checked() && captured_image_.get() && + !captured_image_->empty()) { + image_data = reinterpret_cast<char *>(&captured_image_->front()); + image_data_size = captured_image_->size(); + } +#endif +#if defined(OS_CHROMEOS) + BugReportUtil::SendReport(profile_, + WideToUTF8(page_title_text_->GetText()), + problem_type_, + UTF16ToUTF8(page_url_text_->text()), + UTF16ToUTF8(user_email_text_->text()), + UTF16ToUTF8(description_text_->text()), + image_data, image_data_size, + screen_size_.width(), screen_size_.height(), + WideToUTF8(bug_type_combo_->model()->GetItemAt(problem_type_)), + sys_info_.get()); +#else + BugReportUtil::SendReport(profile_, + WideToUTF8(page_title_text_->GetText()), + problem_type_, + UTF16ToUTF8(page_url_text_->text()), + std::string(), + UTF16ToUTF8(description_text_->text()), + image_data, image_data_size, + screen_size_.width(), screen_size_.height()); +#endif + } + } + return true; +} + +#if defined(OS_CHROMEOS) +void BugReportView::LinkActivated(views::Link* source, + int event_flags) { + GURL url; + if (source == system_information_url_control_) { + url = GURL(chrome::kAboutSystemURL); + } else { + NOTREACHED() << "Unknown link source"; + return; + } + + Browser* browser = BrowserList::GetLastActive(); + if (browser) + browser->OpenURL(url, GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK); +} +#endif + + +views::View* BugReportView::GetContentsView() { + return this; +} diff --git a/chrome/browser/views/bug_report_view.h b/chrome/browser/views/bug_report_view.h new file mode 100644 index 0000000..da9fe41 --- /dev/null +++ b/chrome/browser/views/bug_report_view.h @@ -0,0 +1,173 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_VIEWS_BUG_REPORT_VIEW_H_ +#define CHROME_BROWSER_VIEWS_BUG_REPORT_VIEW_H_ +#pragma once + +#include "chrome/common/net/url_fetcher.h" +#include "gfx/rect.h" +#include "googleurl/src/gurl.h" +#include "views/controls/button/radio_button.h" +#include "views/controls/combobox/combobox.h" +#include "views/controls/textfield/textfield.h" +#include "views/controls/link.h" +#include "views/controls/image_view.h" +#include "views/view.h" +#include "views/window/dialog_delegate.h" + +#if defined(OS_CHROMEOS) +#include "chrome/browser/chromeos/cros/syslogs_library.h" +#include "chrome/browser/chromeos/cros/cros_library.h" +#endif + +namespace views { +class Checkbox; +class Label; +class Throbber; +class Window; +class RadioButton; +class Link; +} + +class Profile; +class TabContents; +class BugReportComboBoxModel; + +// BugReportView draws the dialog that allows the user to report a +// bug in rendering a particular page (note: this is not a crash +// report, which are handled separately by Breakpad). It packages +// up the URL, a text description, system information and optionally +// a screenshot; then it submits the info through https to the google +// feedback chrome end-point. +// +// Note: This UI is being used for the Chrome OS dogfood release only +// In the very next iteration, this will be replaced by a HTML +// based UI, which will be common for all platforms +class BugReportView : public views::View, + public views::DialogDelegate, + public views::Combobox::Listener, +#if defined(OS_CHROMEOS) + public views::LinkController, +#endif + public views::Textfield::Controller { + public: + BugReportView(Profile* profile, TabContents* tab); + virtual ~BugReportView(); + + // NOTE: set_captured_image takes ownership of the vector + void set_captured_image(std::vector<unsigned char>* png_data) { + captured_image_.reset(png_data); + } + + void set_screen_size(const gfx::Rect& screen_size) { + screen_size_ = screen_size; + } + + // Set all additional reporting controls to disabled + // if phishing report + void UpdateReportingControls(bool is_phishing_report); + + // Overridden from views::View: + virtual gfx::Size GetPreferredSize(); + + // views::Textfield::Controller implementation: + virtual void ContentsChanged(views::Textfield* sender, + const string16& new_contents); + virtual bool HandleKeystroke(views::Textfield* sender, + const views::Textfield::Keystroke& key); + + // views::Combobox::Listener implementation: + virtual void ItemChanged(views::Combobox* combobox, int prev_index, + int new_index); + +#if defined(OS_CHROMEOS) + // Overridden from views::LinkController: + virtual void LinkActivated(views::Link* source, int event_flags); + + // Disable the include last image radio control + void DisableLastImageRadio() { + include_last_screen_image_radio_->SetEnabled(false); + } + + // NOTE: set_last_image takes ownership of the vector + void set_last_image(std::vector<unsigned char>* png_data) { + last_image_.reset(png_data); + } +#endif + + // Overridden from views::DialogDelegate: + virtual std::wstring GetDialogButtonLabel( + MessageBoxFlags::DialogButton button) const; + virtual int GetDefaultDialogButton() const; + virtual bool CanResize() const; + virtual bool CanMaximize() const; + virtual bool IsAlwaysOnTop() const; + virtual bool HasAlwaysOnTopMenu() const; + virtual bool IsModal() const; + virtual std::wstring GetWindowTitle() const; + virtual bool Accept(); + virtual views::View* GetContentsView(); + + private: + class PostCleanup; + + // Set OS Version information in a string (maj.minor.build SP) + void SetOSVersion(std::string *os_version); + + // Initializes the controls on the dialog. + void SetupControl(); + // helper function to create a MIME part boundary string + void CreateMimeBoundary(std::string *out); + // Sends the data via an HTTP POST + void SendReport(); + + // Redirects the user to Google's phishing reporting page. + void ReportPhishing(); + + views::Label* bug_type_label_; + views::Combobox* bug_type_combo_; + views::Label* page_title_label_; + views::Label* page_title_text_; + views::Label* page_url_label_; + views::Textfield* page_url_text_; + views::Label* description_label_; + views::Textfield* description_text_; + views::Checkbox* include_page_source_checkbox_; +#if defined(OS_CHROMEOS) + views::Label* user_email_label_; + views::Textfield* user_email_text_; + views::RadioButton* include_new_screen_image_radio_; + views::RadioButton* include_last_screen_image_radio_; + views::RadioButton* include_no_screen_image_radio_; + views::Link* system_information_url_control_; + + scoped_ptr<chromeos::LogDictionaryType> sys_info_; + scoped_ptr< std::vector<unsigned char> > last_image_; +#endif + views::Checkbox* include_page_image_checkbox_; + + + scoped_ptr<BugReportComboBoxModel> bug_type_model_; + + Profile* profile_; + + std::wstring version_; + gfx::Rect screen_size_; + scoped_ptr< std::vector<unsigned char> > captured_image_; + + TabContents* tab_; + + // Used to distinguish the report type: Phishing or other. + int problem_type_; + + // Save the description the user types in when we clear the dialog for the + // phishing option. If the user changes the report type back, we reinstate + // their original text so they don't have to type it again. + std::wstring old_report_text_; + + DISALLOW_COPY_AND_ASSIGN(BugReportView); +}; + +#endif // CHROME_BROWSER_VIEWS_BUG_REPORT_VIEW_H_ diff --git a/chrome/browser/views/frame/browser_view.cc b/chrome/browser/views/frame/browser_view.cc index 16dd49a..65548ef 100644 --- a/chrome/browser/views/frame/browser_view.cc +++ b/chrome/browser/views/frame/browser_view.cc @@ -20,12 +20,10 @@ #include "chrome/browser/autocomplete/autocomplete_popup_view.h" #include "chrome/browser/automation/ui_controls.h" #include "chrome/browser/bookmarks/bookmark_utils.h" -#include "chrome/browser/browser.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_theme_provider.h" #include "chrome/browser/debugger/devtools_window.h" -#include "chrome/browser/dom_ui/bug_report_ui.h" #include "chrome/browser/download/download_manager.h" #include "chrome/browser/ntp_background_util.h" #include "chrome/browser/page_info_window.h" @@ -58,7 +56,6 @@ #include "chrome/common/native_window_notification_source.h" #include "chrome/common/notification_service.h" #include "chrome/common/pref_names.h" -#include "chrome/common/url_constants.h" #include "gfx/canvas_skia.h" #include "grit/app_resources.h" #include "grit/chromium_strings.h" @@ -1137,7 +1134,11 @@ DownloadShelf* BrowserView::GetDownloadShelf() { } void BrowserView::ShowReportBugDialog() { - browser::ShowHtmlBugReportView(GetWindow(), browser_.get()); + // Retrieve the URL for the current tab (if any) and tell the BugReportView + TabContents* current_tab = browser_->GetSelectedTabContents(); + if (!current_tab) + return; + browser::ShowBugReportView(GetWindow(), browser_->profile(), current_tab); } void BrowserView::ShowClearBrowsingDataDialog() { diff --git a/chrome/browser/wrench_menu_model.cc b/chrome/browser/wrench_menu_model.cc index ffd1d17..8dd51e4 100644 --- a/chrome/browser/wrench_menu_model.cc +++ b/chrome/browser/wrench_menu_model.cc @@ -147,8 +147,6 @@ void ToolsMenuModel::Build(Browser* browser) { AddItemWithStringId(IDC_CLEAR_BROWSING_DATA, IDS_CLEAR_BROWSING_DATA); AddSeparator(); - AddItemWithStringId(IDC_REPORT_BUG, IDS_REPORT_BUG); - AddSeparator(); encoding_menu_model_.reset(new EncodingMenuModel(browser)); AddSubMenuWithStringId(IDC_ENCODING_MENU, IDS_ENCODING_MENU, |