[ServiceWorker] Implement WebServiceWorkerContextClient::openWindow().
[chromium-blink-merge.git] / content / renderer / gpu / gpu_benchmarking_extension.cc
bloba83c02a0a1676e250ab681e5d088668a5660a3a7
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.
5 #include "content/renderer/gpu/gpu_benchmarking_extension.h"
7 #include <string>
9 #include "base/base64.h"
10 #include "base/files/file_path.h"
11 #include "base/files/file_util.h"
12 #include "base/memory/scoped_vector.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "cc/layers/layer.h"
15 #include "content/common/input/synthetic_gesture_params.h"
16 #include "content/common/input/synthetic_pinch_gesture_params.h"
17 #include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
18 #include "content/common/input/synthetic_tap_gesture_params.h"
19 #include "content/public/renderer/render_thread.h"
20 #include "content/public/renderer/v8_value_converter.h"
21 #include "content/renderer/chrome_object_extensions_utils.h"
22 #include "content/renderer/gpu/render_widget_compositor.h"
23 #include "content/renderer/render_thread_impl.h"
24 #include "content/renderer/render_view_impl.h"
25 #include "content/renderer/skia_benchmarking_extension.h"
26 #include "gin/arguments.h"
27 #include "gin/handle.h"
28 #include "gin/object_template_builder.h"
29 #include "third_party/WebKit/public/web/WebImageCache.h"
30 #include "third_party/WebKit/public/web/WebKit.h"
31 #include "third_party/WebKit/public/web/WebLocalFrame.h"
32 #include "third_party/WebKit/public/web/WebView.h"
33 #include "third_party/skia/include/core/SkData.h"
34 #include "third_party/skia/include/core/SkGraphics.h"
35 #include "third_party/skia/include/core/SkPicture.h"
36 #include "third_party/skia/include/core/SkPixelRef.h"
37 #include "third_party/skia/include/core/SkPixelSerializer.h"
38 #include "third_party/skia/include/core/SkStream.h"
39 #include "ui/gfx/codec/png_codec.h"
40 #include "v8/include/v8.h"
42 using blink::WebCanvas;
43 using blink::WebLocalFrame;
44 using blink::WebImageCache;
45 using blink::WebPrivatePtr;
46 using blink::WebSize;
47 using blink::WebView;
49 namespace content {
51 namespace {
53 class PNGSerializer : public SkPixelSerializer {
54 protected:
55 bool onUseEncodedData(const void* data, size_t len) override { return true; }
57 SkData* onEncodePixels(const SkImageInfo& info,
58 const void* pixels,
59 size_t row_bytes) override {
60 SkBitmap bm;
61 // The const_cast is fine, since we only read from the bitmap.
62 if (bm.installPixels(info, const_cast<void*>(pixels), row_bytes)) {
63 std::vector<unsigned char> vector;
64 if (gfx::PNGCodec::EncodeBGRASkBitmap(bm, false, &vector)) {
65 return SkData::NewWithCopy(&vector.front(), vector.size());
68 return nullptr;
72 class SkPictureSerializer {
73 public:
74 explicit SkPictureSerializer(const base::FilePath& dirpath)
75 : dirpath_(dirpath),
76 layer_id_(0) {
77 // Let skia register known effect subclasses. This basically enables
78 // reflection on those subclasses required for picture serialization.
79 SkiaBenchmarking::Initialize();
82 // Recursively serializes the layer tree.
83 // Each layer in the tree is serialized into a separate skp file
84 // in the given directory.
85 void Serialize(const cc::Layer* layer) {
86 const cc::LayerList& children = layer->children();
87 for (size_t i = 0; i < children.size(); ++i) {
88 Serialize(children[i].get());
91 skia::RefPtr<SkPicture> picture = layer->GetPicture();
92 if (!picture)
93 return;
95 // Serialize picture to file.
96 // TODO(alokp): Note that for this to work Chrome needs to be launched with
97 // --no-sandbox command-line flag. Get rid of this limitation.
98 // CRBUG: 139640.
99 std::string filename = "layer_" + base::IntToString(layer_id_++) + ".skp";
100 std::string filepath = dirpath_.AppendASCII(filename).MaybeAsASCII();
101 DCHECK(!filepath.empty());
102 SkFILEWStream file(filepath.c_str());
103 DCHECK(file.isValid());
105 PNGSerializer serializer;
106 picture->serialize(&file, &serializer);
109 private:
110 base::FilePath dirpath_;
111 int layer_id_;
114 template <typename T>
115 bool GetArg(gin::Arguments* args, T* value) {
116 if (!args->GetNext(value)) {
117 args->ThrowError();
118 return false;
120 return true;
123 template <>
124 bool GetArg(gin::Arguments* args, int* value) {
125 float number;
126 bool ret = GetArg(args, &number);
127 *value = number;
128 return ret;
131 template <typename T>
132 bool GetOptionalArg(gin::Arguments* args, T* value) {
133 if (args->PeekNext().IsEmpty())
134 return true;
135 if (args->PeekNext()->IsUndefined()) {
136 args->Skip();
137 return true;
139 return GetArg(args, value);
142 class CallbackAndContext : public base::RefCounted<CallbackAndContext> {
143 public:
144 CallbackAndContext(v8::Isolate* isolate,
145 v8::Handle<v8::Function> callback,
146 v8::Handle<v8::Context> context)
147 : isolate_(isolate) {
148 callback_.Reset(isolate_, callback);
149 context_.Reset(isolate_, context);
152 v8::Isolate* isolate() {
153 return isolate_;
156 v8::Handle<v8::Function> GetCallback() {
157 return v8::Local<v8::Function>::New(isolate_, callback_);
160 v8::Handle<v8::Context> GetContext() {
161 return v8::Local<v8::Context>::New(isolate_, context_);
164 private:
165 friend class base::RefCounted<CallbackAndContext>;
167 virtual ~CallbackAndContext() {
168 callback_.Reset();
169 context_.Reset();
172 v8::Isolate* isolate_;
173 v8::Persistent<v8::Function> callback_;
174 v8::Persistent<v8::Context> context_;
175 DISALLOW_COPY_AND_ASSIGN(CallbackAndContext);
178 class GpuBenchmarkingContext {
179 public:
180 GpuBenchmarkingContext()
181 : web_frame_(NULL),
182 web_view_(NULL),
183 render_view_impl_(NULL),
184 compositor_(NULL) {}
186 bool Init(bool init_compositor) {
187 web_frame_ = WebLocalFrame::frameForCurrentContext();
188 if (!web_frame_)
189 return false;
191 web_view_ = web_frame_->view();
192 if (!web_view_) {
193 web_frame_ = NULL;
194 return false;
197 render_view_impl_ = RenderViewImpl::FromWebView(web_view_);
198 if (!render_view_impl_) {
199 web_frame_ = NULL;
200 web_view_ = NULL;
201 return false;
204 if (!init_compositor)
205 return true;
207 compositor_ = render_view_impl_->compositor();
208 if (!compositor_) {
209 web_frame_ = NULL;
210 web_view_ = NULL;
211 render_view_impl_ = NULL;
212 return false;
215 return true;
218 WebLocalFrame* web_frame() const {
219 DCHECK(web_frame_ != NULL);
220 return web_frame_;
222 WebView* web_view() const {
223 DCHECK(web_view_ != NULL);
224 return web_view_;
226 RenderViewImpl* render_view_impl() const {
227 DCHECK(render_view_impl_ != NULL);
228 return render_view_impl_;
230 RenderWidgetCompositor* compositor() const {
231 DCHECK(compositor_ != NULL);
232 return compositor_;
235 private:
236 WebLocalFrame* web_frame_;
237 WebView* web_view_;
238 RenderViewImpl* render_view_impl_;
239 RenderWidgetCompositor* compositor_;
241 DISALLOW_COPY_AND_ASSIGN(GpuBenchmarkingContext);
244 void OnMicroBenchmarkCompleted(
245 CallbackAndContext* callback_and_context,
246 scoped_ptr<base::Value> result) {
247 v8::Isolate* isolate = callback_and_context->isolate();
248 v8::HandleScope scope(isolate);
249 v8::Handle<v8::Context> context = callback_and_context->GetContext();
250 v8::Context::Scope context_scope(context);
251 WebLocalFrame* frame = WebLocalFrame::frameForContext(context);
252 if (frame) {
253 scoped_ptr<V8ValueConverter> converter =
254 make_scoped_ptr(V8ValueConverter::create());
255 v8::Handle<v8::Value> value = converter->ToV8Value(result.get(), context);
256 v8::Handle<v8::Value> argv[] = { value };
258 frame->callFunctionEvenIfScriptDisabled(
259 callback_and_context->GetCallback(),
260 v8::Object::New(isolate),
262 argv);
266 void OnSnapshotCompleted(CallbackAndContext* callback_and_context,
267 const gfx::Size& size,
268 const std::vector<unsigned char>& png) {
269 v8::Isolate* isolate = callback_and_context->isolate();
270 v8::HandleScope scope(isolate);
271 v8::Handle<v8::Context> context = callback_and_context->GetContext();
272 v8::Context::Scope context_scope(context);
273 WebLocalFrame* frame = WebLocalFrame::frameForContext(context);
274 if (frame) {
275 v8::Handle<v8::Value> result;
277 if (!size.IsEmpty()) {
278 v8::Handle<v8::Object> result_object;
279 result_object = v8::Object::New(isolate);
281 result_object->Set(v8::String::NewFromUtf8(isolate, "width"),
282 v8::Number::New(isolate, size.width()));
283 result_object->Set(v8::String::NewFromUtf8(isolate, "height"),
284 v8::Number::New(isolate, size.height()));
286 std::string base64_png;
287 base::Base64Encode(
288 base::StringPiece(reinterpret_cast<const char*>(&*png.begin()),
289 png.size()),
290 &base64_png);
292 result_object->Set(v8::String::NewFromUtf8(isolate, "data"),
293 v8::String::NewFromUtf8(isolate,
294 base64_png.c_str(),
295 v8::String::kNormalString,
296 base64_png.size()));
298 result = result_object;
299 } else {
300 result = v8::Null(isolate);
303 v8::Handle<v8::Value> argv[] = {result};
305 frame->callFunctionEvenIfScriptDisabled(
306 callback_and_context->GetCallback(), v8::Object::New(isolate), 1, argv);
310 void OnSyntheticGestureCompleted(CallbackAndContext* callback_and_context) {
311 v8::Isolate* isolate = callback_and_context->isolate();
312 v8::HandleScope scope(isolate);
313 v8::Handle<v8::Context> context = callback_and_context->GetContext();
314 v8::Context::Scope context_scope(context);
315 WebLocalFrame* frame = WebLocalFrame::frameForContext(context);
316 if (frame) {
317 frame->callFunctionEvenIfScriptDisabled(
318 callback_and_context->GetCallback(), v8::Object::New(isolate), 0, NULL);
322 bool BeginSmoothScroll(v8::Isolate* isolate,
323 int pixels_to_scroll,
324 v8::Handle<v8::Function> callback,
325 int gesture_source_type,
326 const std::string& direction,
327 int speed_in_pixels_s,
328 bool prevent_fling,
329 int start_x,
330 int start_y) {
331 GpuBenchmarkingContext context;
332 if (!context.Init(false))
333 return false;
335 scoped_refptr<CallbackAndContext> callback_and_context =
336 new CallbackAndContext(
337 isolate, callback, context.web_frame()->mainWorldScriptContext());
339 scoped_ptr<SyntheticSmoothScrollGestureParams> gesture_params(
340 new SyntheticSmoothScrollGestureParams);
342 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
343 float page_scale_factor = context.web_view()->pageScaleFactor();
345 if (gesture_source_type < 0 ||
346 gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
347 return false;
349 gesture_params->gesture_source_type =
350 static_cast<SyntheticGestureParams::GestureSourceType>(
351 gesture_source_type);
353 gesture_params->speed_in_pixels_s = speed_in_pixels_s;
354 gesture_params->prevent_fling = prevent_fling;
356 gesture_params->anchor.SetPoint(start_x * page_scale_factor,
357 start_y * page_scale_factor);
359 int distance_length = pixels_to_scroll * page_scale_factor;
360 gfx::Vector2d distance;
361 if (direction == "down")
362 distance.set_y(-distance_length);
363 else if (direction == "up")
364 distance.set_y(distance_length);
365 else if (direction == "right")
366 distance.set_x(-distance_length);
367 else if (direction == "left")
368 distance.set_x(distance_length);
369 else {
370 return false;
372 gesture_params->distances.push_back(distance);
374 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
375 // progress, we will leak the callback and context. This needs to be fixed,
376 // somehow.
377 context.render_view_impl()->QueueSyntheticGesture(
378 gesture_params.Pass(),
379 base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
381 return true;
384 } // namespace
386 gin::WrapperInfo GpuBenchmarking::kWrapperInfo = {gin::kEmbedderNativeGin};
388 // static
389 void GpuBenchmarking::Install(blink::WebFrame* frame) {
390 v8::Isolate* isolate = blink::mainThreadIsolate();
391 v8::HandleScope handle_scope(isolate);
392 v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
393 if (context.IsEmpty())
394 return;
396 v8::Context::Scope context_scope(context);
398 gin::Handle<GpuBenchmarking> controller =
399 gin::CreateHandle(isolate, new GpuBenchmarking());
400 if (controller.IsEmpty())
401 return;
403 v8::Handle<v8::Object> chrome = GetOrCreateChromeObject(isolate,
404 context->Global());
405 chrome->Set(gin::StringToV8(isolate, "gpuBenchmarking"), controller.ToV8());
408 GpuBenchmarking::GpuBenchmarking() {
411 GpuBenchmarking::~GpuBenchmarking() {
414 gin::ObjectTemplateBuilder GpuBenchmarking::GetObjectTemplateBuilder(
415 v8::Isolate* isolate) {
416 return gin::Wrappable<GpuBenchmarking>::GetObjectTemplateBuilder(isolate)
417 .SetMethod("setNeedsDisplayOnAllLayers",
418 &GpuBenchmarking::SetNeedsDisplayOnAllLayers)
419 .SetMethod("setRasterizeOnlyVisibleContent",
420 &GpuBenchmarking::SetRasterizeOnlyVisibleContent)
421 .SetMethod("printToSkPicture", &GpuBenchmarking::PrintToSkPicture)
422 .SetValue("DEFAULT_INPUT", 0)
423 .SetValue("TOUCH_INPUT", 1)
424 .SetValue("MOUSE_INPUT", 2)
425 .SetMethod("gestureSourceTypeSupported",
426 &GpuBenchmarking::GestureSourceTypeSupported)
427 .SetMethod("smoothScrollBy", &GpuBenchmarking::SmoothScrollBy)
428 .SetMethod("swipe", &GpuBenchmarking::Swipe)
429 .SetMethod("scrollBounce", &GpuBenchmarking::ScrollBounce)
430 // TODO(dominikg): Remove once JS interface changes have rolled into
431 // stable.
432 .SetValue("newPinchInterface", true)
433 .SetMethod("pinchBy", &GpuBenchmarking::PinchBy)
434 .SetMethod("tap", &GpuBenchmarking::Tap)
435 .SetMethod("beginWindowSnapshotPNG",
436 &GpuBenchmarking::BeginWindowSnapshotPNG)
437 .SetMethod("clearImageCache", &GpuBenchmarking::ClearImageCache)
438 .SetMethod("runMicroBenchmark", &GpuBenchmarking::RunMicroBenchmark)
439 .SetMethod("sendMessageToMicroBenchmark",
440 &GpuBenchmarking::SendMessageToMicroBenchmark)
441 .SetMethod("hasGpuProcess", &GpuBenchmarking::HasGpuProcess);
444 void GpuBenchmarking::SetNeedsDisplayOnAllLayers() {
445 GpuBenchmarkingContext context;
446 if (!context.Init(true))
447 return;
449 context.compositor()->SetNeedsDisplayOnAllLayers();
452 void GpuBenchmarking::SetRasterizeOnlyVisibleContent() {
453 GpuBenchmarkingContext context;
454 if (!context.Init(true))
455 return;
457 context.compositor()->SetRasterizeOnlyVisibleContent();
460 void GpuBenchmarking::PrintToSkPicture(v8::Isolate* isolate,
461 const std::string& dirname) {
462 GpuBenchmarkingContext context;
463 if (!context.Init(true))
464 return;
466 const cc::Layer* root_layer = context.compositor()->GetRootLayer();
467 if (!root_layer)
468 return;
470 base::FilePath dirpath = base::FilePath::FromUTF8Unsafe(dirname);
471 if (!base::CreateDirectory(dirpath) ||
472 !base::PathIsWritable(dirpath)) {
473 std::string msg("Path is not writable: ");
474 msg.append(dirpath.MaybeAsASCII());
475 isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(
476 isolate, msg.c_str(), v8::String::kNormalString, msg.length())));
477 return;
480 SkPictureSerializer serializer(dirpath);
481 serializer.Serialize(root_layer);
484 bool GpuBenchmarking::GestureSourceTypeSupported(int gesture_source_type) {
485 if (gesture_source_type < 0 ||
486 gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
487 return false;
490 return SyntheticGestureParams::IsGestureSourceTypeSupported(
491 static_cast<SyntheticGestureParams::GestureSourceType>(
492 gesture_source_type));
495 bool GpuBenchmarking::SmoothScrollBy(gin::Arguments* args) {
496 GpuBenchmarkingContext context;
497 if (!context.Init(true))
498 return false;
500 float page_scale_factor = context.web_view()->pageScaleFactor();
501 blink::WebRect rect = context.render_view_impl()->windowRect();
503 int pixels_to_scroll = 0;
504 v8::Handle<v8::Function> callback;
505 int start_x = rect.width / (page_scale_factor * 2);
506 int start_y = rect.height / (page_scale_factor * 2);
507 int gesture_source_type = 0; // DEFAULT_INPUT
508 std::string direction = "down";
509 int speed_in_pixels_s = 800;
511 if (!GetOptionalArg(args, &pixels_to_scroll) ||
512 !GetOptionalArg(args, &callback) ||
513 !GetOptionalArg(args, &start_x) ||
514 !GetOptionalArg(args, &start_y) ||
515 !GetOptionalArg(args, &gesture_source_type) ||
516 !GetOptionalArg(args, &direction) ||
517 !GetOptionalArg(args, &speed_in_pixels_s)) {
518 return false;
521 return BeginSmoothScroll(args->isolate(),
522 pixels_to_scroll,
523 callback,
524 gesture_source_type,
525 direction,
526 speed_in_pixels_s,
527 true,
528 start_x,
529 start_y);
532 bool GpuBenchmarking::Swipe(gin::Arguments* args) {
533 GpuBenchmarkingContext context;
534 if (!context.Init(true))
535 return false;
537 float page_scale_factor = context.web_view()->pageScaleFactor();
538 blink::WebRect rect = context.render_view_impl()->windowRect();
540 std::string direction = "up";
541 int pixels_to_scroll = 0;
542 v8::Handle<v8::Function> callback;
543 int start_x = rect.width / (page_scale_factor * 2);
544 int start_y = rect.height / (page_scale_factor * 2);
545 int speed_in_pixels_s = 800;
547 if (!GetOptionalArg(args, &direction) ||
548 !GetOptionalArg(args, &pixels_to_scroll) ||
549 !GetOptionalArg(args, &callback) ||
550 !GetOptionalArg(args, &start_x) ||
551 !GetOptionalArg(args, &start_y) ||
552 !GetOptionalArg(args, &speed_in_pixels_s)) {
553 return false;
556 return BeginSmoothScroll(args->isolate(),
557 -pixels_to_scroll,
558 callback,
559 1, // TOUCH_INPUT
560 direction,
561 speed_in_pixels_s,
562 false,
563 start_x,
564 start_y);
567 bool GpuBenchmarking::ScrollBounce(gin::Arguments* args) {
568 GpuBenchmarkingContext context;
569 if (!context.Init(false))
570 return false;
572 float page_scale_factor = context.web_view()->pageScaleFactor();
573 blink::WebRect rect = context.render_view_impl()->windowRect();
575 std::string direction = "down";
576 int distance_length = 0;
577 int overscroll_length = 0;
578 int repeat_count = 1;
579 v8::Handle<v8::Function> callback;
580 int start_x = rect.width / (page_scale_factor * 2);
581 int start_y = rect.height / (page_scale_factor * 2);
582 int speed_in_pixels_s = 800;
584 if (!GetOptionalArg(args, &direction) ||
585 !GetOptionalArg(args, &distance_length) ||
586 !GetOptionalArg(args, &overscroll_length) ||
587 !GetOptionalArg(args, &repeat_count) ||
588 !GetOptionalArg(args, &callback) ||
589 !GetOptionalArg(args, &start_x) ||
590 !GetOptionalArg(args, &start_y) ||
591 !GetOptionalArg(args, &speed_in_pixels_s)) {
592 return false;
595 scoped_refptr<CallbackAndContext> callback_and_context =
596 new CallbackAndContext(args->isolate(),
597 callback,
598 context.web_frame()->mainWorldScriptContext());
600 scoped_ptr<SyntheticSmoothScrollGestureParams> gesture_params(
601 new SyntheticSmoothScrollGestureParams);
603 gesture_params->speed_in_pixels_s = speed_in_pixels_s;
605 gesture_params->anchor.SetPoint(start_x * page_scale_factor,
606 start_y * page_scale_factor);
608 distance_length *= page_scale_factor;
609 overscroll_length *= page_scale_factor;
610 gfx::Vector2d distance;
611 gfx::Vector2d overscroll;
612 if (direction == "down") {
613 distance.set_y(-distance_length);
614 overscroll.set_y(overscroll_length);
615 } else if (direction == "up") {
616 distance.set_y(distance_length);
617 overscroll.set_y(-overscroll_length);
618 } else if (direction == "right") {
619 distance.set_x(-distance_length);
620 overscroll.set_x(overscroll_length);
621 } else if (direction == "left") {
622 distance.set_x(distance_length);
623 overscroll.set_x(-overscroll_length);
624 } else {
625 return false;
628 for (int i = 0; i < repeat_count; i++) {
629 gesture_params->distances.push_back(distance);
630 gesture_params->distances.push_back(-distance + overscroll);
633 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
634 // progress, we will leak the callback and context. This needs to be fixed,
635 // somehow.
636 context.render_view_impl()->QueueSyntheticGesture(
637 gesture_params.Pass(),
638 base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
640 return true;
643 bool GpuBenchmarking::PinchBy(gin::Arguments* args) {
644 GpuBenchmarkingContext context;
645 if (!context.Init(false))
646 return false;
648 float scale_factor;
649 int anchor_x;
650 int anchor_y;
651 v8::Handle<v8::Function> callback;
652 int relative_pointer_speed_in_pixels_s = 800;
655 if (!GetArg(args, &scale_factor) ||
656 !GetArg(args, &anchor_x) ||
657 !GetArg(args, &anchor_y) ||
658 !GetOptionalArg(args, &callback) ||
659 !GetOptionalArg(args, &relative_pointer_speed_in_pixels_s)) {
660 return false;
663 scoped_ptr<SyntheticPinchGestureParams> gesture_params(
664 new SyntheticPinchGestureParams);
666 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
667 float page_scale_factor = context.web_view()->pageScaleFactor();
669 gesture_params->scale_factor = scale_factor;
670 gesture_params->anchor.SetPoint(anchor_x * page_scale_factor,
671 anchor_y * page_scale_factor);
672 gesture_params->relative_pointer_speed_in_pixels_s =
673 relative_pointer_speed_in_pixels_s;
675 scoped_refptr<CallbackAndContext> callback_and_context =
676 new CallbackAndContext(args->isolate(),
677 callback,
678 context.web_frame()->mainWorldScriptContext());
681 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
682 // progress, we will leak the callback and context. This needs to be fixed,
683 // somehow.
684 context.render_view_impl()->QueueSyntheticGesture(
685 gesture_params.Pass(),
686 base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
688 return true;
691 bool GpuBenchmarking::Tap(gin::Arguments* args) {
692 GpuBenchmarkingContext context;
693 if (!context.Init(false))
694 return false;
696 int position_x;
697 int position_y;
698 v8::Handle<v8::Function> callback;
699 int duration_ms = 50;
700 int gesture_source_type = 0; // DEFAULT_INPUT
702 if (!GetArg(args, &position_x) ||
703 !GetArg(args, &position_y) ||
704 !GetOptionalArg(args, &callback) ||
705 !GetOptionalArg(args, &duration_ms) ||
706 !GetOptionalArg(args, &gesture_source_type)) {
707 return false;
710 scoped_ptr<SyntheticTapGestureParams> gesture_params(
711 new SyntheticTapGestureParams);
713 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
714 float page_scale_factor = context.web_view()->pageScaleFactor();
716 gesture_params->position.SetPoint(position_x * page_scale_factor,
717 position_y * page_scale_factor);
718 gesture_params->duration_ms = duration_ms;
720 if (gesture_source_type < 0 ||
721 gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
722 return false;
724 gesture_params->gesture_source_type =
725 static_cast<SyntheticGestureParams::GestureSourceType>(
726 gesture_source_type);
728 scoped_refptr<CallbackAndContext> callback_and_context =
729 new CallbackAndContext(args->isolate(),
730 callback,
731 context.web_frame()->mainWorldScriptContext());
733 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
734 // progress, we will leak the callback and context. This needs to be fixed,
735 // somehow.
736 context.render_view_impl()->QueueSyntheticGesture(
737 gesture_params.Pass(),
738 base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
740 return true;
743 void GpuBenchmarking::BeginWindowSnapshotPNG(
744 v8::Isolate* isolate,
745 v8::Handle<v8::Function> callback) {
746 GpuBenchmarkingContext context;
747 if (!context.Init(false))
748 return;
750 scoped_refptr<CallbackAndContext> callback_and_context =
751 new CallbackAndContext(isolate,
752 callback,
753 context.web_frame()->mainWorldScriptContext());
755 context.render_view_impl()->GetWindowSnapshot(
756 base::Bind(&OnSnapshotCompleted, callback_and_context));
759 void GpuBenchmarking::ClearImageCache() {
760 WebImageCache::clear();
763 int GpuBenchmarking::RunMicroBenchmark(gin::Arguments* args) {
764 GpuBenchmarkingContext context;
765 if (!context.Init(true))
766 return 0;
768 std::string name;
769 v8::Handle<v8::Function> callback;
770 v8::Handle<v8::Object> arguments;
772 if (!GetArg(args, &name) || !GetArg(args, &callback) ||
773 !GetOptionalArg(args, &arguments)) {
774 return 0;
777 scoped_refptr<CallbackAndContext> callback_and_context =
778 new CallbackAndContext(args->isolate(),
779 callback,
780 context.web_frame()->mainWorldScriptContext());
782 scoped_ptr<V8ValueConverter> converter =
783 make_scoped_ptr(V8ValueConverter::create());
784 v8::Handle<v8::Context> v8_context = callback_and_context->GetContext();
785 scoped_ptr<base::Value> value =
786 make_scoped_ptr(converter->FromV8Value(arguments, v8_context));
788 return context.compositor()->ScheduleMicroBenchmark(
789 name,
790 value.Pass(),
791 base::Bind(&OnMicroBenchmarkCompleted, callback_and_context));
794 bool GpuBenchmarking::SendMessageToMicroBenchmark(
795 int id,
796 v8::Handle<v8::Object> message) {
797 GpuBenchmarkingContext context;
798 if (!context.Init(true))
799 return false;
801 scoped_ptr<V8ValueConverter> converter =
802 make_scoped_ptr(V8ValueConverter::create());
803 v8::Handle<v8::Context> v8_context =
804 context.web_frame()->mainWorldScriptContext();
805 scoped_ptr<base::Value> value =
806 make_scoped_ptr(converter->FromV8Value(message, v8_context));
808 return context.compositor()->SendMessageToMicroBenchmark(id, value.Pass());
811 bool GpuBenchmarking::HasGpuProcess() {
812 GpuChannelHost* gpu_channel = RenderThreadImpl::current()->GetGpuChannel();
813 return !!gpu_channel;
816 } // namespace content