• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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