Trace-based benchmarking via a mojo app.

This patch adds `benchmark.mojo` app for trace-based benchmarking and a
runner script.

$ mojo/devtools/common/mojo_benchmark mojo/tools/data/benchmarks
[Trace me]
measurement: time_until/trace_me/DoWork 4488.810000
measurement: avg_duration/trace_me/DoWork 300.449714
[Spinning cube]
measurement: time_until/gpu/GpuScheduler:PutChanged 4341.874000

Fixes #371.

R=etiennej@chromium.org, jamesr@chromium.org

Review URL: https://codereview.chromium.org/1305193002 .
diff --git a/apps/benchmark/event.cc b/apps/benchmark/event.cc
new file mode 100644
index 0000000..6c52848
--- /dev/null
+++ b/apps/benchmark/event.cc
@@ -0,0 +1,69 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "apps/benchmark/event.h"
+
+#include "base/json/json_reader.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/values.h"
+
+namespace benchmark {
+
+Event::Event() {}
+
+Event::Event(std::string name,
+             std::string category,
+             base::TimeTicks timestamp,
+             base::TimeDelta duration)
+    : name(name),
+      category(category),
+      timestamp(timestamp),
+      duration(duration) {}
+
+Event::~Event() {}
+
+bool GetEvents(const std::string& trace_json, std::vector<Event>* result) {
+  result->clear();
+
+  // Parse the JSON string describing the events.
+  base::JSONReader reader;
+  scoped_ptr<base::Value> trace_data = reader.ReadToValue(trace_json);
+  if (!trace_data) {
+    return false;
+  }
+
+  base::ListValue* event_list;
+  if (!trace_data->GetAsList(&event_list))
+    return false;
+
+  for (base::Value* val : *event_list) {
+    Event event;
+    base::DictionaryValue* dict;
+    if (!val->GetAsDictionary(&dict))
+      return false;
+
+    if (!dict->GetString("name", &event.name))
+      return false;
+
+    if (!dict->GetString("cat", &event.category))
+      return false;
+
+    double timestamp;
+    if (!dict->GetDouble("ts", &timestamp))
+      return false;
+    event.timestamp = base::TimeTicks::FromInternalValue(timestamp);
+
+    // It is valid for an event to not have duration.
+    double duration;
+    if (!dict->GetDouble("dur", &duration)) {
+      event.duration = base::TimeDelta();
+    } else {
+      event.duration = base::TimeDelta::FromInternalValue(duration);
+    }
+
+    result->push_back(event);
+  }
+  return true;
+}
+}  // namespace benchmark