Home | History | Annotate | Download | only in performance_monitor
      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"
     10 #include "base/time/time.h"
     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 "content/public/browser/browser_thread.h"
     22 #include "content/public/browser/web_ui.h"
     23 #include "extensions/common/value_builder.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,
    227                           const base::Time& start,
    228                           const base::Time& end) {
    229   Database* db = PerformanceMonitor::GetInstance()->database();
    230   if (db == NULL)
    231     return;
    232 
    233   std::vector<TimeRange> intervals = db->GetActiveIntervals(start, end);
    234 
    235   for (std::vector<TimeRange>::iterator it = intervals.begin();
    236        it != intervals.end(); ++it) {
    237     DictionaryValue* interval_value = new DictionaryValue();
    238     interval_value->SetDouble("start", it->start.ToJsTime());
    239     interval_value->SetDouble("end", it->end.ToJsTime());
    240     results->Append(interval_value);
    241   }
    242 }
    243 
    244 // Queries the PerformanceMonitor database for events of type |event_type|
    245 // between |start| and |end| times, creates a new event with localized keys
    246 // for display, and appends the results to |results|.
    247 void DoGetEvents(ListValue* results,
    248                  const std::set<EventType>& event_types,
    249                  const base::Time& start,
    250                  const base::Time& end) {
    251   Database* db = PerformanceMonitor::GetInstance()->database();
    252   if (db == NULL)
    253     return;
    254 
    255   for (std::set<EventType>::const_iterator iter = event_types.begin();
    256        iter != event_types.end(); ++iter) {
    257     DictionaryValue* event_results = new DictionaryValue();
    258     event_results->SetInteger("eventId", static_cast<int>(*iter));
    259     ListValue* events = new ListValue();
    260     event_results->Set("events", events);
    261     results->Append(event_results);
    262 
    263     Database::EventVector event_vector = db->GetEvents(*iter, start, end);
    264 
    265     for (Database::EventVector::iterator event = event_vector.begin();
    266          event != event_vector.end(); ++event) {
    267       DictionaryValue* localized_event = new DictionaryValue();
    268 
    269       for (DictionaryValue::Iterator data(*(*event)->data()); !data.IsAtEnd();
    270            data.Advance()) {
    271         Value* value = NULL;
    272 
    273         // The property 'eventType' is set in HandleGetEvents as part of the
    274         // entire result set, so we don't need to include this here in the
    275         // event.
    276         if (data.key() == "eventType")
    277           continue;
    278         else if (data.key() == "time") {
    279           // The property 'time' is also used computationally, but must be
    280           // converted to JS-style time.
    281           double time = 0.0;
    282           if (!data.value().GetAsDouble(&time)) {
    283             LOG(ERROR) << "Failed to get 'time' field from event.";
    284             continue;
    285           }
    286           value = Value::CreateDoubleValue(
    287               base::Time::FromInternalValue(
    288                   static_cast<int64>(time)).ToJsTime());
    289         } else {
    290           // All other values are user-facing, so we create a new value for
    291           // localized display.
    292           DictionaryValue* localized_value = new DictionaryValue();
    293           localized_value->SetString(
    294               "label",
    295               GetLocalizedStringFromEventProperty(data.key()));
    296           localized_value->SetWithoutPathExpansion("value",
    297                                                    data.value().DeepCopy());
    298           value = localized_value;
    299         }
    300 
    301         localized_event->SetWithoutPathExpansion(data.key(), value);
    302       }
    303       events->Append(localized_event);
    304     }
    305   }
    306 }
    307 
    308 // Populates results with a dictionary for each metric requested. The dictionary
    309 // includes a metric id, the maximum value for the metric, and a list of lists
    310 // of metric points, with each sublist containing the aggregated data for an
    311 // interval for which PerformanceMonitor was active. This will also convert
    312 // time to JS-style time.
    313 void DoGetMetrics(ListValue* results,
    314                   const std::set<MetricType>& metric_types,
    315                   const base::Time& start,
    316                   const base::Time& end,
    317                   const base::TimeDelta& resolution,
    318                   AggregationMethod aggregation_method) {
    319   Database* db = PerformanceMonitor::GetInstance()->database();
    320   if (db == NULL)
    321     return;
    322 
    323   std::vector<TimeRange> intervals = db->GetActiveIntervals(start, end);
    324 
    325   // For each metric type, populate a new dictionary and append it to results.
    326   for (std::set<MetricType>::const_iterator metric_type = metric_types.begin();
    327        metric_type != metric_types.end(); ++metric_type) {
    328     double conversion_factor =
    329         GetConversionFactor(*GetUnitDetails(GetUnitForMetricType(*metric_type)),
    330                             *GetUnitDetails(GetUnitForMetricCategory(
    331                                 GetCategoryForMetric(*metric_type))));
    332 
    333     DictionaryValue* metric_set = new DictionaryValue();
    334     metric_set->SetInteger("metricId", static_cast<int>(*metric_type));
    335     metric_set->SetDouble(
    336         "maxValue",
    337         db->GetMaxStatsForActivityAndMetric(*metric_type) * conversion_factor);
    338 
    339     // Retrieve all metrics in the database, and aggregate them into a series
    340     // of points for each active interval.
    341     scoped_ptr<Database::MetricVector> metric_vector =
    342         db->GetStatsForActivityAndMetric(*metric_type, start, end);
    343 
    344     scoped_ptr<VectorOfMetricVectors> aggregated_metrics =
    345         AggregateMetric(*metric_type,
    346                         metric_vector.get(),
    347                         start,
    348                         intervals,
    349                         resolution,
    350                         aggregation_method);
    351 
    352     // The JS-side expects a list to be present, even if there are no metrics.
    353     if (!aggregated_metrics) {
    354       metric_set->Set("metrics", new ListValue());
    355       results->Append(metric_set);
    356       continue;
    357     }
    358 
    359     ListValue* metric_points_by_interval = new ListValue();
    360 
    361     // For each metric point, record it in the expected format for the JS-side
    362     // (a dictionary of time and value, with time as a JS-style time), and
    363     // convert the values to be display-friendly.
    364     for (VectorOfMetricVectors::const_iterator metric_series =
    365              aggregated_metrics->begin();
    366          metric_series != aggregated_metrics->end(); ++metric_series) {
    367       ListValue* series_value = new ListValue();
    368       for (Database::MetricVector::const_iterator metric_point =
    369                metric_series->begin();
    370            metric_point != metric_series->end(); ++metric_point) {
    371         DictionaryValue* point_value = new DictionaryValue();
    372         point_value->SetDouble("time", metric_point->time.ToJsTime());
    373         point_value->SetDouble("value",
    374                                metric_point->value * conversion_factor);
    375         series_value->Append(point_value);
    376       }
    377       metric_points_by_interval->Append(series_value);
    378     }
    379 
    380     metric_set->Set("metrics", metric_points_by_interval);
    381     results->Append(metric_set);
    382   }
    383 }
    384 
    385 }  // namespace
    386 
    387 PerformanceMonitorHandler::PerformanceMonitorHandler() {
    388 }
    389 
    390 PerformanceMonitorHandler::~PerformanceMonitorHandler() {}
    391 
    392 void PerformanceMonitorHandler::RegisterMessages() {
    393   web_ui()->RegisterMessageCallback(
    394       "getActiveIntervals",
    395       base::Bind(&PerformanceMonitorHandler::HandleGetActiveIntervals,
    396                  AsWeakPtr()));
    397   web_ui()->RegisterMessageCallback(
    398       "getFlagEnabled",
    399       base::Bind(&PerformanceMonitorHandler::HandleGetFlagEnabled,
    400                  AsWeakPtr()));
    401   web_ui()->RegisterMessageCallback(
    402       "getAggregationTypes",
    403       base::Bind(&PerformanceMonitorHandler::HandleGetAggregationTypes,
    404                  AsWeakPtr()));
    405   web_ui()->RegisterMessageCallback(
    406       "getEventTypes",
    407       base::Bind(&PerformanceMonitorHandler::HandleGetEventTypes,
    408                  AsWeakPtr()));
    409   web_ui()->RegisterMessageCallback(
    410       "getEvents",
    411       base::Bind(&PerformanceMonitorHandler::HandleGetEvents,
    412                  AsWeakPtr()));
    413   web_ui()->RegisterMessageCallback(
    414       "getMetricTypes",
    415       base::Bind(&PerformanceMonitorHandler::HandleGetMetricTypes,
    416                  AsWeakPtr()));
    417   web_ui()->RegisterMessageCallback(
    418       "getMetrics",
    419       base::Bind(&PerformanceMonitorHandler::HandleGetMetrics,
    420                  AsWeakPtr()));
    421 }
    422 
    423 void PerformanceMonitorHandler::ReturnResults(const std::string& function,
    424                                  const Value* results) {
    425   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    426   web_ui()->CallJavascriptFunction(function, *results);
    427 }
    428 
    429 void PerformanceMonitorHandler::HandleGetActiveIntervals(
    430     const ListValue* args) {
    431   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    432   CHECK_EQ(2u, args->GetSize());
    433   double double_time = 0.0;
    434   CHECK(args->GetDouble(0, &double_time));
    435   base::Time start = base::Time::FromJsTime(double_time);
    436   CHECK(args->GetDouble(1, &double_time));
    437   base::Time end = base::Time::FromJsTime(double_time);
    438 
    439   ListValue* results = new ListValue();
    440   util::PostTaskToDatabaseThreadAndReply(
    441       FROM_HERE,
    442       base::Bind(&DoGetActiveIntervals, results, start, end),
    443       base::Bind(&PerformanceMonitorHandler::ReturnResults, AsWeakPtr(),
    444                  "PerformanceMonitor.getActiveIntervalsCallback",
    445                  base::Owned(results)));
    446 }
    447 
    448 void PerformanceMonitorHandler::HandleGetFlagEnabled(const ListValue* args) {
    449   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    450   CHECK_EQ(0u, args->GetSize());
    451   scoped_ptr<Value> value(Value::CreateBooleanValue(
    452       CommandLine::ForCurrentProcess()->HasSwitch(
    453           switches::kPerformanceMonitorGathering)));
    454   ReturnResults("PerformanceMonitor.getFlagEnabledCallback", value.get());
    455 }
    456 
    457 void PerformanceMonitorHandler::HandleGetAggregationTypes(
    458     const ListValue* args) {
    459   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    460   CHECK_EQ(0u, args->GetSize());
    461   ListValue results;
    462   for (int i = 0; i < AGGREGATION_METHOD_NUMBER_OF_METHODS; ++i) {
    463     results.Append(
    464         GetAggregationMethod(static_cast<AggregationMethod>(i)).release());
    465   }
    466 
    467   ReturnResults(
    468       "PerformanceMonitor.getAggregationTypesCallback", &results);
    469 }
    470 
    471 void PerformanceMonitorHandler::HandleGetEventTypes(const ListValue* args) {
    472   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    473   CHECK_EQ(0u, args->GetSize());
    474   ListValue results;
    475   for (int i = 0; i < EVENT_CATEGORY_NUMBER_OF_CATEGORIES; ++i)
    476     results.Append(GetEventCategory(static_cast<EventCategory>(i)).release());
    477 
    478   ReturnResults("PerformanceMonitor.getEventTypesCallback", &results);
    479 }
    480 
    481 void PerformanceMonitorHandler::HandleGetEvents(const ListValue* args) {
    482   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    483   CHECK_EQ(3u, args->GetSize());
    484 
    485   const ListValue* event_type_list;
    486   CHECK(args->GetList(0, &event_type_list));
    487   std::set<EventType> event_types;
    488   for (ListValue::const_iterator iter = event_type_list->begin();
    489        iter != event_type_list->end(); ++iter) {
    490     double event_type_double = 0.0;
    491     CHECK((*iter)->GetAsDouble(&event_type_double));
    492     CHECK(event_type_double < EVENT_NUMBER_OF_EVENTS &&
    493         event_type_double > EVENT_UNDEFINED);
    494     event_types.insert(
    495         static_cast<EventType>(static_cast<int>(event_type_double)));
    496   }
    497 
    498   double double_time = 0.0;
    499   CHECK(args->GetDouble(1, &double_time));
    500   base::Time start = base::Time::FromJsTime(double_time);
    501   CHECK(args->GetDouble(2, &double_time));
    502   base::Time end = base::Time::FromJsTime(double_time);
    503 
    504   ListValue* results = new ListValue();
    505   util::PostTaskToDatabaseThreadAndReply(
    506       FROM_HERE,
    507       base::Bind(&DoGetEvents, results, event_types, start, end),
    508       base::Bind(&PerformanceMonitorHandler::ReturnResults, AsWeakPtr(),
    509                  "PerformanceMonitor.getEventsCallback",
    510                  base::Owned(results)));
    511 }
    512 
    513 void PerformanceMonitorHandler::HandleGetMetricTypes(const ListValue* args) {
    514   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    515   CHECK_EQ(0u, args->GetSize());
    516   ListValue results;
    517   for (int i = 0; i < METRIC_CATEGORY_NUMBER_OF_CATEGORIES; ++i)
    518     results.Append(GetMetricCategory(static_cast<MetricCategory>(i)).release());
    519 
    520   ReturnResults("PerformanceMonitor.getMetricTypesCallback", &results);
    521 }
    522 
    523 void PerformanceMonitorHandler::HandleGetMetrics(const ListValue* args) {
    524   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    525   CHECK_EQ(5u, args->GetSize());
    526 
    527   const ListValue* metric_type_list;
    528   CHECK(args->GetList(0, &metric_type_list));
    529   std::set<MetricType> metric_types;
    530   for (ListValue::const_iterator iter = metric_type_list->begin();
    531        iter != metric_type_list->end(); ++iter) {
    532     double metric_type_double = 0.0;
    533     CHECK((*iter)->GetAsDouble(&metric_type_double));
    534     CHECK(metric_type_double < METRIC_NUMBER_OF_METRICS &&
    535           metric_type_double > METRIC_UNDEFINED);
    536     metric_types.insert(
    537         static_cast<MetricType>(static_cast<int>(metric_type_double)));
    538   }
    539 
    540   double time_double = 0.0;
    541   CHECK(args->GetDouble(1, &time_double));
    542   base::Time start = base::Time::FromJsTime(time_double);
    543   CHECK(args->GetDouble(2, &time_double));
    544   base::Time end = base::Time::FromJsTime(time_double);
    545 
    546   double resolution_in_milliseconds = 0.0;
    547   CHECK(args->GetDouble(3, &resolution_in_milliseconds));
    548   base::TimeDelta resolution =
    549       base::TimeDelta::FromMilliseconds(resolution_in_milliseconds);
    550 
    551   double aggregation_double = 0.0;
    552   CHECK(args->GetDouble(4, &aggregation_double));
    553   CHECK(aggregation_double < AGGREGATION_METHOD_NUMBER_OF_METHODS &&
    554         aggregation_double >= 0);
    555   AggregationMethod aggregation_method =
    556       static_cast<AggregationMethod>(static_cast<int>(aggregation_double));
    557 
    558   ListValue* results = new ListValue();
    559   util::PostTaskToDatabaseThreadAndReply(
    560       FROM_HERE,
    561       base::Bind(&DoGetMetrics, results, metric_types,
    562                  start, end, resolution, aggregation_method),
    563       base::Bind(&PerformanceMonitorHandler::ReturnResults, AsWeakPtr(),
    564                  "PerformanceMonitor.getMetricsCallback",
    565                  base::Owned(results)));
    566 }
    567 
    568 }  // namespace performance_monitor
    569