Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 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/performance_monitor/performance_monitor_handler.h" |
| 6 | |
| 7 | #include "base/bind.h" |
| 8 | #include "base/bind_helpers.h" |
| 9 | #include "base/command_line.h" |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 10 | #include "base/time/time.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 11 | #include "base/values.h" |
| 12 | #include "chrome/browser/performance_monitor/database.h" |
| 13 | #include "chrome/browser/performance_monitor/event.h" |
| 14 | #include "chrome/browser/performance_monitor/metric.h" |
| 15 | #include "chrome/browser/performance_monitor/performance_monitor.h" |
| 16 | #include "chrome/browser/performance_monitor/performance_monitor_util.h" |
| 17 | #include "chrome/browser/ui/webui/performance_monitor/performance_monitor_l10n.h" |
| 18 | #include "chrome/browser/ui/webui/performance_monitor/performance_monitor_ui_constants.h" |
| 19 | #include "chrome/browser/ui/webui/performance_monitor/performance_monitor_ui_util.h" |
| 20 | #include "chrome/common/chrome_switches.h" |
| 21 | #include "chrome/common/extensions/value_builder.h" |
| 22 | #include "content/public/browser/browser_thread.h" |
| 23 | #include "content/public/browser/web_ui.h" |
| 24 | |
| 25 | using content::BrowserThread; |
| 26 | |
| 27 | namespace performance_monitor { |
| 28 | namespace { |
| 29 | |
| 30 | std::set<MetricType> GetMetricSetForCategory(MetricCategory category) { |
| 31 | std::set<MetricType> metric_set; |
| 32 | switch (category) { |
| 33 | case METRIC_CATEGORY_CPU: |
| 34 | metric_set.insert(METRIC_CPU_USAGE); |
| 35 | break; |
| 36 | case METRIC_CATEGORY_MEMORY: |
| 37 | metric_set.insert(METRIC_SHARED_MEMORY_USAGE); |
| 38 | metric_set.insert(METRIC_PRIVATE_MEMORY_USAGE); |
| 39 | break; |
| 40 | case METRIC_CATEGORY_TIMING: |
| 41 | metric_set.insert(METRIC_STARTUP_TIME); |
| 42 | metric_set.insert(METRIC_TEST_STARTUP_TIME); |
| 43 | metric_set.insert(METRIC_SESSION_RESTORE_TIME); |
| 44 | metric_set.insert(METRIC_PAGE_LOAD_TIME); |
| 45 | break; |
| 46 | case METRIC_CATEGORY_NETWORK: |
| 47 | metric_set.insert(METRIC_NETWORK_BYTES_READ); |
| 48 | break; |
| 49 | default: |
| 50 | NOTREACHED(); |
| 51 | } |
| 52 | return metric_set; |
| 53 | } |
| 54 | |
| 55 | std::set<EventType> GetEventSetForCategory(EventCategory category) { |
| 56 | std::set<EventType> event_set; |
| 57 | switch (category) { |
| 58 | case EVENT_CATEGORY_EXTENSIONS: |
| 59 | event_set.insert(EVENT_EXTENSION_INSTALL); |
| 60 | event_set.insert(EVENT_EXTENSION_UNINSTALL); |
| 61 | event_set.insert(EVENT_EXTENSION_UPDATE); |
| 62 | event_set.insert(EVENT_EXTENSION_ENABLE); |
| 63 | event_set.insert(EVENT_EXTENSION_DISABLE); |
| 64 | break; |
| 65 | case EVENT_CATEGORY_CHROME: |
| 66 | event_set.insert(EVENT_CHROME_UPDATE); |
| 67 | break; |
| 68 | case EVENT_CATEGORY_EXCEPTIONS: |
| 69 | event_set.insert(EVENT_RENDERER_HANG); |
| 70 | event_set.insert(EVENT_RENDERER_CRASH); |
| 71 | event_set.insert(EVENT_RENDERER_KILLED); |
| 72 | event_set.insert(EVENT_UNCLEAN_EXIT); |
| 73 | break; |
| 74 | default: |
| 75 | NOTREACHED(); |
| 76 | } |
| 77 | return event_set; |
| 78 | } |
| 79 | |
| 80 | Unit GetUnitForMetricCategory(MetricCategory category) { |
| 81 | switch (category) { |
| 82 | case METRIC_CATEGORY_CPU: |
| 83 | return UNIT_PERCENT; |
| 84 | case METRIC_CATEGORY_MEMORY: |
| 85 | return UNIT_MEGABYTES; |
| 86 | case METRIC_CATEGORY_TIMING: |
| 87 | return UNIT_SECONDS; |
| 88 | case METRIC_CATEGORY_NETWORK: |
| 89 | return UNIT_MEGABYTES; |
| 90 | default: |
| 91 | NOTREACHED(); |
| 92 | } |
| 93 | return UNIT_UNDEFINED; |
| 94 | } |
| 95 | |
| 96 | MetricCategory GetCategoryForMetric(MetricType type) { |
| 97 | switch (type) { |
| 98 | case METRIC_CPU_USAGE: |
| 99 | return METRIC_CATEGORY_CPU; |
| 100 | case METRIC_SHARED_MEMORY_USAGE: |
| 101 | case METRIC_PRIVATE_MEMORY_USAGE: |
| 102 | return METRIC_CATEGORY_MEMORY; |
| 103 | case METRIC_STARTUP_TIME: |
| 104 | case METRIC_TEST_STARTUP_TIME: |
| 105 | case METRIC_SESSION_RESTORE_TIME: |
| 106 | case METRIC_PAGE_LOAD_TIME: |
| 107 | return METRIC_CATEGORY_TIMING; |
| 108 | case METRIC_NETWORK_BYTES_READ: |
| 109 | return METRIC_CATEGORY_NETWORK; |
| 110 | default: |
| 111 | NOTREACHED(); |
| 112 | } |
| 113 | return METRIC_CATEGORY_NUMBER_OF_CATEGORIES; |
| 114 | } |
| 115 | |
| 116 | Unit GetUnitForMetricType(MetricType type) { |
| 117 | switch (type) { |
| 118 | case METRIC_CPU_USAGE: |
| 119 | return UNIT_PERCENT; |
| 120 | case METRIC_SHARED_MEMORY_USAGE: |
| 121 | case METRIC_PRIVATE_MEMORY_USAGE: |
| 122 | case METRIC_NETWORK_BYTES_READ: |
| 123 | return UNIT_BYTES; |
| 124 | case METRIC_STARTUP_TIME: |
| 125 | case METRIC_TEST_STARTUP_TIME: |
| 126 | case METRIC_SESSION_RESTORE_TIME: |
| 127 | case METRIC_PAGE_LOAD_TIME: |
| 128 | return UNIT_MICROSECONDS; |
| 129 | default: |
| 130 | NOTREACHED(); |
| 131 | } |
| 132 | return UNIT_UNDEFINED; |
| 133 | } |
| 134 | |
| 135 | // Returns a dictionary for the aggregation method. Aggregation strategies |
| 136 | // contain an id representing the method, and localized strings for the |
| 137 | // method name and method description. |
| 138 | scoped_ptr<DictionaryValue> GetAggregationMethod( |
| 139 | AggregationMethod method) { |
| 140 | scoped_ptr<DictionaryValue> value(new DictionaryValue()); |
| 141 | value->SetInteger("id", method); |
| 142 | value->SetString("name", GetLocalizedStringFromAggregationMethod(method)); |
| 143 | value->SetString( |
| 144 | "description", |
| 145 | GetLocalizedStringForAggregationMethodDescription(method)); |
| 146 | return value.Pass(); |
| 147 | } |
| 148 | |
| 149 | // Returns a list of metric details, with one entry per metric. Metric details |
| 150 | // are dictionaries which contain the id representing the metric and localized |
| 151 | // strings for the metric name and metric description. |
| 152 | scoped_ptr<ListValue> GetMetricDetailsForCategory(MetricCategory category) { |
| 153 | scoped_ptr<ListValue> value(new ListValue()); |
| 154 | std::set<MetricType> metric_set = GetMetricSetForCategory(category); |
| 155 | for (std::set<MetricType>::const_iterator iter = metric_set.begin(); |
| 156 | iter != metric_set.end(); ++iter) { |
| 157 | DictionaryValue* metric_details = new DictionaryValue(); |
| 158 | metric_details->SetInteger("metricId", *iter); |
| 159 | metric_details->SetString( |
| 160 | "name", GetLocalizedStringFromMetricType(*iter)); |
| 161 | metric_details->SetString( |
| 162 | "description", GetLocalizedStringForMetricTypeDescription(*iter)); |
| 163 | value->Append(metric_details); |
| 164 | } |
| 165 | return value.Pass(); |
| 166 | } |
| 167 | |
| 168 | // Returns a dictionary for the metric category. Metric categories contain |
| 169 | // an id representing the category; localized strings for the category name, |
| 170 | // the default unit in which the category is measured, and the category's |
| 171 | // description; and the metric details for each metric type in the category. |
| 172 | scoped_ptr<DictionaryValue> GetMetricCategory(MetricCategory category) { |
| 173 | scoped_ptr<DictionaryValue> value(new DictionaryValue()); |
| 174 | value->SetInteger("metricCategoryId", category); |
| 175 | value->SetString( |
| 176 | "name", GetLocalizedStringFromMetricCategory(category)); |
| 177 | value->SetString( |
| 178 | "unit", |
| 179 | GetLocalizedStringFromUnit(GetUnitForMetricCategory(category))); |
| 180 | value->SetString( |
| 181 | "description", |
| 182 | GetLocalizedStringForMetricCategoryDescription(category)); |
| 183 | value->Set("details", GetMetricDetailsForCategory(category).release()); |
| 184 | return value.Pass(); |
| 185 | } |
| 186 | |
| 187 | // Returns a list of event types, with one entry per event. Event types |
| 188 | // are dictionaries which contain the id representing the event and localized |
| 189 | // strings for the event name, event description, and a title suitable for a |
| 190 | // mouseover popup. |
| 191 | scoped_ptr<ListValue> GetEventTypesForCategory(EventCategory category) { |
| 192 | scoped_ptr<ListValue> value(new ListValue()); |
| 193 | std::set<EventType> event_set = GetEventSetForCategory(category); |
| 194 | for (std::set<EventType>::const_iterator iter = event_set.begin(); |
| 195 | iter != event_set.end(); ++iter) { |
| 196 | DictionaryValue* event_details = new DictionaryValue(); |
| 197 | event_details->SetInteger("eventId", *iter); |
| 198 | event_details->SetString( |
| 199 | "name", GetLocalizedStringFromEventType(*iter)); |
| 200 | event_details->SetString( |
| 201 | "description", GetLocalizedStringForEventTypeDescription(*iter)); |
| 202 | event_details->SetString( |
| 203 | "popupTitle", GetLocalizedStringForEventTypeMouseover(*iter)); |
| 204 | value->Append(event_details); |
| 205 | } |
| 206 | return value.Pass(); |
| 207 | } |
| 208 | |
| 209 | // Returns a dictionary for the event category. Event categories contain an |
| 210 | // id representing the category, localized strings for the event name and |
| 211 | // event description, and event details for each event type in the category. |
| 212 | scoped_ptr<DictionaryValue> GetEventCategory(EventCategory category) { |
| 213 | scoped_ptr<DictionaryValue> value(new DictionaryValue()); |
| 214 | value->SetInteger("eventCategoryId", category); |
| 215 | value->SetString( |
| 216 | "name", GetLocalizedStringFromEventCategory(category)); |
| 217 | value->SetString( |
| 218 | "description", |
| 219 | GetLocalizedStringForEventCategoryDescription(category)); |
| 220 | value->Set("details", GetEventTypesForCategory(category).release()); |
| 221 | return value.Pass(); |
| 222 | } |
| 223 | |
| 224 | // Queries the performance monitor database for active intervals between |
| 225 | // |start| and |end| times and appends the results to |results|. |
| 226 | void DoGetActiveIntervals(ListValue* results, |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 227 | const base::Time& start, |
| 228 | const base::Time& end) { |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 229 | Database* db = PerformanceMonitor::GetInstance()->database(); |
| 230 | std::vector<TimeRange> intervals = db->GetActiveIntervals(start, end); |
| 231 | |
| 232 | for (std::vector<TimeRange>::iterator it = intervals.begin(); |
| 233 | it != intervals.end(); ++it) { |
| 234 | DictionaryValue* interval_value = new DictionaryValue(); |
| 235 | interval_value->SetDouble("start", it->start.ToJsTime()); |
| 236 | interval_value->SetDouble("end", it->end.ToJsTime()); |
| 237 | results->Append(interval_value); |
| 238 | } |
| 239 | } |
| 240 | |
| 241 | // Queries the PerformanceMonitor database for events of type |event_type| |
| 242 | // between |start| and |end| times, creates a new event with localized keys |
| 243 | // for display, and appends the results to |results|. |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 244 | void DoGetEvents(ListValue* results, |
| 245 | const std::set<EventType>& event_types, |
| 246 | const base::Time& start, |
| 247 | const base::Time& end) { |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 248 | Database* db = PerformanceMonitor::GetInstance()->database(); |
| 249 | |
| 250 | for (std::set<EventType>::const_iterator iter = event_types.begin(); |
| 251 | iter != event_types.end(); ++iter) { |
| 252 | DictionaryValue* event_results = new DictionaryValue(); |
| 253 | event_results->SetInteger("eventId", static_cast<int>(*iter)); |
| 254 | ListValue* events = new ListValue(); |
| 255 | event_results->Set("events", events); |
| 256 | results->Append(event_results); |
| 257 | |
| 258 | Database::EventVector event_vector = db->GetEvents(*iter, start, end); |
| 259 | |
| 260 | for (Database::EventVector::iterator event = event_vector.begin(); |
| 261 | event != event_vector.end(); ++event) { |
| 262 | DictionaryValue* localized_event = new DictionaryValue(); |
| 263 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 264 | for (DictionaryValue::Iterator data(*(*event)->data()); !data.IsAtEnd(); |
| 265 | data.Advance()) { |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 266 | Value* value = NULL; |
| 267 | |
| 268 | // The property 'eventType' is set in HandleGetEvents as part of the |
| 269 | // entire result set, so we don't need to include this here in the |
| 270 | // event. |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 271 | if (data.key() == "eventType") |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 272 | continue; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 273 | else if (data.key() == "time") { |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 274 | // The property 'time' is also used computationally, but must be |
| 275 | // converted to JS-style time. |
| 276 | double time = 0.0; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 277 | if (!data.value().GetAsDouble(&time)) { |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 278 | LOG(ERROR) << "Failed to get 'time' field from event."; |
| 279 | continue; |
| 280 | } |
| 281 | value = Value::CreateDoubleValue( |
| 282 | base::Time::FromInternalValue( |
| 283 | static_cast<int64>(time)).ToJsTime()); |
| 284 | } else { |
| 285 | // All other values are user-facing, so we create a new value for |
| 286 | // localized display. |
| 287 | DictionaryValue* localized_value = new DictionaryValue(); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 288 | localized_value->SetString( |
| 289 | "label", |
| 290 | GetLocalizedStringFromEventProperty(data.key())); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 291 | localized_value->SetWithoutPathExpansion("value", |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 292 | data.value().DeepCopy()); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 293 | value = localized_value; |
| 294 | } |
| 295 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 296 | localized_event->SetWithoutPathExpansion(data.key(), value); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 297 | } |
| 298 | events->Append(localized_event); |
| 299 | } |
| 300 | } |
| 301 | } |
| 302 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 303 | // Populates results with a dictionary for each metric requested. The dictionary |
| 304 | // includes a metric id, the maximum value for the metric, and a list of lists |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 305 | // of metric points, with each sublist containing the aggregated data for an |
| 306 | // interval for which PerformanceMonitor was active. This will also convert |
| 307 | // time to JS-style time. |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 308 | void DoGetMetrics(ListValue* results, |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 309 | const std::set<MetricType>& metric_types, |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 310 | const base::Time& start, |
| 311 | const base::Time& end, |
| 312 | const base::TimeDelta& resolution, |
| 313 | AggregationMethod aggregation_method) { |
| 314 | Database* db = PerformanceMonitor::GetInstance()->database(); |
| 315 | std::vector<TimeRange> intervals = db->GetActiveIntervals(start, end); |
| 316 | |
| 317 | // For each metric type, populate a new dictionary and append it to results. |
| 318 | for (std::set<MetricType>::const_iterator metric_type = metric_types.begin(); |
| 319 | metric_type != metric_types.end(); ++metric_type) { |
| 320 | double conversion_factor = |
| 321 | GetConversionFactor(*GetUnitDetails(GetUnitForMetricType(*metric_type)), |
| 322 | *GetUnitDetails(GetUnitForMetricCategory( |
| 323 | GetCategoryForMetric(*metric_type)))); |
| 324 | |
| 325 | DictionaryValue* metric_set = new DictionaryValue(); |
| 326 | metric_set->SetInteger("metricId", static_cast<int>(*metric_type)); |
| 327 | metric_set->SetDouble( |
| 328 | "maxValue", |
| 329 | db->GetMaxStatsForActivityAndMetric(*metric_type) * conversion_factor); |
| 330 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 331 | // Retrieve all metrics in the database, and aggregate them into a series |
| 332 | // of points for each active interval. |
| 333 | scoped_ptr<Database::MetricVector> metric_vector = |
| 334 | db->GetStatsForActivityAndMetric(*metric_type, start, end); |
| 335 | |
| 336 | scoped_ptr<VectorOfMetricVectors> aggregated_metrics = |
| 337 | AggregateMetric(*metric_type, |
| 338 | metric_vector.get(), |
| 339 | start, |
| 340 | intervals, |
| 341 | resolution, |
| 342 | aggregation_method); |
| 343 | |
| 344 | // The JS-side expects a list to be present, even if there are no metrics. |
| 345 | if (!aggregated_metrics) { |
| 346 | metric_set->Set("metrics", new ListValue()); |
| 347 | results->Append(metric_set); |
| 348 | continue; |
| 349 | } |
| 350 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 351 | ListValue* metric_points_by_interval = new ListValue(); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 352 | |
| 353 | // For each metric point, record it in the expected format for the JS-side |
| 354 | // (a dictionary of time and value, with time as a JS-style time), and |
| 355 | // convert the values to be display-friendly. |
| 356 | for (VectorOfMetricVectors::const_iterator metric_series = |
| 357 | aggregated_metrics->begin(); |
| 358 | metric_series != aggregated_metrics->end(); ++metric_series) { |
| 359 | ListValue* series_value = new ListValue(); |
| 360 | for (Database::MetricVector::const_iterator metric_point = |
| 361 | metric_series->begin(); |
| 362 | metric_point != metric_series->end(); ++metric_point) { |
| 363 | DictionaryValue* point_value = new DictionaryValue(); |
| 364 | point_value->SetDouble("time", metric_point->time.ToJsTime()); |
| 365 | point_value->SetDouble("value", |
| 366 | metric_point->value * conversion_factor); |
| 367 | series_value->Append(point_value); |
| 368 | } |
| 369 | metric_points_by_interval->Append(series_value); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 370 | } |
| 371 | |
| 372 | metric_set->Set("metrics", metric_points_by_interval); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 373 | results->Append(metric_set); |
| 374 | } |
| 375 | } |
| 376 | |
| 377 | } // namespace |
| 378 | |
| 379 | PerformanceMonitorHandler::PerformanceMonitorHandler() { |
| 380 | // If we are not running the --run-performance-monitor flag, we will not have |
| 381 | // started PerformanceMonitor. |
| 382 | if (!PerformanceMonitor::initialized()) |
| 383 | PerformanceMonitor::GetInstance()->Start(); |
| 384 | } |
| 385 | |
| 386 | PerformanceMonitorHandler::~PerformanceMonitorHandler() {} |
| 387 | |
| 388 | void PerformanceMonitorHandler::RegisterMessages() { |
| 389 | web_ui()->RegisterMessageCallback( |
| 390 | "getActiveIntervals", |
| 391 | base::Bind(&PerformanceMonitorHandler::HandleGetActiveIntervals, |
| 392 | AsWeakPtr())); |
| 393 | web_ui()->RegisterMessageCallback( |
| 394 | "getFlagEnabled", |
| 395 | base::Bind(&PerformanceMonitorHandler::HandleGetFlagEnabled, |
| 396 | AsWeakPtr())); |
| 397 | web_ui()->RegisterMessageCallback( |
| 398 | "getAggregationTypes", |
| 399 | base::Bind(&PerformanceMonitorHandler::HandleGetAggregationTypes, |
| 400 | AsWeakPtr())); |
| 401 | web_ui()->RegisterMessageCallback( |
| 402 | "getEventTypes", |
| 403 | base::Bind(&PerformanceMonitorHandler::HandleGetEventTypes, |
| 404 | AsWeakPtr())); |
| 405 | web_ui()->RegisterMessageCallback( |
| 406 | "getEvents", |
| 407 | base::Bind(&PerformanceMonitorHandler::HandleGetEvents, |
| 408 | AsWeakPtr())); |
| 409 | web_ui()->RegisterMessageCallback( |
| 410 | "getMetricTypes", |
| 411 | base::Bind(&PerformanceMonitorHandler::HandleGetMetricTypes, |
| 412 | AsWeakPtr())); |
| 413 | web_ui()->RegisterMessageCallback( |
| 414 | "getMetrics", |
| 415 | base::Bind(&PerformanceMonitorHandler::HandleGetMetrics, |
| 416 | AsWeakPtr())); |
| 417 | } |
| 418 | |
| 419 | void PerformanceMonitorHandler::ReturnResults(const std::string& function, |
| 420 | const Value* results) { |
| 421 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 422 | web_ui()->CallJavascriptFunction(function, *results); |
| 423 | } |
| 424 | |
| 425 | void PerformanceMonitorHandler::HandleGetActiveIntervals( |
| 426 | const ListValue* args) { |
| 427 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 428 | CHECK_EQ(2u, args->GetSize()); |
| 429 | double double_time = 0.0; |
| 430 | CHECK(args->GetDouble(0, &double_time)); |
| 431 | base::Time start = base::Time::FromJsTime(double_time); |
| 432 | CHECK(args->GetDouble(1, &double_time)); |
| 433 | base::Time end = base::Time::FromJsTime(double_time); |
| 434 | |
| 435 | ListValue* results = new ListValue(); |
| 436 | util::PostTaskToDatabaseThreadAndReply( |
| 437 | FROM_HERE, |
| 438 | base::Bind(&DoGetActiveIntervals, results, start, end), |
| 439 | base::Bind(&PerformanceMonitorHandler::ReturnResults, AsWeakPtr(), |
| 440 | "PerformanceMonitor.getActiveIntervalsCallback", |
| 441 | base::Owned(results))); |
| 442 | } |
| 443 | |
| 444 | void PerformanceMonitorHandler::HandleGetFlagEnabled(const ListValue* args) { |
| 445 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 446 | CHECK_EQ(0u, args->GetSize()); |
| 447 | scoped_ptr<Value> value(Value::CreateBooleanValue( |
| 448 | CommandLine::ForCurrentProcess()->HasSwitch( |
| 449 | switches::kPerformanceMonitorGathering))); |
| 450 | ReturnResults("PerformanceMonitor.getFlagEnabledCallback", value.get()); |
| 451 | } |
| 452 | |
| 453 | void PerformanceMonitorHandler::HandleGetAggregationTypes( |
| 454 | const ListValue* args) { |
| 455 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 456 | CHECK_EQ(0u, args->GetSize()); |
| 457 | ListValue results; |
| 458 | for (int i = 0; i < AGGREGATION_METHOD_NUMBER_OF_METHODS; ++i) { |
| 459 | results.Append( |
| 460 | GetAggregationMethod(static_cast<AggregationMethod>(i)).release()); |
| 461 | } |
| 462 | |
| 463 | ReturnResults( |
| 464 | "PerformanceMonitor.getAggregationTypesCallback", &results); |
| 465 | } |
| 466 | |
| 467 | void PerformanceMonitorHandler::HandleGetEventTypes(const ListValue* args) { |
| 468 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 469 | CHECK_EQ(0u, args->GetSize()); |
| 470 | ListValue results; |
| 471 | for (int i = 0; i < EVENT_CATEGORY_NUMBER_OF_CATEGORIES; ++i) |
| 472 | results.Append(GetEventCategory(static_cast<EventCategory>(i)).release()); |
| 473 | |
| 474 | ReturnResults("PerformanceMonitor.getEventTypesCallback", &results); |
| 475 | } |
| 476 | |
| 477 | void PerformanceMonitorHandler::HandleGetEvents(const ListValue* args) { |
| 478 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 479 | CHECK_EQ(3u, args->GetSize()); |
| 480 | |
| 481 | const ListValue* event_type_list; |
| 482 | CHECK(args->GetList(0, &event_type_list)); |
| 483 | std::set<EventType> event_types; |
| 484 | for (ListValue::const_iterator iter = event_type_list->begin(); |
| 485 | iter != event_type_list->end(); ++iter) { |
| 486 | double event_type_double = 0.0; |
| 487 | CHECK((*iter)->GetAsDouble(&event_type_double)); |
| 488 | CHECK(event_type_double < EVENT_NUMBER_OF_EVENTS && |
| 489 | event_type_double > EVENT_UNDEFINED); |
| 490 | event_types.insert( |
| 491 | static_cast<EventType>(static_cast<int>(event_type_double))); |
| 492 | } |
| 493 | |
| 494 | double double_time = 0.0; |
| 495 | CHECK(args->GetDouble(1, &double_time)); |
| 496 | base::Time start = base::Time::FromJsTime(double_time); |
| 497 | CHECK(args->GetDouble(2, &double_time)); |
| 498 | base::Time end = base::Time::FromJsTime(double_time); |
| 499 | |
| 500 | ListValue* results = new ListValue(); |
| 501 | util::PostTaskToDatabaseThreadAndReply( |
| 502 | FROM_HERE, |
| 503 | base::Bind(&DoGetEvents, results, event_types, start, end), |
| 504 | base::Bind(&PerformanceMonitorHandler::ReturnResults, AsWeakPtr(), |
| 505 | "PerformanceMonitor.getEventsCallback", |
| 506 | base::Owned(results))); |
| 507 | } |
| 508 | |
| 509 | void PerformanceMonitorHandler::HandleGetMetricTypes(const ListValue* args) { |
| 510 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 511 | CHECK_EQ(0u, args->GetSize()); |
| 512 | ListValue results; |
| 513 | for (int i = 0; i < METRIC_CATEGORY_NUMBER_OF_CATEGORIES; ++i) |
| 514 | results.Append(GetMetricCategory(static_cast<MetricCategory>(i)).release()); |
| 515 | |
| 516 | ReturnResults("PerformanceMonitor.getMetricTypesCallback", &results); |
| 517 | } |
| 518 | |
| 519 | void PerformanceMonitorHandler::HandleGetMetrics(const ListValue* args) { |
| 520 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 521 | CHECK_EQ(5u, args->GetSize()); |
| 522 | |
| 523 | const ListValue* metric_type_list; |
| 524 | CHECK(args->GetList(0, &metric_type_list)); |
| 525 | std::set<MetricType> metric_types; |
| 526 | for (ListValue::const_iterator iter = metric_type_list->begin(); |
| 527 | iter != metric_type_list->end(); ++iter) { |
| 528 | double metric_type_double = 0.0; |
| 529 | CHECK((*iter)->GetAsDouble(&metric_type_double)); |
| 530 | CHECK(metric_type_double < METRIC_NUMBER_OF_METRICS && |
| 531 | metric_type_double > METRIC_UNDEFINED); |
| 532 | metric_types.insert( |
| 533 | static_cast<MetricType>(static_cast<int>(metric_type_double))); |
| 534 | } |
| 535 | |
| 536 | double time_double = 0.0; |
| 537 | CHECK(args->GetDouble(1, &time_double)); |
| 538 | base::Time start = base::Time::FromJsTime(time_double); |
| 539 | CHECK(args->GetDouble(2, &time_double)); |
| 540 | base::Time end = base::Time::FromJsTime(time_double); |
| 541 | |
| 542 | double resolution_in_milliseconds = 0.0; |
| 543 | CHECK(args->GetDouble(3, &resolution_in_milliseconds)); |
| 544 | base::TimeDelta resolution = |
| 545 | base::TimeDelta::FromMilliseconds(resolution_in_milliseconds); |
| 546 | |
| 547 | double aggregation_double = 0.0; |
| 548 | CHECK(args->GetDouble(4, &aggregation_double)); |
| 549 | CHECK(aggregation_double < AGGREGATION_METHOD_NUMBER_OF_METHODS && |
| 550 | aggregation_double >= 0); |
| 551 | AggregationMethod aggregation_method = |
| 552 | static_cast<AggregationMethod>(static_cast<int>(aggregation_double)); |
| 553 | |
| 554 | ListValue* results = new ListValue(); |
| 555 | util::PostTaskToDatabaseThreadAndReply( |
| 556 | FROM_HERE, |
| 557 | base::Bind(&DoGetMetrics, results, metric_types, |
| 558 | start, end, resolution, aggregation_method), |
| 559 | base::Bind(&PerformanceMonitorHandler::ReturnResults, AsWeakPtr(), |
| 560 | "PerformanceMonitor.getMetricsCallback", |
| 561 | base::Owned(results))); |
| 562 | } |
| 563 | |
| 564 | } // namespace performance_monitor |