1 // Copyright 2014 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/chromeos/power_ui.h" 6 7 #include "base/bind.h" 8 #include "base/bind_helpers.h" 9 #include "base/compiler_specific.h" 10 #include "base/strings/string_number_conversions.h" 11 #include "base/time/time.h" 12 #include "base/values.h" 13 #include "chrome/browser/chromeos/power/power_data_collector.h" 14 #include "chrome/browser/profiles/profile.h" 15 #include "chrome/common/url_constants.h" 16 #include "chrome/grit/generated_resources.h" 17 #include "content/public/browser/web_ui.h" 18 #include "content/public/browser/web_ui_data_source.h" 19 #include "content/public/browser/web_ui_message_handler.h" 20 #include "grit/browser_resources.h" 21 22 namespace chromeos { 23 24 namespace { 25 26 const char kStringsJsFile[] = "strings.js"; 27 28 const char kRequestBatteryChargeDataCallback[] = "requestBatteryChargeData"; 29 const char kOnRequestBatteryChargeDataFunction[] = 30 "powerUI.showBatteryChargeData"; 31 32 const char kRequestCpuIdleDataCallback[] = "requestCpuIdleData"; 33 const char kOnRequestCpuIdleDataFunction[] = 34 "powerUI.showCpuIdleData"; 35 36 const char kRequestCpuFreqDataCallback[] = "requestCpuFreqData"; 37 const char kOnRequestCpuFreqDataFunction[] = 38 "powerUI.showCpuFreqData"; 39 40 class PowerMessageHandler : public content::WebUIMessageHandler { 41 public: 42 PowerMessageHandler(); 43 virtual ~PowerMessageHandler(); 44 45 // WebUIMessageHandler implementation. 46 virtual void RegisterMessages() OVERRIDE; 47 48 private: 49 void OnGetBatteryChargeData(const base::ListValue* value); 50 void OnGetCpuIdleData(const base::ListValue* value); 51 void OnGetCpuFreqData(const base::ListValue* value); 52 void GetJsStateOccupancyData( 53 const std::vector<CpuDataCollector::StateOccupancySampleDeque>& data, 54 const std::vector<std::string>& state_names, 55 base::ListValue* js_data); 56 void GetJsSystemResumedData(base::ListValue* value); 57 }; 58 59 PowerMessageHandler::PowerMessageHandler() { 60 } 61 62 PowerMessageHandler::~PowerMessageHandler() { 63 } 64 65 void PowerMessageHandler::RegisterMessages() { 66 web_ui()->RegisterMessageCallback( 67 kRequestBatteryChargeDataCallback, 68 base::Bind(&PowerMessageHandler::OnGetBatteryChargeData, 69 base::Unretained(this))); 70 web_ui()->RegisterMessageCallback( 71 kRequestCpuIdleDataCallback, 72 base::Bind(&PowerMessageHandler::OnGetCpuIdleData, 73 base::Unretained(this))); 74 web_ui()->RegisterMessageCallback( 75 kRequestCpuFreqDataCallback, 76 base::Bind(&PowerMessageHandler::OnGetCpuFreqData, 77 base::Unretained(this))); 78 } 79 80 void PowerMessageHandler::OnGetBatteryChargeData(const base::ListValue* value) { 81 const std::deque<PowerDataCollector::PowerSupplySample>& power_supply = 82 PowerDataCollector::Get()->power_supply_data(); 83 base::ListValue js_power_supply_data; 84 for (size_t i = 0; i < power_supply.size(); ++i) { 85 const PowerDataCollector::PowerSupplySample& sample = power_supply[i]; 86 scoped_ptr<base::DictionaryValue> element(new base::DictionaryValue); 87 element->SetDouble("batteryPercent", sample.battery_percent); 88 element->SetDouble("batteryDischargeRate", sample.battery_discharge_rate); 89 element->SetBoolean("externalPower", sample.external_power); 90 element->SetDouble("time", sample.time.ToJsTime()); 91 92 js_power_supply_data.Append(element.release()); 93 } 94 95 base::ListValue js_system_resumed_data; 96 GetJsSystemResumedData(&js_system_resumed_data); 97 98 web_ui()->CallJavascriptFunction(kOnRequestBatteryChargeDataFunction, 99 js_power_supply_data, 100 js_system_resumed_data); 101 } 102 103 void PowerMessageHandler::OnGetCpuIdleData(const base::ListValue* value) { 104 const CpuDataCollector& cpu_data_collector = 105 PowerDataCollector::Get()->cpu_data_collector(); 106 107 const std::vector<CpuDataCollector::StateOccupancySampleDeque>& idle_data = 108 cpu_data_collector.cpu_idle_state_data(); 109 const std::vector<std::string>& idle_state_names = 110 cpu_data_collector.cpu_idle_state_names(); 111 base::ListValue js_idle_data; 112 GetJsStateOccupancyData(idle_data, idle_state_names, &js_idle_data); 113 114 base::ListValue js_system_resumed_data; 115 GetJsSystemResumedData(&js_system_resumed_data); 116 117 web_ui()->CallJavascriptFunction(kOnRequestCpuIdleDataFunction, 118 js_idle_data, 119 js_system_resumed_data); 120 } 121 122 void PowerMessageHandler::OnGetCpuFreqData(const base::ListValue* value) { 123 const CpuDataCollector& cpu_data_collector = 124 PowerDataCollector::Get()->cpu_data_collector(); 125 126 const std::vector<CpuDataCollector::StateOccupancySampleDeque>& freq_data = 127 cpu_data_collector.cpu_freq_state_data(); 128 const std::vector<std::string>& freq_state_names = 129 cpu_data_collector.cpu_freq_state_names(); 130 base::ListValue js_freq_data; 131 GetJsStateOccupancyData(freq_data, freq_state_names, &js_freq_data); 132 133 base::ListValue js_system_resumed_data; 134 GetJsSystemResumedData(&js_system_resumed_data); 135 136 web_ui()->CallJavascriptFunction(kOnRequestCpuFreqDataFunction, 137 js_freq_data, 138 js_system_resumed_data); 139 } 140 141 void PowerMessageHandler::GetJsSystemResumedData(base::ListValue *data) { 142 DCHECK(data); 143 144 const std::deque<PowerDataCollector::SystemResumedSample>& system_resumed = 145 PowerDataCollector::Get()->system_resumed_data(); 146 for (size_t i = 0; i < system_resumed.size(); ++i) { 147 const PowerDataCollector::SystemResumedSample& sample = system_resumed[i]; 148 scoped_ptr<base::DictionaryValue> element(new base::DictionaryValue); 149 element->SetDouble("sleepDuration", 150 sample.sleep_duration.InMillisecondsF()); 151 element->SetDouble("time", sample.time.ToJsTime()); 152 153 data->Append(element.release()); 154 } 155 } 156 157 void PowerMessageHandler::GetJsStateOccupancyData( 158 const std::vector<CpuDataCollector::StateOccupancySampleDeque>& data, 159 const std::vector<std::string>& state_names, 160 base::ListValue *js_data) { 161 for (unsigned int cpu = 0; cpu < data.size(); ++cpu) { 162 const CpuDataCollector::StateOccupancySampleDeque& sample_deque = data[cpu]; 163 scoped_ptr<base::ListValue> js_sample_list(new base::ListValue); 164 for (unsigned int i = 0; i < sample_deque.size(); ++i) { 165 const CpuDataCollector::StateOccupancySample& sample = sample_deque[i]; 166 scoped_ptr<base::DictionaryValue> js_sample(new base::DictionaryValue); 167 js_sample->SetDouble("time", sample.time.ToJsTime()); 168 js_sample->SetBoolean("cpuOnline", sample.cpu_online); 169 170 scoped_ptr<base::DictionaryValue> state_dict(new base::DictionaryValue); 171 for (size_t index = 0; index < sample.time_in_state.size(); ++index) { 172 state_dict->SetDouble(state_names[index], 173 static_cast<double>(sample.time_in_state[index])); 174 } 175 js_sample->Set("timeInState", state_dict.release()); 176 177 js_sample_list->Append(js_sample.release()); 178 } 179 js_data->Append(js_sample_list.release()); 180 } 181 } 182 183 } // namespace 184 185 PowerUI::PowerUI(content::WebUI* web_ui) : content::WebUIController(web_ui) { 186 web_ui->AddMessageHandler(new PowerMessageHandler()); 187 188 content::WebUIDataSource* html = 189 content::WebUIDataSource::Create(chrome::kChromeUIPowerHost); 190 html->SetUseJsonJSFormatV2(); 191 192 html->AddLocalizedString("titleText", IDS_ABOUT_POWER_TITLE); 193 html->AddLocalizedString("showButton", IDS_ABOUT_POWER_SHOW_BUTTON); 194 html->AddLocalizedString("hideButton", IDS_ABOUT_POWER_HIDE_BUTTON); 195 html->AddLocalizedString("reloadButton", IDS_ABOUT_POWER_RELOAD_BUTTON); 196 html->AddLocalizedString("notEnoughDataAvailableYet", 197 IDS_ABOUT_POWER_NOT_ENOUGH_DATA); 198 html->AddLocalizedString("systemSuspended", 199 IDS_ABOUT_POWER_SYSTEM_SUSPENDED); 200 html->AddLocalizedString("invalidData", IDS_ABOUT_POWER_INVALID); 201 html->AddLocalizedString("offlineText", IDS_ABOUT_POWER_OFFLINE); 202 203 html->AddLocalizedString("batteryChargeSectionTitle", 204 IDS_ABOUT_POWER_BATTERY_CHARGE_SECTION_TITLE); 205 html->AddLocalizedString("batteryChargePercentageHeader", 206 IDS_ABOUT_POWER_BATTERY_CHARGE_PERCENTAGE_HEADER); 207 html->AddLocalizedString("batteryDischargeRateHeader", 208 IDS_ABOUT_POWER_BATTERY_DISCHARGE_RATE_HEADER); 209 html->AddLocalizedString("dischargeRateLegendText", 210 IDS_ABOUT_POWER_DISCHARGE_RATE_LEGEND_TEXT); 211 html->AddLocalizedString("movingAverageLegendText", 212 IDS_ABOUT_POWER_MOVING_AVERAGE_LEGEND_TEXT); 213 html->AddLocalizedString("binnedAverageLegendText", 214 IDS_ABOUT_POWER_BINNED_AVERAGE_LEGEND_TEXT); 215 html->AddLocalizedString("averageOverText", 216 IDS_ABOUT_POWER_AVERAGE_OVER_TEXT); 217 html->AddLocalizedString("samplesText", 218 IDS_ABOUT_POWER_AVERAGE_SAMPLES_TEXT); 219 220 html->AddLocalizedString("cpuIdleSectionTitle", 221 IDS_ABOUT_POWER_CPU_IDLE_SECTION_TITLE); 222 html->AddLocalizedString("idleStateOccupancyPercentageHeader", 223 IDS_ABOUT_POWER_CPU_IDLE_STATE_OCCUPANCY_PERCENTAGE); 224 225 html->AddLocalizedString("cpuFreqSectionTitle", 226 IDS_ABOUT_POWER_CPU_FREQ_SECTION_TITLE); 227 html->AddLocalizedString("frequencyStateOccupancyPercentageHeader", 228 IDS_ABOUT_POWER_CPU_FREQ_STATE_OCCUPANCY_PERCENTAGE); 229 230 html->SetJsonPath(kStringsJsFile); 231 232 html->AddResourcePath("power.css", IDR_ABOUT_POWER_CSS); 233 html->AddResourcePath("power.js", IDR_ABOUT_POWER_JS); 234 html->SetDefaultResource(IDR_ABOUT_POWER_HTML); 235 236 Profile* profile = Profile::FromWebUI(web_ui); 237 content::WebUIDataSource::Add(profile, html); 238 } 239 240 PowerUI::~PowerUI() { 241 } 242 243 } // namespace chromeos 244