Home | History | Annotate | Download | only in webui
      1 // Copyright (c) 2012 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/crashes_ui.h"
      6 
      7 #include <vector>
      8 
      9 #include "base/bind.h"
     10 #include "base/bind_helpers.h"
     11 #include "base/i18n/time_formatting.h"
     12 #include "base/memory/ref_counted_memory.h"
     13 #include "base/strings/utf_string_conversions.h"
     14 #include "base/values.h"
     15 #include "chrome/browser/crash_upload_list.h"
     16 #include "chrome/browser/metrics/chrome_metrics_service_accessor.h"
     17 #include "chrome/browser/profiles/profile.h"
     18 #include "chrome/common/chrome_version_info.h"
     19 #include "chrome/common/url_constants.h"
     20 #include "content/public/browser/web_contents.h"
     21 #include "content/public/browser/web_ui.h"
     22 #include "content/public/browser/web_ui_data_source.h"
     23 #include "content/public/browser/web_ui_message_handler.h"
     24 #include "grit/browser_resources.h"
     25 #include "grit/chromium_strings.h"
     26 #include "grit/generated_resources.h"
     27 #include "grit/theme_resources.h"
     28 #include "ui/base/l10n/l10n_util.h"
     29 #include "ui/base/resource/resource_bundle.h"
     30 
     31 #if defined(OS_CHROMEOS)
     32 #include "chromeos/dbus/dbus_thread_manager.h"
     33 #include "chromeos/dbus/debug_daemon_client.h"
     34 #endif
     35 
     36 using content::WebContents;
     37 using content::WebUIMessageHandler;
     38 
     39 namespace {
     40 
     41 content::WebUIDataSource* CreateCrashesUIHTMLSource() {
     42   content::WebUIDataSource* source =
     43       content::WebUIDataSource::Create(chrome::kChromeUICrashesHost);
     44   source->SetUseJsonJSFormatV2();
     45 
     46   source->AddLocalizedString("shortProductName", IDS_SHORT_PRODUCT_NAME);
     47   source->AddLocalizedString("crashesTitle", IDS_CRASHES_TITLE);
     48   source->AddLocalizedString("crashCountFormat",
     49                              IDS_CRASHES_CRASH_COUNT_BANNER_FORMAT);
     50   source->AddLocalizedString("crashHeaderFormat",
     51                              IDS_CRASHES_CRASH_HEADER_FORMAT);
     52   source->AddLocalizedString("crashTimeFormat", IDS_CRASHES_CRASH_TIME_FORMAT);
     53   source->AddLocalizedString("bugLinkText", IDS_CRASHES_BUG_LINK_LABEL);
     54   source->AddLocalizedString("noCrashesMessage",
     55                              IDS_CRASHES_NO_CRASHES_MESSAGE);
     56   source->AddLocalizedString("disabledHeader", IDS_CRASHES_DISABLED_HEADER);
     57   source->AddLocalizedString("disabledMessage", IDS_CRASHES_DISABLED_MESSAGE);
     58   source->AddLocalizedString("uploadCrashesLinkText",
     59                              IDS_CRASHES_UPLOAD_MESSAGE);
     60   source->SetJsonPath("strings.js");
     61   source->AddResourcePath("crashes.js", IDR_CRASHES_JS);
     62   source->SetDefaultResource(IDR_CRASHES_HTML);
     63   return source;
     64 }
     65 
     66 ////////////////////////////////////////////////////////////////////////////////
     67 //
     68 // CrashesDOMHandler
     69 //
     70 ////////////////////////////////////////////////////////////////////////////////
     71 
     72 // The handler for Javascript messages for the chrome://crashes/ page.
     73 class CrashesDOMHandler : public WebUIMessageHandler,
     74                           public CrashUploadList::Delegate {
     75  public:
     76   explicit CrashesDOMHandler();
     77   virtual ~CrashesDOMHandler();
     78 
     79   // WebUIMessageHandler implementation.
     80   virtual void RegisterMessages() OVERRIDE;
     81 
     82   // CrashUploadList::Delegate implemenation.
     83   virtual void OnUploadListAvailable() OVERRIDE;
     84 
     85  private:
     86   // Asynchronously fetches the list of crashes. Called from JS.
     87   void HandleRequestCrashes(const base::ListValue* args);
     88 
     89 #if defined(OS_CHROMEOS)
     90   // Asynchronously triggers crash uploading. Called from JS.
     91   void HandleRequestUploads(const base::ListValue* args);
     92 #endif
     93 
     94   // Sends the recent crashes list JS.
     95   void UpdateUI();
     96 
     97   scoped_refptr<CrashUploadList> upload_list_;
     98   bool list_available_;
     99   bool first_load_;
    100 
    101   DISALLOW_COPY_AND_ASSIGN(CrashesDOMHandler);
    102 };
    103 
    104 CrashesDOMHandler::CrashesDOMHandler()
    105     : list_available_(false), first_load_(true) {
    106   upload_list_ = CrashUploadList::Create(this);
    107 }
    108 
    109 CrashesDOMHandler::~CrashesDOMHandler() {
    110   upload_list_->ClearDelegate();
    111 }
    112 
    113 void CrashesDOMHandler::RegisterMessages() {
    114   upload_list_->LoadUploadListAsynchronously();
    115   web_ui()->RegisterMessageCallback("requestCrashList",
    116       base::Bind(&CrashesDOMHandler::HandleRequestCrashes,
    117                  base::Unretained(this)));
    118 
    119 #if defined(OS_CHROMEOS)
    120   web_ui()->RegisterMessageCallback("requestCrashUpload",
    121       base::Bind(&CrashesDOMHandler::HandleRequestUploads,
    122                  base::Unretained(this)));
    123 #endif
    124 }
    125 
    126 void CrashesDOMHandler::HandleRequestCrashes(const base::ListValue* args) {
    127   if (first_load_) {
    128     first_load_ = false;
    129     if (list_available_)
    130       UpdateUI();
    131   } else {
    132     list_available_ = false;
    133     upload_list_->LoadUploadListAsynchronously();
    134   }
    135 }
    136 
    137 #if defined(OS_CHROMEOS)
    138 void CrashesDOMHandler::HandleRequestUploads(const base::ListValue* args) {
    139   chromeos::DebugDaemonClient* debugd_client =
    140       chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
    141   DCHECK(debugd_client);
    142 
    143   debugd_client->UploadCrashes();
    144 }
    145 #endif
    146 
    147 void CrashesDOMHandler::OnUploadListAvailable() {
    148   list_available_ = true;
    149   if (!first_load_)
    150     UpdateUI();
    151 }
    152 
    153 void CrashesDOMHandler::UpdateUI() {
    154   bool crash_reporting_enabled =
    155       ChromeMetricsServiceAccessor::IsCrashReportingEnabled();
    156   base::ListValue crash_list;
    157   bool system_crash_reporter = false;
    158 
    159 #if defined(OS_CHROMEOS)
    160   // Chrome OS has a system crash reporter.
    161   system_crash_reporter = true;
    162 #endif
    163 
    164   if (crash_reporting_enabled) {
    165     std::vector<CrashUploadList::UploadInfo> crashes;
    166     upload_list_->GetUploads(50, &crashes);
    167 
    168     for (std::vector<CrashUploadList::UploadInfo>::iterator i = crashes.begin();
    169          i != crashes.end(); ++i) {
    170       base::DictionaryValue* crash = new base::DictionaryValue();
    171       crash->SetString("id", i->id);
    172       crash->SetString("time", base::TimeFormatFriendlyDateAndTime(i->time));
    173       crash->SetString("local_id", i->local_id);
    174       crash_list.Append(crash);
    175     }
    176   }
    177 
    178   base::FundamentalValue enabled(crash_reporting_enabled);
    179   base::FundamentalValue dynamic_backend(system_crash_reporter);
    180 
    181   const chrome::VersionInfo version_info;
    182   base::StringValue version(version_info.Version());
    183 
    184   web_ui()->CallJavascriptFunction("updateCrashList", enabled, dynamic_backend,
    185                                    crash_list, version);
    186 }
    187 
    188 }  // namespace
    189 
    190 ///////////////////////////////////////////////////////////////////////////////
    191 //
    192 // CrashesUI
    193 //
    194 ///////////////////////////////////////////////////////////////////////////////
    195 
    196 CrashesUI::CrashesUI(content::WebUI* web_ui) : WebUIController(web_ui) {
    197   web_ui->AddMessageHandler(new CrashesDOMHandler());
    198 
    199   // Set up the chrome://crashes/ source.
    200   Profile* profile = Profile::FromWebUI(web_ui);
    201   content::WebUIDataSource::Add(profile, CreateCrashesUIHTMLSource());
    202 }
    203 
    204 // static
    205 base::RefCountedMemory* CrashesUI::GetFaviconResourceBytes(
    206       ui::ScaleFactor scale_factor) {
    207   return ResourceBundle::GetSharedInstance().
    208       LoadDataResourceBytesForScale(IDR_SAD_FAVICON, scale_factor);
    209 }
    210