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
GetSavedScreenshots(std::vector<std::string> * saved_screenshots,base::WaitableEvent * done)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.
GetScreenshotUrls(std::vector<std::string> * 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
GetUserEmail()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
GetIndexOfFeedbackTab(Browser * browser)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
RefreshLastScreenshot(Browser * browser)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
ShowHtmlBugReportView(Browser * browser)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);
GetMimeType(const std::string &) const175 virtual std::string GetMimeType(const std::string&) const {
176 return "text/html";
177 }
178
179 private:
180 base::StringPiece bug_report_html_;
~BugReportUIHTMLSource()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
BugReportUIHTMLSource(base::StringPiece html)236 BugReportUIHTMLSource::BugReportUIHTMLSource(base::StringPiece html)
237 : DataSource(chrome::kChromeUIBugReportHost, MessageLoop::current()) {
238 bug_report_html_ = html;
239 }
240
StartDataRequest(const std::string & path,bool is_incognito,int request_id)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 ////////////////////////////////////////////////////////////////////////////////
SendReport()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 ////////////////////////////////////////////////////////////////////////////////
BugReportHandler(TabContents * tab)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
~BugReportHandler()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
ClobberScreenshotsSource()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
SetupScreenshotsSource()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
Attach(WebUI * web_ui)476 WebUIMessageHandler* BugReportHandler::Attach(WebUI* web_ui) {
477 SetupScreenshotsSource();
478 return WebUIMessageHandler::Attach(web_ui);
479 }
480
Init()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
RegisterMessages()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
HandleGetDialogDefaults(const ListValue *)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
HandleRefreshCurrentScreenshot(const ListValue *)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)
HandleRefreshSavedScreenshots(const ListValue *)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
HandleSendReport(const ListValue * list_value)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
HandleCancel(const ListValue *)698 void BugReportHandler::HandleCancel(const ListValue*) {
699 CloseFeedbackTab();
700 }
701
HandleOpenSystemTab(const ListValue * args)702 void BugReportHandler::HandleOpenSystemTab(const ListValue* args) {
703 #if defined(OS_CHROMEOS)
704 BrowserList::GetLastActive()->OpenSystemTabAndActivate();
705 #endif
706 }
707
CancelFeedbackCollection()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
CloseFeedbackTab()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 ////////////////////////////////////////////////////////////////////////////////
BugReportUI(TabContents * tab)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