1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/ui/webui/bug_report_ui.h" 6 7 #include <algorithm> 8 #include <string> 9 #include <vector> 10 11 #include "base/callback.h" 12 #include "base/logging.h" 13 #include "base/memory/singleton.h" 14 #include "base/memory/weak_ptr.h" 15 #include "base/message_loop.h" 16 #include "base/string_number_conversions.h" 17 #include "base/string_piece.h" 18 #include "base/utf_string_conversions.h" 19 #include "base/values.h" 20 #include "chrome/browser/bug_report_data.h" 21 #include "chrome/browser/bug_report_util.h" 22 #include "chrome/browser/profiles/profile.h" 23 #include "chrome/browser/ui/browser.h" 24 #include "chrome/browser/ui/browser_list.h" 25 #include "chrome/browser/ui/browser_window.h" 26 #include "chrome/browser/ui/webui/screenshot_source.h" 27 #include "chrome/browser/ui/window_snapshot/window_snapshot.h" 28 #include "chrome/common/chrome_paths.h" 29 #include "chrome/common/jstemplate_builder.h" 30 #include "chrome/common/url_constants.h" 31 #include "content/browser/browser_thread.h" 32 #include "content/browser/tab_contents/tab_contents.h" 33 #include "grit/browser_resources.h" 34 #include "grit/chromium_strings.h" 35 #include "grit/generated_resources.h" 36 #include "grit/locale_settings.h" 37 #include "ui/base/l10n/l10n_util.h" 38 #include "ui/base/resource/resource_bundle.h" 39 #include "ui/gfx/rect.h" 40 41 #if defined(OS_CHROMEOS) 42 #include "base/file_util.h" 43 #include "base/path_service.h" 44 #include "base/synchronization/waitable_event.h" 45 #include "chrome/browser/chromeos/cros/cros_library.h" 46 #include "chrome/browser/chromeos/cros/syslogs_library.h" 47 #include "chrome/browser/chromeos/login/user_manager.h" 48 #endif 49 50 namespace { 51 52 const char kScreenshotBaseUrl[] = "chrome://screenshots/"; 53 const char kCurrentScreenshotUrl[] = "chrome://screenshots/current"; 54 #if defined(OS_CHROMEOS) 55 const char kSavedScreenshotsUrl[] = "chrome://screenshots/saved/"; 56 57 const char kScreenshotPattern[] = "*.png"; 58 const char kScreenshotsRelativePath[] = "/Screenshots"; 59 60 const size_t kMaxSavedScreenshots = 2; 61 #endif 62 63 #if defined(OS_CHROMEOS) 64 65 void GetSavedScreenshots(std::vector<std::string>* saved_screenshots, 66 base::WaitableEvent* done) { 67 saved_screenshots->clear(); 68 69 FilePath fileshelf_path; 70 if (!PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, 71 &fileshelf_path)) { 72 done->Signal(); 73 return; 74 } 75 76 // TODO(rkc): Change this to use FilePath.Append() once the cros 77 // issue with it is fixed 78 FilePath screenshots_path(fileshelf_path.value() + 79 std::string(kScreenshotsRelativePath)); 80 file_util::FileEnumerator screenshots(screenshots_path, false, 81 file_util::FileEnumerator::FILES, 82 std::string(kScreenshotPattern)); 83 FilePath screenshot = screenshots.Next(); 84 while (!screenshot.empty()) { 85 saved_screenshots->push_back(std::string(kSavedScreenshotsUrl) + 86 screenshot.BaseName().value()); 87 if (saved_screenshots->size() >= kMaxSavedScreenshots) 88 break; 89 90 screenshot = screenshots.Next(); 91 } 92 done->Signal(); 93 } 94 95 // This fuction posts a task to the file thread to create/list all the current 96 // and saved screenshots. 97 void GetScreenshotUrls(std::vector<std::string>* saved_screenshots) { 98 base::WaitableEvent done(true, false); 99 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, 100 NewRunnableFunction(&GetSavedScreenshots, 101 saved_screenshots, &done)); 102 done.Wait(); 103 } 104 105 std::string GetUserEmail() { 106 chromeos::UserManager* manager = chromeos::UserManager::Get(); 107 if (!manager) 108 return std::string(); 109 else 110 return manager->logged_in_user().email(); 111 } 112 #endif 113 114 // Returns the index of the feedback tab if already open, -1 otherwise 115 int GetIndexOfFeedbackTab(Browser* browser) { 116 GURL bug_report_url(chrome::kChromeUIBugReportURL); 117 for (int i = 0; i < browser->tab_count(); ++i) { 118 TabContents* tab = browser->GetTabContentsAt(i); 119 if (tab && tab->GetURL().GetWithEmptyPath() == bug_report_url) 120 return i; 121 } 122 123 return -1; 124 } 125 126 } // namespace 127 128 129 namespace browser { 130 131 // TODO(rkc): Eventually find a better way to do this 132 std::vector<unsigned char>* last_screenshot_png = 0; 133 gfx::Rect screen_size; 134 135 void RefreshLastScreenshot(Browser* browser) { 136 if (last_screenshot_png) 137 last_screenshot_png->clear(); 138 else 139 last_screenshot_png = new std::vector<unsigned char>; 140 141 gfx::NativeWindow native_window = browser->window()->GetNativeHandle(); 142 screen_size = browser::GrabWindowSnapshot(native_window, last_screenshot_png); 143 } 144 145 void ShowHtmlBugReportView(Browser* browser) { 146 // First check if we're already open (we cannot depend on ShowSingletonTab 147 // for this functionality since we need to make *sure* we never get 148 // instantiated again while we are open - with singleton tabs, that can 149 // happen) 150 int feedback_tab_index = GetIndexOfFeedbackTab(browser); 151 if (feedback_tab_index >=0) { 152 // Do not refresh screenshot, do not create a new tab 153 browser->ActivateTabAt(feedback_tab_index, true); 154 return; 155 } 156 157 RefreshLastScreenshot(browser); 158 std::string bug_report_url = std::string(chrome::kChromeUIBugReportURL) + 159 "#" + base::IntToString(browser->active_index()); 160 browser->ShowSingletonTab(GURL(bug_report_url)); 161 } 162 163 } // namespace browser 164 165 166 class BugReportUIHTMLSource : public ChromeURLDataManager::DataSource { 167 public: 168 explicit BugReportUIHTMLSource(base::StringPiece html); 169 170 // Called when the network layer has requested a resource underneath 171 // the path we registered. 172 virtual void StartDataRequest(const std::string& path, 173 bool is_incognito, 174 int request_id); 175 virtual std::string GetMimeType(const std::string&) const { 176 return "text/html"; 177 } 178 179 private: 180 base::StringPiece bug_report_html_; 181 ~BugReportUIHTMLSource() {} 182 183 DISALLOW_COPY_AND_ASSIGN(BugReportUIHTMLSource); 184 }; 185 186 // The handler for Javascript messages related to the "bug report" dialog 187 class BugReportHandler : public WebUIMessageHandler, 188 public base::SupportsWeakPtr<BugReportHandler> { 189 public: 190 explicit BugReportHandler(TabContents* tab); 191 virtual ~BugReportHandler(); 192 193 // Init work after Attach. 194 base::StringPiece Init(); 195 196 // WebUIMessageHandler implementation. 197 virtual WebUIMessageHandler* Attach(WebUI* web_ui); 198 virtual void RegisterMessages(); 199 200 private: 201 void HandleGetDialogDefaults(const ListValue* args); 202 void HandleRefreshCurrentScreenshot(const ListValue* args); 203 #if defined(OS_CHROMEOS) 204 void HandleRefreshSavedScreenshots(const ListValue* args); 205 #endif 206 void HandleSendReport(const ListValue* args); 207 void HandleCancel(const ListValue* args); 208 void HandleOpenSystemTab(const ListValue* args); 209 210 void SetupScreenshotsSource(); 211 void ClobberScreenshotsSource(); 212 213 void CancelFeedbackCollection(); 214 void CloseFeedbackTab(); 215 216 TabContents* tab_; 217 ScreenshotSource* screenshot_source_; 218 219 BugReportData* bug_report_; 220 std::string target_tab_url_; 221 #if defined(OS_CHROMEOS) 222 // Variables to track SyslogsLibrary::RequestSyslogs callback. 223 chromeos::SyslogsLibrary::Handle syslogs_handle_; 224 CancelableRequestConsumer syslogs_consumer_; 225 #endif 226 227 DISALLOW_COPY_AND_ASSIGN(BugReportHandler); 228 }; 229 230 //////////////////////////////////////////////////////////////////////////////// 231 // 232 // BugReportHTMLSource 233 // 234 //////////////////////////////////////////////////////////////////////////////// 235 236 BugReportUIHTMLSource::BugReportUIHTMLSource(base::StringPiece html) 237 : DataSource(chrome::kChromeUIBugReportHost, MessageLoop::current()) { 238 bug_report_html_ = html; 239 } 240 241 void BugReportUIHTMLSource::StartDataRequest(const std::string& path, 242 bool is_incognito, 243 int request_id) { 244 DictionaryValue localized_strings; 245 localized_strings.SetString(std::string("title"), 246 l10n_util::GetStringUTF8(IDS_BUGREPORT_TITLE)); 247 localized_strings.SetString(std::string("page-title"), 248 l10n_util::GetStringUTF8(IDS_BUGREPORT_REPORT_PAGE_TITLE)); 249 localized_strings.SetString(std::string("issue-with"), 250 l10n_util::GetStringUTF8(IDS_BUGREPORT_ISSUE_WITH)); 251 localized_strings.SetString(std::string("page-url"), 252 l10n_util::GetStringUTF8(IDS_BUGREPORT_REPORT_URL_LABEL)); 253 localized_strings.SetString(std::string("description"), 254 l10n_util::GetStringUTF8(IDS_BUGREPORT_DESCRIPTION_LABEL)); 255 localized_strings.SetString(std::string("current-screenshot"), 256 l10n_util::GetStringUTF8(IDS_BUGREPORT_SCREENSHOT_LABEL)); 257 localized_strings.SetString(std::string("saved-screenshot"), 258 l10n_util::GetStringUTF8(IDS_BUGREPORT_SAVED_SCREENSHOT_LABEL)); 259 #if defined(OS_CHROMEOS) 260 localized_strings.SetString(std::string("user-email"), 261 l10n_util::GetStringUTF8(IDS_BUGREPORT_USER_EMAIL_LABEL)); 262 localized_strings.SetString(std::string("sysinfo"), 263 l10n_util::GetStringUTF8( 264 IDS_BUGREPORT_INCLUDE_SYSTEM_INFORMATION_CHKBOX)); 265 266 localized_strings.SetString(std::string("currentscreenshots"), 267 l10n_util::GetStringUTF8(IDS_BUGREPORT_CURRENT_SCREENSHOTS)); 268 localized_strings.SetString(std::string("savedscreenshots"), 269 l10n_util::GetStringUTF8(IDS_BUGREPORT_SAVED_SCREENSHOTS)); 270 271 localized_strings.SetString(std::string("choose-different-screenshot"), 272 l10n_util::GetStringUTF8( 273 IDS_BUGREPORT_CHOOSE_DIFFERENT_SCREENSHOT)); 274 localized_strings.SetString(std::string("choose-original-screenshot"), 275 l10n_util::GetStringUTF8( 276 IDS_BUGREPORT_CHOOSE_ORIGINAL_SCREENSHOT)); 277 #else 278 localized_strings.SetString(std::string("currentscreenshots"), 279 l10n_util::GetStringUTF8(IDS_BUGREPORT_INCLUDE_NEW_SCREEN_IMAGE)); 280 #endif 281 localized_strings.SetString(std::string("noscreenshot"), 282 l10n_util::GetStringUTF8(IDS_BUGREPORT_INCLUDE_NO_SCREENSHOT)); 283 284 localized_strings.SetString(std::string("send-report"), 285 l10n_util::GetStringUTF8(IDS_BUGREPORT_SEND_REPORT)); 286 localized_strings.SetString(std::string("cancel"), 287 l10n_util::GetStringUTF8(IDS_CANCEL)); 288 289 // Option strings for the "issue with" drop-down. 290 localized_strings.SetString(std::string("issue-choose"), 291 l10n_util::GetStringUTF8(IDS_BUGREPORT_CHOOSE_ISSUE)); 292 293 localized_strings.SetString(std::string("no-issue-selected"), 294 l10n_util::GetStringUTF8(IDS_BUGREPORT_NO_ISSUE_SELECTED)); 295 296 localized_strings.SetString(std::string("no-description"), 297 l10n_util::GetStringUTF8(IDS_BUGREPORT_NO_DESCRIPTION)); 298 299 localized_strings.SetString(std::string("no-saved-screenshots"), 300 l10n_util::GetStringUTF8(IDS_BUGREPORT_NO_SAVED_SCREENSHOTS_HELP)); 301 302 localized_strings.SetString(std::string("privacy-note"), 303 l10n_util::GetStringUTF8(IDS_BUGREPORT_PRIVACY_NOTE)); 304 305 // TODO(rkc): Find some way to ensure this order of dropdowns is in sync 306 // with the order in the userfeedback ChromeData proto buffer 307 #if defined(OS_CHROMEOS) 308 // Dropdown for ChromeOS: 309 // 310 // Connectivity 311 // Sync 312 // Crash 313 // Page Formatting 314 // Extensions or Apps 315 // Standby or Resume 316 // Phishing Page 317 // General Feedback/Other 318 319 localized_strings.SetString(std::string("issue-connectivity"), 320 l10n_util::GetStringUTF8(IDS_BUGREPORT_CONNECTIVITY)); 321 localized_strings.SetString(std::string("issue-sync"), 322 l10n_util::GetStringUTF8(IDS_BUGREPORT_SYNC)); 323 localized_strings.SetString(std::string("issue-crashes"), 324 l10n_util::GetStringUTF8(IDS_BUGREPORT_CRASHES)); 325 localized_strings.SetString(std::string("issue-page-formatting"), 326 l10n_util::GetStringUTF8(IDS_BUGREPORT_PAGE_FORMATTING)); 327 localized_strings.SetString(std::string("issue-extensions"), 328 l10n_util::GetStringUTF8(IDS_BUGREPORT_EXTENSIONS)); 329 localized_strings.SetString(std::string("issue-standby"), 330 l10n_util::GetStringUTF8(IDS_BUGREPORT_STANDBY_RESUME)); 331 localized_strings.SetString(std::string("issue-phishing"), 332 l10n_util::GetStringUTF8(IDS_BUGREPORT_PHISHING_PAGE)); 333 localized_strings.SetString(std::string("issue-other"), 334 l10n_util::GetStringUTF8(IDS_BUGREPORT_GENERAL)); 335 #else 336 // Dropdown for Chrome: 337 // 338 // Page formatting or layout 339 // Pages not loading 340 // Plug-ins (e.g. Adobe Flash Player, Quicktime, etc) 341 // Tabs or windows 342 // Synced preferences 343 // Crashes 344 // Extensions or apps 345 // Phishing 346 // Other 347 348 localized_strings.SetString(std::string("issue-page-formatting"), 349 l10n_util::GetStringUTF8(IDS_BUGREPORT_PAGE_FORMATTING)); 350 localized_strings.SetString(std::string("issue-page-load"), 351 l10n_util::GetStringUTF8(IDS_BUGREPORT_PAGE_LOAD)); 352 localized_strings.SetString(std::string("issue-plugins"), 353 l10n_util::GetStringUTF8(IDS_BUGREPORT_PLUGINS)); 354 localized_strings.SetString(std::string("issue-tabs"), 355 l10n_util::GetStringUTF8(IDS_BUGREPORT_TABS)); 356 localized_strings.SetString(std::string("issue-sync"), 357 l10n_util::GetStringUTF8(IDS_BUGREPORT_SYNC)); 358 localized_strings.SetString(std::string("issue-crashes"), 359 l10n_util::GetStringUTF8(IDS_BUGREPORT_CRASHES)); 360 localized_strings.SetString(std::string("issue-extensions"), 361 l10n_util::GetStringUTF8(IDS_BUGREPORT_EXTENSIONS)); 362 localized_strings.SetString(std::string("issue-phishing"), 363 l10n_util::GetStringUTF8(IDS_BUGREPORT_PHISHING_PAGE)); 364 localized_strings.SetString(std::string("issue-other"), 365 l10n_util::GetStringUTF8(IDS_BUGREPORT_OTHER)); 366 #endif 367 368 SetFontAndTextDirection(&localized_strings); 369 370 const std::string full_html = jstemplate_builder::GetI18nTemplateHtml( 371 bug_report_html_, &localized_strings); 372 373 scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes); 374 html_bytes->data.resize(full_html.size()); 375 std::copy(full_html.begin(), full_html.end(), html_bytes->data.begin()); 376 377 SendResponse(request_id, html_bytes); 378 } 379 380 381 //////////////////////////////////////////////////////////////////////////////// 382 // 383 // BugReportData 384 // 385 //////////////////////////////////////////////////////////////////////////////// 386 void BugReportData::SendReport() { 387 #if defined(OS_CHROMEOS) 388 // In case we already got the syslogs and sent the report, leave 389 if (sent_report_) return; 390 // Set send_report_ so that no one else processes SendReport 391 sent_report_ = true; 392 #endif 393 394 int image_data_size = image_.size(); 395 char* image_data = image_data_size ? 396 reinterpret_cast<char*>(&(image_.front())) : NULL; 397 BugReportUtil::SendReport(profile_ 398 , problem_type_ 399 , page_url_ 400 , description_ 401 , image_data 402 , image_data_size 403 , browser::screen_size.width() 404 , browser::screen_size.height() 405 #if defined(OS_CHROMEOS) 406 , user_email_ 407 , zip_content_ ? zip_content_->c_str() : NULL 408 , zip_content_ ? zip_content_->length() : 0 409 , send_sys_info_ ? sys_info_ : NULL 410 #endif 411 ); 412 413 #if defined(OS_CHROMEOS) 414 if (sys_info_) { 415 delete sys_info_; 416 sys_info_ = NULL; 417 } 418 if (zip_content_) { 419 delete zip_content_; 420 zip_content_ = NULL; 421 } 422 #endif 423 424 // Once the report has been sent, this object has no purpose in life, delete 425 // ourselves. 426 delete this; 427 } 428 429 430 //////////////////////////////////////////////////////////////////////////////// 431 // 432 // BugReportHandler 433 // 434 //////////////////////////////////////////////////////////////////////////////// 435 BugReportHandler::BugReportHandler(TabContents* tab) 436 : tab_(tab), 437 screenshot_source_(NULL), 438 bug_report_(NULL) 439 #if defined(OS_CHROMEOS) 440 , syslogs_handle_(0) 441 #endif 442 { 443 } 444 445 BugReportHandler::~BugReportHandler() { 446 // Just in case we didn't send off bug_report_ to SendReport 447 if (bug_report_) { 448 // If we're deleting the report object, cancel feedback collection first 449 CancelFeedbackCollection(); 450 delete bug_report_; 451 } 452 } 453 454 void BugReportHandler::ClobberScreenshotsSource() { 455 // Re-create our screenshots data source (this clobbers the last source) 456 // setting the screenshot to NULL, effectively disabling the source 457 // TODO(rkc): Once there is a method to 'remove' a source, change this code 458 tab_->profile()->GetChromeURLDataManager()->AddDataSource( 459 new ScreenshotSource(NULL)); 460 461 // clobber last screenshot 462 if (browser::last_screenshot_png) 463 browser::last_screenshot_png->clear(); 464 } 465 466 void BugReportHandler::SetupScreenshotsSource() { 467 // If we don't already have a screenshot source object created, create one. 468 if (!screenshot_source_) 469 screenshot_source_ = new ScreenshotSource( 470 browser::last_screenshot_png); 471 472 // Add the source to the data manager. 473 tab_->profile()->GetChromeURLDataManager()->AddDataSource(screenshot_source_); 474 } 475 476 WebUIMessageHandler* BugReportHandler::Attach(WebUI* web_ui) { 477 SetupScreenshotsSource(); 478 return WebUIMessageHandler::Attach(web_ui); 479 } 480 481 base::StringPiece BugReportHandler::Init() { 482 std::string page_url; 483 if (tab_->controller().GetActiveEntry()) { 484 page_url = tab_->controller().GetActiveEntry()->url().spec(); 485 } 486 487 std::string params = page_url.substr(strlen(chrome::kChromeUIBugReportURL)); 488 // Erase the # - the first character. 489 if (params.length()) 490 params.erase(params.begin(), params.begin() + 1); 491 492 int index = 0; 493 if (!base::StringToInt(params, &index)) { 494 return base::StringPiece( 495 ResourceBundle::GetSharedInstance().GetRawDataResource( 496 IDR_BUGREPORT_HTML_INVALID)); 497 } 498 499 Browser* browser = BrowserList::GetLastActive(); 500 // Sanity checks. 501 if (((index == 0) && (params != "0")) || !browser || 502 index >= browser->tab_count()) { 503 return base::StringPiece( 504 ResourceBundle::GetSharedInstance().GetRawDataResource( 505 IDR_BUGREPORT_HTML_INVALID)); 506 } 507 508 TabContents* target_tab = browser->GetTabContentsAt(index); 509 if (target_tab) { 510 target_tab_url_ = target_tab->GetURL().spec(); 511 } 512 513 // Setup the screenshot source after we've verified input is legit. 514 SetupScreenshotsSource(); 515 516 return base::StringPiece( 517 ResourceBundle::GetSharedInstance().GetRawDataResource( 518 IDR_BUGREPORT_HTML)); 519 } 520 521 void BugReportHandler::RegisterMessages() { 522 web_ui_->RegisterMessageCallback("getDialogDefaults", 523 NewCallback(this, &BugReportHandler::HandleGetDialogDefaults)); 524 web_ui_->RegisterMessageCallback("refreshCurrentScreenshot", 525 NewCallback(this, &BugReportHandler::HandleRefreshCurrentScreenshot)); 526 #if defined(OS_CHROMEOS) 527 web_ui_->RegisterMessageCallback("refreshSavedScreenshots", 528 NewCallback(this, &BugReportHandler::HandleRefreshSavedScreenshots)); 529 #endif 530 web_ui_->RegisterMessageCallback("sendReport", 531 NewCallback(this, &BugReportHandler::HandleSendReport)); 532 web_ui_->RegisterMessageCallback("cancel", 533 NewCallback(this, &BugReportHandler::HandleCancel)); 534 web_ui_->RegisterMessageCallback("openSystemTab", 535 NewCallback(this, &BugReportHandler::HandleOpenSystemTab)); 536 } 537 538 void BugReportHandler::HandleGetDialogDefaults(const ListValue*) { 539 bug_report_ = new BugReportData(); 540 541 // send back values which the dialog js needs initially 542 ListValue dialog_defaults; 543 544 // 0: current url 545 if (target_tab_url_.length()) 546 dialog_defaults.Append(new StringValue(target_tab_url_)); 547 else 548 dialog_defaults.Append(new StringValue("")); 549 550 #if defined(OS_CHROMEOS) 551 // 1: about:system 552 dialog_defaults.Append(new StringValue(chrome::kChromeUISystemInfoURL)); 553 // Trigger the request for system information here. 554 chromeos::SyslogsLibrary* syslogs_lib = 555 chromeos::CrosLibrary::Get()->GetSyslogsLibrary(); 556 if (syslogs_lib) { 557 syslogs_handle_ = syslogs_lib->RequestSyslogs( 558 true, true, &syslogs_consumer_, 559 NewCallback(bug_report_, &BugReportData::SyslogsComplete)); 560 } 561 // 2: user e-mail 562 dialog_defaults.Append(new StringValue(GetUserEmail())); 563 #endif 564 565 web_ui_->CallJavascriptFunction("setupDialogDefaults", dialog_defaults); 566 } 567 568 void BugReportHandler::HandleRefreshCurrentScreenshot(const ListValue*) { 569 std::string current_screenshot(kCurrentScreenshotUrl); 570 StringValue screenshot(current_screenshot); 571 web_ui_->CallJavascriptFunction("setupCurrentScreenshot", screenshot); 572 } 573 574 575 #if defined(OS_CHROMEOS) 576 void BugReportHandler::HandleRefreshSavedScreenshots(const ListValue*) { 577 std::vector<std::string> saved_screenshots; 578 GetScreenshotUrls(&saved_screenshots); 579 580 ListValue screenshots_list; 581 for (size_t i = 0; i < saved_screenshots.size(); ++i) 582 screenshots_list.Append(new StringValue(saved_screenshots[i])); 583 web_ui_->CallJavascriptFunction("setupSavedScreenshots", screenshots_list); 584 } 585 #endif 586 587 588 void BugReportHandler::HandleSendReport(const ListValue* list_value) { 589 if (!bug_report_) { 590 LOG(ERROR) << "Bug report hasn't been intialized yet."; 591 return; 592 } 593 594 ListValue::const_iterator i = list_value->begin(); 595 if (i == list_value->end()) { 596 LOG(ERROR) << "Incorrect data passed to sendReport."; 597 return; 598 } 599 600 // #0 - Problem type. 601 int problem_type; 602 std::string problem_type_str; 603 (*i)->GetAsString(&problem_type_str); 604 if (!base::StringToInt(problem_type_str, &problem_type)) { 605 LOG(ERROR) << "Incorrect data passed to sendReport."; 606 return; 607 } 608 if (++i == list_value->end()) { 609 LOG(ERROR) << "Incorrect data passed to sendReport."; 610 return; 611 } 612 613 // #1 - Page url. 614 std::string page_url; 615 (*i)->GetAsString(&page_url); 616 if (++i == list_value->end()) { 617 LOG(ERROR) << "Incorrect data passed to sendReport."; 618 return; 619 } 620 621 // #2 - Description. 622 std::string description; 623 (*i)->GetAsString(&description); 624 if (++i == list_value->end()) { 625 LOG(ERROR) << "Incorrect data passed to sendReport."; 626 return; 627 } 628 629 // #3 - Screenshot to send. 630 std::string screenshot_path; 631 (*i)->GetAsString(&screenshot_path); 632 screenshot_path.erase(0, strlen(kScreenshotBaseUrl)); 633 634 // Get the image to send in the report. 635 std::vector<unsigned char> image; 636 if (!screenshot_path.empty()) 637 image = screenshot_source_->GetScreenshot(screenshot_path); 638 639 #if defined(OS_CHROMEOS) 640 if (++i == list_value->end()) { 641 LOG(ERROR) << "Incorrect data passed to sendReport."; 642 return; 643 } 644 645 // #4 - User e-mail 646 std::string user_email; 647 (*i)->GetAsString(&user_email); 648 if (++i == list_value->end()) { 649 LOG(ERROR) << "Incorrect data passed to sendReport."; 650 return; 651 } 652 653 // #5 - System info checkbox. 654 std::string sys_info_checkbox; 655 (*i)->GetAsString(&sys_info_checkbox); 656 bool send_sys_info = (sys_info_checkbox == "true"); 657 658 // If we aren't sending the sys_info, cancel the gathering of the syslogs. 659 if (!send_sys_info) 660 CancelFeedbackCollection(); 661 #endif 662 663 // Update the data in bug_report_ so it can be sent 664 bug_report_->UpdateData(web_ui_->GetProfile() 665 , target_tab_url_ 666 , problem_type 667 , page_url 668 , description 669 , image 670 #if defined(OS_CHROMEOS) 671 , user_email 672 , send_sys_info 673 , false // sent_report 674 #endif 675 ); 676 677 #if defined(OS_CHROMEOS) 678 // If we don't require sys_info, or we have it, or we never requested it 679 // (because libcros failed to load), then send the report now. 680 // Otherwise, the report will get sent when we receive sys_info. 681 if (!send_sys_info || bug_report_->sys_info() != NULL || 682 syslogs_handle_ == 0) { 683 bug_report_->SendReport(); 684 } 685 #else 686 bug_report_->SendReport(); 687 #endif 688 // Lose the pointer to the BugReportData object; the object will delete itself 689 // from SendReport, whether we called it, or will be called by the log 690 // completion routine. 691 bug_report_ = NULL; 692 693 // Whether we sent the report, or if it will be sent by the Syslogs complete 694 // function, close our feedback tab anyway, we have no more use for it. 695 CloseFeedbackTab(); 696 } 697 698 void BugReportHandler::HandleCancel(const ListValue*) { 699 CloseFeedbackTab(); 700 } 701 702 void BugReportHandler::HandleOpenSystemTab(const ListValue* args) { 703 #if defined(OS_CHROMEOS) 704 BrowserList::GetLastActive()->OpenSystemTabAndActivate(); 705 #endif 706 } 707 708 void BugReportHandler::CancelFeedbackCollection() { 709 #if defined(OS_CHROMEOS) 710 if (syslogs_handle_ != 0) { 711 chromeos::SyslogsLibrary* syslogs_lib = 712 chromeos::CrosLibrary::Get()->GetSyslogsLibrary(); 713 if (syslogs_lib) 714 syslogs_lib->CancelRequest(syslogs_handle_); 715 } 716 #endif 717 } 718 719 void BugReportHandler::CloseFeedbackTab() { 720 ClobberScreenshotsSource(); 721 722 Browser* browser = BrowserList::GetLastActive(); 723 if (browser) { 724 browser->CloseTabContents(tab_); 725 } else { 726 LOG(FATAL) << "Failed to get last active browser."; 727 } 728 } 729 730 //////////////////////////////////////////////////////////////////////////////// 731 // 732 // BugReportUI 733 // 734 //////////////////////////////////////////////////////////////////////////////// 735 BugReportUI::BugReportUI(TabContents* tab) : HtmlDialogUI(tab) { 736 BugReportHandler* handler = new BugReportHandler(tab); 737 AddMessageHandler((handler)->Attach(this)); 738 739 // The handler's init will specify which html 740 // resource we'll display to the user 741 BugReportUIHTMLSource* html_source = 742 new BugReportUIHTMLSource(handler->Init()); 743 // Set up the chrome://bugreport/ source. 744 tab->profile()->GetChromeURLDataManager()->AddDataSource(html_source); 745 } 746