blob: 333ecb1b56803ee1ae321640eb0af358873531f0 [file] [log] [blame]
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001// 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 Murdocheb525c52013-07-10 11:40:50 +010010#include "base/time/time.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000011#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
25using content::BrowserThread;
26
27namespace performance_monitor {
28namespace {
29
30std::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
55std::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
80Unit 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
96MetricCategory 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
116Unit 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.
138scoped_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.
152scoped_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.
172scoped_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.
191scoped_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.
212scoped_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|.
226void DoGetActiveIntervals(ListValue* results,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000227 const base::Time& start,
228 const base::Time& end) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000229 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)2a99a7e2013-03-28 15:31:22 +0000244void DoGetEvents(ListValue* results,
245 const std::set<EventType>& event_types,
246 const base::Time& start,
247 const base::Time& end) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000248 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)2a99a7e2013-03-28 15:31:22 +0000264 for (DictionaryValue::Iterator data(*(*event)->data()); !data.IsAtEnd();
265 data.Advance()) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000266 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)2a99a7e2013-03-28 15:31:22 +0000271 if (data.key() == "eventType")
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000272 continue;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000273 else if (data.key() == "time") {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000274 // The property 'time' is also used computationally, but must be
275 // converted to JS-style time.
276 double time = 0.0;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000277 if (!data.value().GetAsDouble(&time)) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000278 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)2a99a7e2013-03-28 15:31:22 +0000288 localized_value->SetString(
289 "label",
290 GetLocalizedStringFromEventProperty(data.key()));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000291 localized_value->SetWithoutPathExpansion("value",
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000292 data.value().DeepCopy());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000293 value = localized_value;
294 }
295
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000296 localized_event->SetWithoutPathExpansion(data.key(), value);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000297 }
298 events->Append(localized_event);
299 }
300 }
301}
302
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000303// 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)2a99a7e2013-03-28 15:31:22 +0000305// 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)58218062012-11-14 11:43:16 +0000308void DoGetMetrics(ListValue* results,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000309 const std::set<MetricType>& metric_types,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000310 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)2a99a7e2013-03-28 15:31:22 +0000331 // 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)58218062012-11-14 11:43:16 +0000351 ListValue* metric_points_by_interval = new ListValue();
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000352
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)58218062012-11-14 11:43:16 +0000370 }
371
372 metric_set->Set("metrics", metric_points_by_interval);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000373 results->Append(metric_set);
374 }
375}
376
377} // namespace
378
379PerformanceMonitorHandler::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
386PerformanceMonitorHandler::~PerformanceMonitorHandler() {}
387
388void 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
419void PerformanceMonitorHandler::ReturnResults(const std::string& function,
420 const Value* results) {
421 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
422 web_ui()->CallJavascriptFunction(function, *results);
423}
424
425void 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
444void 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
453void 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
467void 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
477void 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
509void 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
519void 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