Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / renderer / gpu / gpu_benchmarking_extension.cc
index a2e948d..f57a9a7 100644 (file)
 #include "content/common/input/synthetic_tap_gesture_params.h"
 #include "content/public/renderer/render_thread.h"
 #include "content/public/renderer/v8_value_converter.h"
+#include "content/renderer/chrome_object_extensions_utils.h"
 #include "content/renderer/gpu/render_widget_compositor.h"
 #include "content/renderer/render_thread_impl.h"
 #include "content/renderer/render_view_impl.h"
 #include "content/renderer/skia_benchmarking_extension.h"
+#include "gin/arguments.h"
+#include "gin/handle.h"
+#include "gin/object_template_builder.h"
 #include "third_party/WebKit/public/web/WebImageCache.h"
+#include "third_party/WebKit/public/web/WebKit.h"
 #include "third_party/WebKit/public/web/WebLocalFrame.h"
 #include "third_party/WebKit/public/web/WebView.h"
 #include "third_party/skia/include/core/SkData.h"
@@ -40,26 +45,26 @@ using blink::WebPrivatePtr;
 using blink::WebSize;
 using blink::WebView;
 
-const char kGpuBenchmarkingExtensionName[] = "v8/GpuBenchmarking";
+namespace content {
+
+namespace {
 
 // offset parameter is deprecated/ignored, and will be remove from the
 // signature in a future skia release. <reed@google.com>
-static SkData* EncodeBitmapToData(size_t* offset, const SkBitmap& bm) {
-    SkPixelRef* pr = bm.pixelRef();
-    if (pr != NULL) {
-        SkData* data = pr->refEncodedData();
-        if (data != NULL)
-            return data;
-    }
-    std::vector<unsigned char> vector;
-    if (gfx::PNGCodec::EncodeBGRASkBitmap(bm, false, &vector)) {
-        return SkData::NewWithCopy(&vector.front() , vector.size());
-    }
-    return NULL;
+SkData* EncodeBitmapToData(size_t* offset, const SkBitmap& bm) {
+  SkPixelRef* pr = bm.pixelRef();
+  if (pr != NULL) {
+    SkData* data = pr->refEncodedData();
+    if (data != NULL)
+      return data;
+  }
+  std::vector<unsigned char> vector;
+  if (gfx::PNGCodec::EncodeBGRASkBitmap(bm, false, &vector)) {
+    return SkData::NewWithCopy(&vector.front(), vector.size());
+  }
+  return NULL;
 }
 
-namespace {
-
 class SkPictureSerializer {
  public:
   explicit SkPictureSerializer(const base::FilePath& dirpath)
@@ -67,7 +72,7 @@ class SkPictureSerializer {
         layer_id_(0) {
     // Let skia register known effect subclasses. This basically enables
     // reflection on those subclasses required for picture serialization.
-    content::SkiaBenchmarking::Initialize();
+    SkiaBenchmarking::Initialize();
   }
 
   // Recursively serializes the layer tree.
@@ -100,11 +105,33 @@ class SkPictureSerializer {
   int layer_id_;
 };
 
-}  // namespace
+template <typename T>
+bool GetArg(gin::Arguments* args, T* value) {
+  if (!args->GetNext(value)) {
+    args->ThrowError();
+    return false;
+  }
+  return true;
+}
 
-namespace content {
+template <>
+bool GetArg(gin::Arguments* args, int* value) {
+  float number;
+  bool ret = GetArg(args, &number);
+  *value = number;
+  return ret;
+}
 
-namespace {
+template <typename T>
+bool GetOptionalArg(gin::Arguments* args, T* value) {
+  if (args->PeekNext().IsEmpty())
+    return true;
+  if (args->PeekNext()->IsUndefined()) {
+    args->Skip();
+    return true;
+  }
+  return GetArg(args, value);
+}
 
 class CallbackAndContext : public base::RefCounted<CallbackAndContext> {
  public:
@@ -208,720 +235,576 @@ class GpuBenchmarkingContext {
   DISALLOW_COPY_AND_ASSIGN(GpuBenchmarkingContext);
 };
 
-}  // namespace
+void OnMicroBenchmarkCompleted(
+    CallbackAndContext* callback_and_context,
+    scoped_ptr<base::Value> result) {
+  v8::Isolate* isolate = callback_and_context->isolate();
+  v8::HandleScope scope(isolate);
+  v8::Handle<v8::Context> context = callback_and_context->GetContext();
+  v8::Context::Scope context_scope(context);
+  WebLocalFrame* frame = WebLocalFrame::frameForContext(context);
+  if (frame) {
+    scoped_ptr<V8ValueConverter> converter =
+        make_scoped_ptr(V8ValueConverter::create());
+    v8::Handle<v8::Value> value = converter->ToV8Value(result.get(), context);
+    v8::Handle<v8::Value> argv[] = { value };
+
+    frame->callFunctionEvenIfScriptDisabled(
+        callback_and_context->GetCallback(),
+        v8::Object::New(isolate),
+        1,
+        argv);
+  }
+}
 
-class GpuBenchmarkingWrapper : public v8::Extension {
- public:
-  GpuBenchmarkingWrapper() :
-      v8::Extension(kGpuBenchmarkingExtensionName,
-            "if (typeof(chrome) == 'undefined') {"
-            "  chrome = {};"
-            "};"
-            "if (typeof(chrome.gpuBenchmarking) == 'undefined') {"
-            "  chrome.gpuBenchmarking = {};"
-            "};"
-            "chrome.gpuBenchmarking.setNeedsDisplayOnAllLayers = function() {"
-            "  native function SetNeedsDisplayOnAllLayers();"
-            "  return SetNeedsDisplayOnAllLayers();"
-            "};"
-            "chrome.gpuBenchmarking.setRasterizeOnlyVisibleContent = "
-            "function() {"
-            "  native function SetRasterizeOnlyVisibleContent();"
-            "  return SetRasterizeOnlyVisibleContent();"
-            "};"
-            "chrome.gpuBenchmarking.printToSkPicture = function(dirname) {"
-            "  native function PrintToSkPicture();"
-            "  return PrintToSkPicture(dirname);"
-            "};"
-            "chrome.gpuBenchmarking.DEFAULT_INPUT = 0;"
-            "chrome.gpuBenchmarking.TOUCH_INPUT = 1;"
-            "chrome.gpuBenchmarking.MOUSE_INPUT = 2;"
-            "chrome.gpuBenchmarking.gestureSourceTypeSupported = "
-            "    function(gesture_source_type) {"
-            "  native function GestureSourceTypeSupported();"
-            "  return GestureSourceTypeSupported(gesture_source_type);"
-            "};"
-            "chrome.gpuBenchmarking.smoothScrollBy = "
-            "    function(pixels_to_scroll, opt_callback, opt_start_x,"
-            "             opt_start_y, opt_gesture_source_type,"
-            "             opt_direction, opt_speed_in_pixels_s) {"
-            "  pixels_to_scroll = pixels_to_scroll || 0;"
-            "  callback = opt_callback || function() { };"
-            "  gesture_source_type = opt_gesture_source_type ||"
-            "      chrome.gpuBenchmarking.DEFAULT_INPUT;"
-            "  direction = opt_direction || 'down';"
-            "  speed_in_pixels_s = opt_speed_in_pixels_s || 800;"
-            "  native function BeginSmoothScroll();"
-            "  return BeginSmoothScroll(pixels_to_scroll, callback,"
-            "                           gesture_source_type, direction,"
-            "                           speed_in_pixels_s, true,"
-            "                           opt_start_x, opt_start_y);"
-            "};"
-            "chrome.gpuBenchmarking.swipe = "
-            "    function(direction, distance, opt_callback,"
-            "             opt_start_x, opt_start_y,"
-            "             opt_speed_in_pixels_s) {"
-            "  direction = direction || 'up';"
-            "  distance = distance || 0;"
-            "  callback = opt_callback || function() { };"
-            "  speed_in_pixels_s = opt_speed_in_pixels_s || 800;"
-            "  native function BeginSmoothScroll();"
-            "  return BeginSmoothScroll(-distance, callback,"
-            "                           chrome.gpuBenchmarking.TOUCH_INPUT,"
-            "                           direction, speed_in_pixels_s, false,"
-            "                           opt_start_x, opt_start_y);"
-            "};"
-            "chrome.gpuBenchmarking.scrollBounce = "
-            "    function(direction, distance, overscroll, opt_repeat_count,"
-            "             opt_callback, opt_start_x, opt_start_y,"
-            "             opt_speed_in_pixels_s) {"
-            "  direction = direction || 'down';"
-            "  distance = distance || 0;"
-            "  overscroll = overscroll || 0;"
-            "  repeat_count = opt_repeat_count || 1;"
-            "  callback = opt_callback || function() { };"
-            "  speed_in_pixels_s = opt_speed_in_pixels_s || 800;"
-            "  native function BeginScrollBounce();"
-            "  return BeginScrollBounce(direction, distance, overscroll,"
-            "                           repeat_count, callback,"
-            "                           speed_in_pixels_s,"
-            "                           opt_start_x, opt_start_y);"
-            "};"
-            // TODO(dominikg): Remove once JS interface changes have rolled into
-            //                 stable.
-            "chrome.gpuBenchmarking.newPinchInterface = true;"
-            "chrome.gpuBenchmarking.pinchBy = "
-            "    function(scale_factor, anchor_x, anchor_y,"
-            "             opt_callback, "
-            "opt_relative_pointer_speed_in_pixels_s) {"
-            "  callback = opt_callback || function() { };"
-            "  relative_pointer_speed_in_pixels_s ="
-            "      opt_relative_pointer_speed_in_pixels_s || 800;"
-            "  native function BeginPinch();"
-            "  return BeginPinch(scale_factor, anchor_x, anchor_y, callback,"
-            "                    relative_pointer_speed_in_pixels_s);"
-            "};"
-            "chrome.gpuBenchmarking.tap = "
-            "    function(position_x, position_y, opt_callback, "
-            "opt_duration_ms,"
-            "             opt_gesture_source_type) {"
-            "  callback = opt_callback || function() { };"
-            "  duration_ms = opt_duration_ms || 50;"
-            "  gesture_source_type = opt_gesture_source_type ||"
-            "      chrome.gpuBenchmarking.DEFAULT_INPUT;"
-            "  native function BeginTap();"
-            "  return BeginTap(position_x, position_y, callback, duration_ms,"
-            "                  gesture_source_type);"
-            "};"
-            "chrome.gpuBenchmarking.beginWindowSnapshotPNG = "
-            "function(callback) {"
-            "  native function BeginWindowSnapshotPNG();"
-            "  BeginWindowSnapshotPNG(callback);"
-            "};"
-            "chrome.gpuBenchmarking.clearImageCache = function() {"
-            "  native function ClearImageCache();"
-            "  ClearImageCache();"
-            "};"
-            "chrome.gpuBenchmarking.runMicroBenchmark ="
-            "    function(name, callback, opt_arguments) {"
-            "  arguments = opt_arguments || {};"
-            "  native function RunMicroBenchmark();"
-            "  return RunMicroBenchmark(name, callback, arguments);"
-            "};"
-            "chrome.gpuBenchmarking.sendMessageToMicroBenchmark ="
-            "    function(id, arguments) {"
-            "  native function SendMessageToMicroBenchmark();"
-            "  return SendMessageToMicroBenchmark(id, arguments);"
-            "};"
-            "chrome.gpuBenchmarking.hasGpuProcess = function() {"
-            "  native function HasGpuProcess();"
-            "  return HasGpuProcess();"
-            "};") {}
-
-  virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
-      v8::Isolate* isolate,
-      v8::Handle<v8::String> name) OVERRIDE {
-    if (name->Equals(
-            v8::String::NewFromUtf8(isolate, "SetNeedsDisplayOnAllLayers")))
-      return v8::FunctionTemplate::New(isolate, SetNeedsDisplayOnAllLayers);
-    if (name->Equals(
-            v8::String::NewFromUtf8(isolate, "SetRasterizeOnlyVisibleContent")))
-      return v8::FunctionTemplate::New(isolate, SetRasterizeOnlyVisibleContent);
-    if (name->Equals(v8::String::NewFromUtf8(isolate, "PrintToSkPicture")))
-      return v8::FunctionTemplate::New(isolate, PrintToSkPicture);
-    if (name->Equals(
-            v8::String::NewFromUtf8(isolate, "GestureSourceTypeSupported")))
-      return v8::FunctionTemplate::New(isolate, GestureSourceTypeSupported);
-    if (name->Equals(v8::String::NewFromUtf8(isolate, "BeginSmoothScroll")))
-      return v8::FunctionTemplate::New(isolate, BeginSmoothScroll);
-    if (name->Equals(v8::String::NewFromUtf8(isolate, "BeginScrollBounce")))
-      return v8::FunctionTemplate::New(isolate, BeginScrollBounce);
-    if (name->Equals(v8::String::NewFromUtf8(isolate, "BeginPinch")))
-      return v8::FunctionTemplate::New(isolate, BeginPinch);
-    if (name->Equals(v8::String::NewFromUtf8(isolate, "BeginTap")))
-      return v8::FunctionTemplate::New(isolate, BeginTap);
-    if (name->Equals(
-            v8::String::NewFromUtf8(isolate, "BeginWindowSnapshotPNG")))
-      return v8::FunctionTemplate::New(isolate, BeginWindowSnapshotPNG);
-    if (name->Equals(v8::String::NewFromUtf8(isolate, "ClearImageCache")))
-      return v8::FunctionTemplate::New(isolate, ClearImageCache);
-    if (name->Equals(v8::String::NewFromUtf8(isolate, "RunMicroBenchmark")))
-      return v8::FunctionTemplate::New(isolate, RunMicroBenchmark);
-    if (name->Equals(
-            v8::String::NewFromUtf8(isolate, "SendMessageToMicroBenchmark")))
-      return v8::FunctionTemplate::New(isolate, SendMessageToMicroBenchmark);
-    if (name->Equals(v8::String::NewFromUtf8(isolate, "HasGpuProcess")))
-      return v8::FunctionTemplate::New(isolate, HasGpuProcess);
-
-    return v8::Handle<v8::FunctionTemplate>();
-  }
-
-  static void SetNeedsDisplayOnAllLayers(
-      const v8::FunctionCallbackInfo<v8::Value>& args) {
-    GpuBenchmarkingContext context;
-    if (!context.Init(true))
-      return;
+void OnSnapshotCompleted(CallbackAndContext* callback_and_context,
+                         const gfx::Size& size,
+                         const std::vector<unsigned char>& png) {
+  v8::Isolate* isolate = callback_and_context->isolate();
+  v8::HandleScope scope(isolate);
+  v8::Handle<v8::Context> context = callback_and_context->GetContext();
+  v8::Context::Scope context_scope(context);
+  WebLocalFrame* frame = WebLocalFrame::frameForContext(context);
+  if (frame) {
+    v8::Handle<v8::Value> result;
+
+    if (!size.IsEmpty()) {
+      v8::Handle<v8::Object> result_object;
+      result_object = v8::Object::New(isolate);
+
+      result_object->Set(v8::String::NewFromUtf8(isolate, "width"),
+                         v8::Number::New(isolate, size.width()));
+      result_object->Set(v8::String::NewFromUtf8(isolate, "height"),
+                         v8::Number::New(isolate, size.height()));
+
+      std::string base64_png;
+      base::Base64Encode(
+          base::StringPiece(reinterpret_cast<const char*>(&*png.begin()),
+                            png.size()),
+          &base64_png);
+
+      result_object->Set(v8::String::NewFromUtf8(isolate, "data"),
+                         v8::String::NewFromUtf8(isolate,
+                                                 base64_png.c_str(),
+                                                 v8::String::kNormalString,
+                                                 base64_png.size()));
+
+      result = result_object;
+    } else {
+      result = v8::Null(isolate);
+    }
 
-    context.compositor()->SetNeedsDisplayOnAllLayers();
+    v8::Handle<v8::Value> argv[] = {result};
+
+    frame->callFunctionEvenIfScriptDisabled(
+        callback_and_context->GetCallback(), v8::Object::New(isolate), 1, argv);
   }
+}
 
-  static void SetRasterizeOnlyVisibleContent(
-      const v8::FunctionCallbackInfo<v8::Value>& args) {
-    GpuBenchmarkingContext context;
-    if (!context.Init(true))
-      return;
+void OnSyntheticGestureCompleted(CallbackAndContext* callback_and_context) {
+  v8::Isolate* isolate = callback_and_context->isolate();
+  v8::HandleScope scope(isolate);
+  v8::Handle<v8::Context> context = callback_and_context->GetContext();
+  v8::Context::Scope context_scope(context);
+  WebLocalFrame* frame = WebLocalFrame::frameForContext(context);
+  if (frame) {
+    frame->callFunctionEvenIfScriptDisabled(
+        callback_and_context->GetCallback(), v8::Object::New(isolate), 0, NULL);
+  }
+}
 
-    context.compositor()->SetRasterizeOnlyVisibleContent();
+bool BeginSmoothScroll(v8::Isolate* isolate,
+                       int pixels_to_scroll,
+                       v8::Handle<v8::Function> callback,
+                       int gesture_source_type,
+                       const std::string& direction,
+                       int speed_in_pixels_s,
+                       bool prevent_fling,
+                       int start_x,
+                       int start_y) {
+  GpuBenchmarkingContext context;
+  if (!context.Init(false))
+    return false;
+
+  scoped_refptr<CallbackAndContext> callback_and_context =
+      new CallbackAndContext(
+          isolate, callback, context.web_frame()->mainWorldScriptContext());
+
+  scoped_ptr<SyntheticSmoothScrollGestureParams> gesture_params(
+      new SyntheticSmoothScrollGestureParams);
+
+  // Convert coordinates from CSS pixels to density independent pixels (DIPs).
+  float page_scale_factor = context.web_view()->pageScaleFactor();
+
+  if (gesture_source_type < 0 ||
+      gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
+    return false;
+  }
+  gesture_params->gesture_source_type =
+      static_cast<SyntheticGestureParams::GestureSourceType>(
+          gesture_source_type);
+
+  gesture_params->speed_in_pixels_s = speed_in_pixels_s;
+  gesture_params->prevent_fling = prevent_fling;
+
+  gesture_params->anchor.SetPoint(start_x * page_scale_factor,
+                                  start_y * page_scale_factor);
+
+  int distance_length = pixels_to_scroll * page_scale_factor;
+  gfx::Vector2d distance;
+  if (direction == "down")
+    distance.set_y(-distance_length);
+  else if (direction == "up")
+    distance.set_y(distance_length);
+  else if (direction == "right")
+    distance.set_x(-distance_length);
+  else if (direction == "left")
+    distance.set_x(distance_length);
+  else {
+    return false;
   }
+  gesture_params->distances.push_back(distance);
 
-  static void PrintToSkPicture(
-      const v8::FunctionCallbackInfo<v8::Value>& args) {
-    if (args.Length() != 1)
-      return;
+  // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
+  // progress, we will leak the callback and context. This needs to be fixed,
+  // somehow.
+  context.render_view_impl()->QueueSyntheticGesture(
+      gesture_params.Pass(),
+      base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
 
-    v8::String::Utf8Value dirname(args[0]);
-    if (dirname.length() == 0)
-      return;
+  return true;
+}
 
-    GpuBenchmarkingContext context;
-    if (!context.Init(true))
-      return;
+}  // namespace
 
-    const cc::Layer* root_layer = context.compositor()->GetRootLayer();
-    if (!root_layer)
-      return;
+gin::WrapperInfo GpuBenchmarking::kWrapperInfo = {gin::kEmbedderNativeGin};
 
-    base::FilePath dirpath(
-        base::FilePath::StringType(*dirname, *dirname + dirname.length()));
-    if (!base::CreateDirectory(dirpath) ||
-        !base::PathIsWritable(dirpath)) {
-      std::string msg("Path is not writable: ");
-      msg.append(dirpath.MaybeAsASCII());
-      v8::Isolate* isolate = args.GetIsolate();
-      isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(
-          isolate, msg.c_str(), v8::String::kNormalString, msg.length())));
-      return;
-    }
+// static
+void GpuBenchmarking::Install(blink::WebFrame* frame) {
+  v8::Isolate* isolate = blink::mainThreadIsolate();
+  v8::HandleScope handle_scope(isolate);
+  v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
+  if (context.IsEmpty())
+    return;
 
-    SkPictureSerializer serializer(dirpath);
-    serializer.Serialize(root_layer);
-  }
-
-  static void OnSyntheticGestureCompleted(
-      CallbackAndContext* callback_and_context) {
-    v8::Isolate* isolate = callback_and_context->isolate();
-    v8::HandleScope scope(isolate);
-    v8::Handle<v8::Context> context = callback_and_context->GetContext();
-    v8::Context::Scope context_scope(context);
-    WebLocalFrame* frame = WebLocalFrame::frameForContext(context);
-    if (frame) {
-      frame->callFunctionEvenIfScriptDisabled(
-          callback_and_context->GetCallback(),
-          v8::Object::New(isolate),
-          0,
-          NULL);
-    }
-  }
+  v8::Context::Scope context_scope(context);
 
-  static void GestureSourceTypeSupported(
-      const v8::FunctionCallbackInfo<v8::Value>& args) {
-    if (args.Length() != 1 || !args[0]->IsNumber()) {
-      args.GetReturnValue().Set(false);
-      return;
-    }
+  gin::Handle<GpuBenchmarking> controller =
+      gin::CreateHandle(isolate, new GpuBenchmarking());
+  if (controller.IsEmpty())
+    return;
 
-    int gesture_source_type = args[0]->IntegerValue();
-    if (gesture_source_type < 0 ||
-        gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
-      args.GetReturnValue().Set(false);
-      return;
-    }
+  v8::Handle<v8::Object> chrome = GetOrCreateChromeObject(isolate,
+                                                          context->Global());
+  chrome->Set(gin::StringToV8(isolate, "gpuBenchmarking"), controller.ToV8());
+}
 
-    bool is_supported = SyntheticGestureParams::IsGestureSourceTypeSupported(
-        static_cast<SyntheticGestureParams::GestureSourceType>(
-            gesture_source_type));
-    args.GetReturnValue().Set(is_supported);
-  }
+GpuBenchmarking::GpuBenchmarking() {
+}
 
-  static void BeginSmoothScroll(
-      const v8::FunctionCallbackInfo<v8::Value>& args) {
-    GpuBenchmarkingContext context;
-    if (!context.Init(false))
-      return;
+GpuBenchmarking::~GpuBenchmarking() {
+}
 
-    // The last two arguments can be undefined. We check their validity later.
-    int arglen = args.Length();
-    if (arglen < 8 ||
-        !args[0]->IsNumber() ||
-        !args[1]->IsFunction() ||
-        !args[2]->IsNumber() ||
-        !args[3]->IsString() ||
-        !args[4]->IsNumber() ||
-        !args[5]->IsBoolean()) {
-      args.GetReturnValue().Set(false);
-      return;
-    }
+gin::ObjectTemplateBuilder GpuBenchmarking::GetObjectTemplateBuilder(
+    v8::Isolate* isolate) {
+  return gin::Wrappable<GpuBenchmarking>::GetObjectTemplateBuilder(isolate)
+      .SetMethod("setNeedsDisplayOnAllLayers",
+                 &GpuBenchmarking::SetNeedsDisplayOnAllLayers)
+      .SetMethod("setRasterizeOnlyVisibleContent",
+                 &GpuBenchmarking::SetRasterizeOnlyVisibleContent)
+      .SetMethod("printToSkPicture", &GpuBenchmarking::PrintToSkPicture)
+      .SetValue("DEFAULT_INPUT", 0)
+      .SetValue("TOUCH_INPUT", 1)
+      .SetValue("MOUSE_INPUT", 2)
+      .SetMethod("gestureSourceTypeSupported",
+                 &GpuBenchmarking::GestureSourceTypeSupported)
+      .SetMethod("smoothScrollBy", &GpuBenchmarking::SmoothScrollBy)
+      .SetMethod("swipe", &GpuBenchmarking::Swipe)
+      .SetMethod("scrollBounce", &GpuBenchmarking::ScrollBounce)
+      // TODO(dominikg): Remove once JS interface changes have rolled into
+      //                 stable.
+      .SetValue("newPinchInterface", true)
+      .SetMethod("pinchBy", &GpuBenchmarking::PinchBy)
+      .SetMethod("tap", &GpuBenchmarking::Tap)
+      .SetMethod("beginWindowSnapshotPNG",
+                 &GpuBenchmarking::BeginWindowSnapshotPNG)
+      .SetMethod("clearImageCache", &GpuBenchmarking::ClearImageCache)
+      .SetMethod("runMicroBenchmark", &GpuBenchmarking::RunMicroBenchmark)
+      .SetMethod("sendMessageToMicroBenchmark",
+                 &GpuBenchmarking::SendMessageToMicroBenchmark)
+      .SetMethod("hasGpuProcess", &GpuBenchmarking::HasGpuProcess);
+}
 
-    v8::Local<v8::Function> callback_local =
-        v8::Local<v8::Function>::Cast(args[1]);
+void GpuBenchmarking::SetNeedsDisplayOnAllLayers() {
+  GpuBenchmarkingContext context;
+  if (!context.Init(true))
+    return;
 
-    scoped_refptr<CallbackAndContext> callback_and_context =
-        new CallbackAndContext(args.GetIsolate(),
-                               callback_local,
-                               context.web_frame()->mainWorldScriptContext());
+  context.compositor()->SetNeedsDisplayOnAllLayers();
+}
 
-    scoped_ptr<SyntheticSmoothScrollGestureParams> gesture_params(
-        new SyntheticSmoothScrollGestureParams);
+void GpuBenchmarking::SetRasterizeOnlyVisibleContent() {
+  GpuBenchmarkingContext context;
+  if (!context.Init(true))
+    return;
 
-    // Convert coordinates from CSS pixels to density independent pixels (DIPs).
-    float page_scale_factor = context.web_view()->pageScaleFactor();
+  context.compositor()->SetRasterizeOnlyVisibleContent();
+}
 
-    int gesture_source_type = args[2]->IntegerValue();
-    if (gesture_source_type < 0 ||
-        gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
-      args.GetReturnValue().Set(false);
-      return;
-    }
-    gesture_params->gesture_source_type =
-        static_cast<SyntheticGestureParams::GestureSourceType>(
-            gesture_source_type);
-
-    gesture_params->speed_in_pixels_s = args[4]->IntegerValue();
-    gesture_params->prevent_fling = args[5]->BooleanValue();
-
-    // Account for the 2 optional arguments, start_x and start_y.
-    gfx::Point anchor;
-    if (args[6]->IsUndefined() || args[7]->IsUndefined()) {
-      blink::WebRect rect = context.render_view_impl()->windowRect();
-      anchor.SetPoint(rect.width / 2, rect.height / 2);
-    } else if (args[6]->IsNumber() && args[7]->IsNumber()) {
-      anchor.SetPoint(args[6]->IntegerValue() * page_scale_factor,
-                      args[7]->IntegerValue() * page_scale_factor);
-    } else {
-      args.GetReturnValue().Set(false);
-      return;
-    }
-    gesture_params->anchor = anchor;
-
-    int distance_length = args[0]->IntegerValue() * page_scale_factor;
-    gfx::Vector2d distance;
-    v8::String::Utf8Value direction(args[3]);
-    DCHECK(*direction);
-    std::string direction_str(*direction);
-    if (direction_str == "down")
-      distance.set_y(-distance_length);
-    else if (direction_str == "up")
-      distance.set_y(distance_length);
-    else if (direction_str == "right")
-      distance.set_x(-distance_length);
-    else if (direction_str == "left")
-      distance.set_x(distance_length);
-    else {
-      args.GetReturnValue().Set(false);
-      return;
-    }
-    gesture_params->distances.push_back(distance);
+void GpuBenchmarking::PrintToSkPicture(v8::Isolate* isolate,
+                                       const std::string& dirname) {
+  GpuBenchmarkingContext context;
+  if (!context.Init(true))
+    return;
+
+  const cc::Layer* root_layer = context.compositor()->GetRootLayer();
+  if (!root_layer)
+    return;
+
+  base::FilePath dirpath = base::FilePath::FromUTF8Unsafe(dirname);
+  if (!base::CreateDirectory(dirpath) ||
+      !base::PathIsWritable(dirpath)) {
+    std::string msg("Path is not writable: ");
+    msg.append(dirpath.MaybeAsASCII());
+    isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(
+        isolate, msg.c_str(), v8::String::kNormalString, msg.length())));
+    return;
+  }
 
-    // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
-    // progress, we will leak the callback and context. This needs to be fixed,
-    // somehow.
-    context.render_view_impl()->QueueSyntheticGesture(
-        gesture_params.PassAs<SyntheticGestureParams>(),
-        base::Bind(&OnSyntheticGestureCompleted,
-                   callback_and_context));
+  SkPictureSerializer serializer(dirpath);
+  serializer.Serialize(root_layer);
+}
 
-    args.GetReturnValue().Set(true);
+bool GpuBenchmarking::GestureSourceTypeSupported(int gesture_source_type) {
+  if (gesture_source_type < 0 ||
+      gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
+    return false;
   }
 
-  static void BeginScrollBounce(
-      const v8::FunctionCallbackInfo<v8::Value>& args) {
-    GpuBenchmarkingContext context;
-    if (!context.Init(false))
-      return;
+  return SyntheticGestureParams::IsGestureSourceTypeSupported(
+      static_cast<SyntheticGestureParams::GestureSourceType>(
+          gesture_source_type));
+}
 
-    // The last two arguments can be undefined. We check their validity later.
-    int arglen = args.Length();
-    if (arglen < 8 ||
-        !args[0]->IsString() ||
-        !args[1]->IsNumber() ||
-        !args[2]->IsNumber() ||
-        !args[3]->IsNumber() ||
-        !args[4]->IsFunction() ||
-        !args[5]->IsNumber()) {
-      args.GetReturnValue().Set(false);
-      return;
-    }
+bool GpuBenchmarking::SmoothScrollBy(gin::Arguments* args) {
+  GpuBenchmarkingContext context;
+  if (!context.Init(true))
+    return false;
+
+  float page_scale_factor = context.web_view()->pageScaleFactor();
+  blink::WebRect rect = context.render_view_impl()->windowRect();
+
+  int pixels_to_scroll = 0;
+  v8::Handle<v8::Function> callback;
+  int start_x = rect.width / (page_scale_factor * 2);
+  int start_y = rect.height / (page_scale_factor * 2);
+  int gesture_source_type = 0;  // DEFAULT_INPUT
+  std::string direction = "down";
+  int speed_in_pixels_s = 800;
+
+  if (!GetOptionalArg(args, &pixels_to_scroll) ||
+      !GetOptionalArg(args, &callback) ||
+      !GetOptionalArg(args, &start_x) ||
+      !GetOptionalArg(args, &start_y) ||
+      !GetOptionalArg(args, &gesture_source_type) ||
+      !GetOptionalArg(args, &direction) ||
+      !GetOptionalArg(args, &speed_in_pixels_s)) {
+    return false;
+  }
 
-    v8::Local<v8::Function> callback_local =
-        v8::Local<v8::Function>::Cast(args[4]);
+  return BeginSmoothScroll(args->isolate(),
+                           pixels_to_scroll,
+                           callback,
+                           gesture_source_type,
+                           direction,
+                           speed_in_pixels_s,
+                           true,
+                           start_x,
+                           start_y);
+}
 
-    scoped_refptr<CallbackAndContext> callback_and_context =
-        new CallbackAndContext(args.GetIsolate(),
-                               callback_local,
-                               context.web_frame()->mainWorldScriptContext());
+bool GpuBenchmarking::Swipe(gin::Arguments* args) {
+  GpuBenchmarkingContext context;
+  if (!context.Init(true))
+    return false;
+
+  float page_scale_factor = context.web_view()->pageScaleFactor();
+  blink::WebRect rect = context.render_view_impl()->windowRect();
+
+  std::string direction = "up";
+  int pixels_to_scroll = 0;
+  v8::Handle<v8::Function> callback;
+  int start_x = rect.width / (page_scale_factor * 2);
+  int start_y = rect.height / (page_scale_factor * 2);
+  int speed_in_pixels_s = 800;
+
+  if (!GetOptionalArg(args, &direction) ||
+      !GetOptionalArg(args, &pixels_to_scroll) ||
+      !GetOptionalArg(args, &callback) ||
+      !GetOptionalArg(args, &start_x) ||
+      !GetOptionalArg(args, &start_y) ||
+      !GetOptionalArg(args, &speed_in_pixels_s)) {
+    return false;
+  }
 
-    scoped_ptr<SyntheticSmoothScrollGestureParams> gesture_params(
-        new SyntheticSmoothScrollGestureParams);
+  return BeginSmoothScroll(args->isolate(),
+                           -pixels_to_scroll,
+                           callback,
+                           1,  // TOUCH_INPUT
+                           direction,
+                           speed_in_pixels_s,
+                           false,
+                           start_x,
+                           start_y);
+}
 
-    // Convert coordinates from CSS pixels to density independent pixels (DIPs).
-    float page_scale_factor = context.web_view()->pageScaleFactor();
+bool GpuBenchmarking::ScrollBounce(gin::Arguments* args) {
+  GpuBenchmarkingContext context;
+  if (!context.Init(false))
+    return false;
+
+  float page_scale_factor = context.web_view()->pageScaleFactor();
+  blink::WebRect rect = context.render_view_impl()->windowRect();
+
+  std::string direction = "down";
+  int distance_length = 0;
+  int overscroll_length = 0;
+  int repeat_count = 1;
+  v8::Handle<v8::Function> callback;
+  int start_x = rect.width / (page_scale_factor * 2);
+  int start_y = rect.height / (page_scale_factor * 2);
+  int speed_in_pixels_s = 800;
+
+  if (!GetOptionalArg(args, &direction) ||
+      !GetOptionalArg(args, &distance_length) ||
+      !GetOptionalArg(args, &overscroll_length) ||
+      !GetOptionalArg(args, &repeat_count) ||
+      !GetOptionalArg(args, &callback) ||
+      !GetOptionalArg(args, &start_x) ||
+      !GetOptionalArg(args, &start_y) ||
+      !GetOptionalArg(args, &speed_in_pixels_s)) {
+    return false;
+  }
 
-    gesture_params->speed_in_pixels_s = args[5]->IntegerValue();
+  scoped_refptr<CallbackAndContext> callback_and_context =
+      new CallbackAndContext(args->isolate(),
+                             callback,
+                             context.web_frame()->mainWorldScriptContext());
+
+  scoped_ptr<SyntheticSmoothScrollGestureParams> gesture_params(
+      new SyntheticSmoothScrollGestureParams);
+
+  gesture_params->speed_in_pixels_s = speed_in_pixels_s;
+
+  gesture_params->anchor.SetPoint(start_x * page_scale_factor,
+                                  start_y * page_scale_factor);
+
+  distance_length *= page_scale_factor;
+  overscroll_length *= page_scale_factor;
+  gfx::Vector2d distance;
+  gfx::Vector2d overscroll;
+  if (direction == "down") {
+    distance.set_y(-distance_length);
+    overscroll.set_y(overscroll_length);
+  } else if (direction == "up") {
+    distance.set_y(distance_length);
+    overscroll.set_y(-overscroll_length);
+  } else if (direction == "right") {
+    distance.set_x(-distance_length);
+    overscroll.set_x(overscroll_length);
+  } else if (direction == "left") {
+    distance.set_x(distance_length);
+    overscroll.set_x(-overscroll_length);
+  } else {
+    return false;
+  }
 
-    // Account for the 2 optional arguments, start_x and start_y.
-    gfx::Point start;
-    if (args[6]->IsUndefined() || args[7]->IsUndefined()) {
-      blink::WebRect rect = context.render_view_impl()->windowRect();
-      start.SetPoint(rect.width / 2, rect.height / 2);
-    } else if (args[6]->IsNumber() && args[7]->IsNumber()) {
-      start.SetPoint(args[6]->IntegerValue() * page_scale_factor,
-                     args[7]->IntegerValue() * page_scale_factor);
-    } else {
-      args.GetReturnValue().Set(false);
-      return;
-    }
+  for (int i = 0; i < repeat_count; i++) {
+    gesture_params->distances.push_back(distance);
+    gesture_params->distances.push_back(-distance + overscroll);
+  }
 
-    int distance_length = args[1]->IntegerValue() * page_scale_factor;
-    int overscroll_length = args[2]->IntegerValue() * page_scale_factor;
-    gfx::Vector2d distance;
-    gfx::Vector2d overscroll;
-    v8::String::Utf8Value direction(args[0]);
-    DCHECK(*direction);
-    std::string direction_str(*direction);
-    if (direction_str == "down") {
-      distance.set_y(-distance_length);
-      overscroll.set_y(overscroll_length);
-    }
-    else if (direction_str == "up") {
-      distance.set_y(distance_length);
-      overscroll.set_y(-overscroll_length);
-    }
-    else if (direction_str == "right") {
-      distance.set_x(-distance_length);
-      overscroll.set_x(overscroll_length);
-    }
-    else if (direction_str == "left") {
-      distance.set_x(distance_length);
-      overscroll.set_x(-overscroll_length);
-    }
-    else {
-      args.GetReturnValue().Set(false);
-      return;
-    }
+  // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
+  // progress, we will leak the callback and context. This needs to be fixed,
+  // somehow.
+  context.render_view_impl()->QueueSyntheticGesture(
+      gesture_params.Pass(),
+      base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
 
-    int repeat_count = args[3]->IntegerValue();
-    gesture_params->anchor = start;
-    for (int i = 0; i < repeat_count; i++) {
-      gesture_params->distances.push_back(distance);
-      gesture_params->distances.push_back(-distance + overscroll);
-    }
+  return true;
+}
 
-    // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
-    // progress, we will leak the callback and context. This needs to be fixed,
-    // somehow.
-    context.render_view_impl()->QueueSyntheticGesture(
-        gesture_params.PassAs<SyntheticGestureParams>(),
-        base::Bind(&OnSyntheticGestureCompleted,
-                   callback_and_context));
+bool GpuBenchmarking::PinchBy(gin::Arguments* args) {
+  GpuBenchmarkingContext context;
+  if (!context.Init(false))
+    return false;
 
-    args.GetReturnValue().Set(true);
-  }
+  float scale_factor;
+  int anchor_x;
+  int anchor_y;
+  v8::Handle<v8::Function> callback;
+  int relative_pointer_speed_in_pixels_s = 800;
 
-  static void BeginPinch(
-      const v8::FunctionCallbackInfo<v8::Value>& args) {
-    GpuBenchmarkingContext context;
-    if (!context.Init(false))
-      return;
 
-    int arglen = args.Length();
-    if (arglen < 5 ||
-        !args[0]->IsNumber() ||
-        !args[1]->IsNumber() ||
-        !args[2]->IsNumber() ||
-        !args[3]->IsFunction() ||
-        !args[4]->IsNumber()) {
-      args.GetReturnValue().Set(false);
-      return;
-    }
+  if (!GetArg(args, &scale_factor) ||
+      !GetArg(args, &anchor_x) ||
+      !GetArg(args, &anchor_y) ||
+      !GetOptionalArg(args, &callback) ||
+      !GetOptionalArg(args, &relative_pointer_speed_in_pixels_s)) {
+    return false;
+  }
 
-    scoped_ptr<SyntheticPinchGestureParams> gesture_params(
-        new SyntheticPinchGestureParams);
+  scoped_ptr<SyntheticPinchGestureParams> gesture_params(
+      new SyntheticPinchGestureParams);
 
-    // Convert coordinates from CSS pixels to density independent pixels (DIPs).
-    float page_scale_factor = context.web_view()->pageScaleFactor();
+  // Convert coordinates from CSS pixels to density independent pixels (DIPs).
+  float page_scale_factor = context.web_view()->pageScaleFactor();
 
-    gesture_params->scale_factor = args[0]->NumberValue();
-    gesture_params->anchor.SetPoint(
-        args[1]->IntegerValue() * page_scale_factor,
-        args[2]->IntegerValue() * page_scale_factor);
-    gesture_params->relative_pointer_speed_in_pixels_s =
-        args[4]->IntegerValue();
+  gesture_params->scale_factor = scale_factor;
+  gesture_params->anchor.SetPoint(anchor_x * page_scale_factor,
+                                  anchor_y * page_scale_factor);
+  gesture_params->relative_pointer_speed_in_pixels_s =
+      relative_pointer_speed_in_pixels_s;
 
-    v8::Local<v8::Function> callback_local =
-        v8::Local<v8::Function>::Cast(args[3]);
+  scoped_refptr<CallbackAndContext> callback_and_context =
+      new CallbackAndContext(args->isolate(),
+                             callback,
+                             context.web_frame()->mainWorldScriptContext());
 
-    scoped_refptr<CallbackAndContext> callback_and_context =
-        new CallbackAndContext(args.GetIsolate(),
-                               callback_local,
-                               context.web_frame()->mainWorldScriptContext());
 
+  // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
+  // progress, we will leak the callback and context. This needs to be fixed,
+  // somehow.
+  context.render_view_impl()->QueueSyntheticGesture(
+      gesture_params.Pass(),
+      base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
 
-    // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
-    // progress, we will leak the callback and context. This needs to be fixed,
-    // somehow.
-    context.render_view_impl()->QueueSyntheticGesture(
-        gesture_params.PassAs<SyntheticGestureParams>(),
-        base::Bind(&OnSyntheticGestureCompleted,
-                   callback_and_context));
+  return true;
+}
 
-    args.GetReturnValue().Set(true);
+bool GpuBenchmarking::Tap(gin::Arguments* args) {
+  GpuBenchmarkingContext context;
+  if (!context.Init(false))
+    return false;
+
+  int position_x;
+  int position_y;
+  v8::Handle<v8::Function> callback;
+  int duration_ms = 50;
+  int gesture_source_type = 0;  // DEFAULT_INPUT
+
+  if (!GetArg(args, &position_x) ||
+      !GetArg(args, &position_y) ||
+      !GetOptionalArg(args, &callback) ||
+      !GetOptionalArg(args, &duration_ms) ||
+      !GetOptionalArg(args, &gesture_source_type)) {
+    return false;
   }
 
-  static void BeginTap(
-      const v8::FunctionCallbackInfo<v8::Value>& args) {
-    GpuBenchmarkingContext context;
-    if (!context.Init(false))
-      return;
-
-    int arglen = args.Length();
-    if (arglen < 5 ||
-        !args[0]->IsNumber() ||
-        !args[1]->IsNumber() ||
-        !args[2]->IsFunction() ||
-        !args[3]->IsNumber() ||
-        !args[4]->IsNumber()) {
-      args.GetReturnValue().Set(false);
-      return;
-    }
-
-    scoped_ptr<SyntheticTapGestureParams> gesture_params(
-        new SyntheticTapGestureParams);
+  scoped_ptr<SyntheticTapGestureParams> gesture_params(
+      new SyntheticTapGestureParams);
 
-    // Convert coordinates from CSS pixels to density independent pixels (DIPs).
-    float page_scale_factor = context.web_view()->pageScaleFactor();
+  // Convert coordinates from CSS pixels to density independent pixels (DIPs).
+  float page_scale_factor = context.web_view()->pageScaleFactor();
 
-    gesture_params->position.SetPoint(
-        args[0]->IntegerValue() * page_scale_factor,
-        args[1]->IntegerValue() * page_scale_factor);
-    gesture_params->duration_ms = args[3]->IntegerValue();
+  gesture_params->position.SetPoint(position_x * page_scale_factor,
+                                    position_y * page_scale_factor);
+  gesture_params->duration_ms = duration_ms;
 
-    int gesture_source_type = args[4]->IntegerValue();
-    if (gesture_source_type < 0 ||
-        gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
-      args.GetReturnValue().Set(false);
-      return;
-    }
-    gesture_params->gesture_source_type =
-        static_cast<SyntheticGestureParams::GestureSourceType>(
-            gesture_source_type);
-
-    v8::Local<v8::Function> callback_local =
-        v8::Local<v8::Function>::Cast(args[2]);
-
-    scoped_refptr<CallbackAndContext> callback_and_context =
-        new CallbackAndContext(args.GetIsolate(),
-                               callback_local,
-                               context.web_frame()->mainWorldScriptContext());
-
-
-    // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
-    // progress, we will leak the callback and context. This needs to be fixed,
-    // somehow.
-    context.render_view_impl()->QueueSyntheticGesture(
-        gesture_params.PassAs<SyntheticGestureParams>(),
-        base::Bind(&OnSyntheticGestureCompleted,
-                   callback_and_context));
-
-    args.GetReturnValue().Set(true);
-  }
-
-  static void OnSnapshotCompleted(CallbackAndContext* callback_and_context,
-                                  const gfx::Size& size,
-                                  const std::vector<unsigned char>& png) {
-    v8::Isolate* isolate = callback_and_context->isolate();
-    v8::HandleScope scope(isolate);
-    v8::Handle<v8::Context> context = callback_and_context->GetContext();
-    v8::Context::Scope context_scope(context);
-    WebLocalFrame* frame = WebLocalFrame::frameForContext(context);
-    if (frame) {
-
-      v8::Handle<v8::Value> result;
-
-      if(!size.IsEmpty()) {
-        v8::Handle<v8::Object> result_object;
-        result_object = v8::Object::New(isolate);
-
-        result_object->Set(v8::String::NewFromUtf8(isolate, "width"),
-                           v8::Number::New(isolate, size.width()));
-        result_object->Set(v8::String::NewFromUtf8(isolate, "height"),
-                           v8::Number::New(isolate, size.height()));
-
-        std::string base64_png;
-        base::Base64Encode(base::StringPiece(
-            reinterpret_cast<const char*>(&*png.begin()), png.size()),
-            &base64_png);
-
-        result_object->Set(v8::String::NewFromUtf8(isolate, "data"),
-                           v8::String::NewFromUtf8(isolate,
-                                                   base64_png.c_str(),
-                                                   v8::String::kNormalString,
-                                                   base64_png.size()));
-
-        result = result_object;
-      } else {
-        result = v8::Null(isolate);
-      }
-
-      v8::Handle<v8::Value> argv[] = { result };
-
-      frame->callFunctionEvenIfScriptDisabled(
-          callback_and_context->GetCallback(),
-          v8::Object::New(isolate),
-          1,
-          argv);
-    }
+  if (gesture_source_type < 0 ||
+      gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
+    return false;
   }
+  gesture_params->gesture_source_type =
+      static_cast<SyntheticGestureParams::GestureSourceType>(
+          gesture_source_type);
+
+  scoped_refptr<CallbackAndContext> callback_and_context =
+      new CallbackAndContext(args->isolate(),
+                             callback,
+                             context.web_frame()->mainWorldScriptContext());
+
+  // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
+  // progress, we will leak the callback and context. This needs to be fixed,
+  // somehow.
+  context.render_view_impl()->QueueSyntheticGesture(
+      gesture_params.Pass(),
+      base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
+
+  return true;
+}
 
-  static void BeginWindowSnapshotPNG(
-      const v8::FunctionCallbackInfo<v8::Value>& args) {
-    GpuBenchmarkingContext context;
-    if (!context.Init(false))
-      return;
-
-    if (!args[0]->IsFunction())
-      return;
-
-    v8::Local<v8::Function> callback_local =
-        v8::Local<v8::Function>::Cast(args[0]);
-
-    scoped_refptr<CallbackAndContext> callback_and_context =
-        new CallbackAndContext(args.GetIsolate(),
-                               callback_local,
-                               context.web_frame()->mainWorldScriptContext());
-
-    context.render_view_impl()->GetWindowSnapshot(
-        base::Bind(&OnSnapshotCompleted, callback_and_context));
-  }
-
-  static void ClearImageCache(
-      const v8::FunctionCallbackInfo<v8::Value>& args) {
-    WebImageCache::clear();
-  }
-
-  static void OnMicroBenchmarkCompleted(
-      CallbackAndContext* callback_and_context,
-      scoped_ptr<base::Value> result) {
-    v8::Isolate* isolate = callback_and_context->isolate();
-    v8::HandleScope scope(isolate);
-    v8::Handle<v8::Context> context = callback_and_context->GetContext();
-    v8::Context::Scope context_scope(context);
-    WebLocalFrame* frame = WebLocalFrame::frameForContext(context);
-    if (frame) {
-      scoped_ptr<V8ValueConverter> converter =
-          make_scoped_ptr(V8ValueConverter::create());
-      v8::Handle<v8::Value> value = converter->ToV8Value(result.get(), context);
-      v8::Handle<v8::Value> argv[] = { value };
-
-      frame->callFunctionEvenIfScriptDisabled(
-          callback_and_context->GetCallback(),
-          v8::Object::New(isolate),
-          1,
-          argv);
-    }
-  }
+void GpuBenchmarking::BeginWindowSnapshotPNG(
+    v8::Isolate* isolate,
+    v8::Handle<v8::Function> callback) {
+  GpuBenchmarkingContext context;
+  if (!context.Init(false))
+    return;
 
-  static void RunMicroBenchmark(
-      const v8::FunctionCallbackInfo<v8::Value>& args) {
-    GpuBenchmarkingContext context;
-    if (!context.Init(true)) {
-      args.GetReturnValue().Set(0);
-      return;
-    }
+  scoped_refptr<CallbackAndContext> callback_and_context =
+      new CallbackAndContext(isolate,
+                             callback,
+                             context.web_frame()->mainWorldScriptContext());
 
-    if (args.Length() != 3 ||
-        !args[0]->IsString() ||
-        !args[1]->IsFunction() ||
-        !args[2]->IsObject()) {
-      args.GetReturnValue().Set(0);
-      return;
-    }
+  context.render_view_impl()->GetWindowSnapshot(
+      base::Bind(&OnSnapshotCompleted, callback_and_context));
+}
 
-    v8::Local<v8::Function> callback_local =
-        v8::Local<v8::Function>::Cast(args[1]);
+void GpuBenchmarking::ClearImageCache() {
+  WebImageCache::clear();
+}
 
-    scoped_refptr<CallbackAndContext> callback_and_context =
-        new CallbackAndContext(args.GetIsolate(),
-                               callback_local,
-                               context.web_frame()->mainWorldScriptContext());
+int GpuBenchmarking::RunMicroBenchmark(gin::Arguments* args) {
+  GpuBenchmarkingContext context;
+  if (!context.Init(true))
+    return 0;
 
-    scoped_ptr<V8ValueConverter> converter =
-        make_scoped_ptr(V8ValueConverter::create());
-    v8::Handle<v8::Context> v8_context = callback_and_context->GetContext();
-    scoped_ptr<base::Value> value =
-        make_scoped_ptr(converter->FromV8Value(args[2], v8_context));
-
-    v8::String::Utf8Value benchmark(args[0]);
-    DCHECK(*benchmark);
-    args.GetReturnValue().Set(context.compositor()->ScheduleMicroBenchmark(
-        std::string(*benchmark),
-        value.Pass(),
-        base::Bind(&OnMicroBenchmarkCompleted, callback_and_context)));
-  }
-
-  static void SendMessageToMicroBenchmark(
-      const v8::FunctionCallbackInfo<v8::Value>& args) {
-    GpuBenchmarkingContext context;
-    if (!context.Init(true)) {
-      args.GetReturnValue().Set(0);
-      return;
-    }
+  std::string name;
+  v8::Handle<v8::Function> callback;
+  v8::Handle<v8::Object> arguments;
 
-    if (args.Length() != 2 || !args[0]->IsNumber() || !args[1]->IsObject()) {
-      args.GetReturnValue().Set(0);
-      return;
-    }
+  if (!GetArg(args, &name) || !GetArg(args, &callback) ||
+      !GetOptionalArg(args, &arguments)) {
+    return 0;
+  }
 
-    scoped_ptr<V8ValueConverter> converter =
-        make_scoped_ptr(V8ValueConverter::create());
-    v8::Handle<v8::Context> v8_context =
-        context.web_frame()->mainWorldScriptContext();
-    scoped_ptr<base::Value> value =
-        make_scoped_ptr(converter->FromV8Value(args[1], v8_context));
+  scoped_refptr<CallbackAndContext> callback_and_context =
+      new CallbackAndContext(args->isolate(),
+                             callback,
+                             context.web_frame()->mainWorldScriptContext());
+
+  scoped_ptr<V8ValueConverter> converter =
+      make_scoped_ptr(V8ValueConverter::create());
+  v8::Handle<v8::Context> v8_context = callback_and_context->GetContext();
+  scoped_ptr<base::Value> value =
+      make_scoped_ptr(converter->FromV8Value(arguments, v8_context));
+
+  return context.compositor()->ScheduleMicroBenchmark(
+      name,
+      value.Pass(),
+      base::Bind(&OnMicroBenchmarkCompleted, callback_and_context));
+}
 
-    int id = 0;
-    converter->FromV8Value(args[0], v8_context)->GetAsInteger(&id);
-    args.GetReturnValue().Set(
-        context.compositor()->SendMessageToMicroBenchmark(id, value.Pass()));
-  }
+bool GpuBenchmarking::SendMessageToMicroBenchmark(
+    int id,
+    v8::Handle<v8::Object> message) {
+  GpuBenchmarkingContext context;
+  if (!context.Init(true))
+    return false;
+
+  scoped_ptr<V8ValueConverter> converter =
+      make_scoped_ptr(V8ValueConverter::create());
+  v8::Handle<v8::Context> v8_context =
+      context.web_frame()->mainWorldScriptContext();
+  scoped_ptr<base::Value> value =
+      make_scoped_ptr(converter->FromV8Value(message, v8_context));
+
+  return context.compositor()->SendMessageToMicroBenchmark(id, value.Pass());
+}
 
-  static void HasGpuProcess(const v8::FunctionCallbackInfo<v8::Value>& args) {
+bool GpuBenchmarking::HasGpuProcess() {
     GpuChannelHost* gpu_channel = RenderThreadImpl::current()->GetGpuChannel();
-    args.GetReturnValue().Set(!!gpu_channel);
-  }
-};
-
-v8::Extension* GpuBenchmarkingExtension::Get() {
-  return new GpuBenchmarkingWrapper();
+    return !!gpu_channel;
 }
 
 }  // namespace content