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/prefs/pref_service.h" 14#include "base/strings/utf_string_conversions.h" 15#include "base/values.h" 16#include "chrome/browser/browser_process.h" 17#include "chrome/browser/crash_upload_list.h" 18#include "chrome/browser/profiles/profile.h" 19#include "chrome/common/chrome_version_info.h" 20#include "chrome/common/pref_names.h" 21#include "chrome/common/url_constants.h" 22#include "content/public/browser/web_contents.h" 23#include "content/public/browser/web_ui.h" 24#include "content/public/browser/web_ui_data_source.h" 25#include "content/public/browser/web_ui_message_handler.h" 26#include "grit/browser_resources.h" 27#include "grit/chromium_strings.h" 28#include "grit/generated_resources.h" 29#include "grit/theme_resources.h" 30#include "ui/base/l10n/l10n_util.h" 31#include "ui/base/resource/resource_bundle.h" 32 33#if defined(OS_CHROMEOS) 34#include "chrome/browser/chromeos/settings/cros_settings.h" 35#endif 36 37using content::WebContents; 38using content::WebUIMessageHandler; 39 40namespace { 41 42content::WebUIDataSource* CreateCrashesUIHTMLSource() { 43 content::WebUIDataSource* source = 44 content::WebUIDataSource::Create(chrome::kChromeUICrashesHost); 45 source->SetUseJsonJSFormatV2(); 46 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->SetJsonPath("strings.js"); 59 source->AddResourcePath("crashes.js", IDR_CRASHES_JS); 60 source->SetDefaultResource(IDR_CRASHES_HTML); 61 return source; 62} 63 64//////////////////////////////////////////////////////////////////////////////// 65// 66// CrashesDOMHandler 67// 68//////////////////////////////////////////////////////////////////////////////// 69 70// The handler for Javascript messages for the chrome://crashes/ page. 71class CrashesDOMHandler : public WebUIMessageHandler, 72 public CrashUploadList::Delegate { 73 public: 74 explicit CrashesDOMHandler(); 75 virtual ~CrashesDOMHandler(); 76 77 // WebUIMessageHandler implementation. 78 virtual void RegisterMessages() OVERRIDE; 79 80 // CrashUploadList::Delegate implemenation. 81 virtual void OnUploadListAvailable() OVERRIDE; 82 83 private: 84 // Asynchronously fetches the list of crashes. Called from JS. 85 void HandleRequestCrashes(const ListValue* args); 86 87 // Sends the recent crashes list JS. 88 void UpdateUI(); 89 90 scoped_refptr<CrashUploadList> upload_list_; 91 bool list_available_; 92 bool js_request_pending_; 93 94 DISALLOW_COPY_AND_ASSIGN(CrashesDOMHandler); 95}; 96 97CrashesDOMHandler::CrashesDOMHandler() 98 : list_available_(false), js_request_pending_(false) { 99 upload_list_ = CrashUploadList::Create(this); 100} 101 102CrashesDOMHandler::~CrashesDOMHandler() { 103 upload_list_->ClearDelegate(); 104} 105 106void CrashesDOMHandler::RegisterMessages() { 107 upload_list_->LoadUploadListAsynchronously(); 108 109 web_ui()->RegisterMessageCallback("requestCrashList", 110 base::Bind(&CrashesDOMHandler::HandleRequestCrashes, 111 base::Unretained(this))); 112} 113 114void CrashesDOMHandler::HandleRequestCrashes(const ListValue* args) { 115 if (!CrashesUI::CrashReportingUIEnabled() || list_available_) 116 UpdateUI(); 117 else 118 js_request_pending_ = true; 119} 120 121void CrashesDOMHandler::OnUploadListAvailable() { 122 list_available_ = true; 123 if (js_request_pending_) 124 UpdateUI(); 125} 126 127void CrashesDOMHandler::UpdateUI() { 128 bool crash_reporting_enabled = CrashesUI::CrashReportingUIEnabled(); 129 ListValue crash_list; 130 131 if (crash_reporting_enabled) { 132 std::vector<CrashUploadList::UploadInfo> crashes; 133 upload_list_->GetUploads(50, &crashes); 134 135 for (std::vector<CrashUploadList::UploadInfo>::iterator i = crashes.begin(); 136 i != crashes.end(); ++i) { 137 DictionaryValue* crash = new DictionaryValue(); 138 crash->SetString("id", i->id); 139 crash->SetString("time", base::TimeFormatFriendlyDateAndTime(i->time)); 140 crash_list.Append(crash); 141 } 142 } 143 144 base::FundamentalValue enabled(crash_reporting_enabled); 145 146 const chrome::VersionInfo version_info; 147 base::StringValue version(version_info.Version()); 148 149 web_ui()->CallJavascriptFunction("updateCrashList", enabled, crash_list, 150 version); 151} 152 153} // namespace 154 155/////////////////////////////////////////////////////////////////////////////// 156// 157// CrashesUI 158// 159/////////////////////////////////////////////////////////////////////////////// 160 161CrashesUI::CrashesUI(content::WebUI* web_ui) : WebUIController(web_ui) { 162 web_ui->AddMessageHandler(new CrashesDOMHandler()); 163 164 // Set up the chrome://crashes/ source. 165 Profile* profile = Profile::FromWebUI(web_ui); 166 content::WebUIDataSource::Add(profile, CreateCrashesUIHTMLSource()); 167} 168 169// static 170base::RefCountedMemory* CrashesUI::GetFaviconResourceBytes( 171 ui::ScaleFactor scale_factor) { 172 return ResourceBundle::GetSharedInstance(). 173 LoadDataResourceBytesForScale(IDR_SAD_FAVICON, scale_factor); 174} 175 176// static 177bool CrashesUI::CrashReportingUIEnabled() { 178#if defined(GOOGLE_CHROME_BUILD) 179#if defined(OS_CHROMEOS) 180 bool reporting_enabled = false; 181 chromeos::CrosSettings::Get()->GetBoolean(chromeos::kStatsReportingPref, 182 &reporting_enabled); 183 return reporting_enabled; 184#elif defined(OS_ANDROID) 185 // Android has it's own setings for metrics / crash uploading. 186 PrefService* prefs = g_browser_process->local_state(); 187 return prefs->GetBoolean(prefs::kCrashReportingEnabled); 188#else 189 PrefService* prefs = g_browser_process->local_state(); 190 return prefs->GetBoolean(prefs::kMetricsReportingEnabled); 191#endif 192#else 193 return false; 194#endif 195} 196