Refactor WebsiteSettings to operate on a SecurityInfo
[chromium-blink-merge.git] / content / renderer / gpu / gpu_benchmarking_extension.cc
blob454f5f5e5f9410e66312c0a7fc2d371037f1d691
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/strings/string_number_conversions.h"
13 #include "cc/layers/layer.h"
14 #include "content/common/input/synthetic_gesture_params.h"
15 #include "content/common/input/synthetic_pinch_gesture_params.h"
16 #include "content/common/input/synthetic_smooth_drag_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/child/v8_value_converter.h"
20 #include "content/public/renderer/render_thread.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::Local<v8::Function> callback,
146 v8::Local<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::Local<v8::Function> GetCallback() {
157 return v8::Local<v8::Function>::New(isolate_, callback_);
160 v8::Local<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::Local<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::Local<v8::Value> value = converter->ToV8Value(result.get(), context);
256 v8::Local<v8::Value> argv[] = { value };
258 frame->callFunctionEvenIfScriptDisabled(
259 callback_and_context->GetCallback(),
260 v8::Object::New(isolate),
262 argv);
266 void OnSyntheticGestureCompleted(CallbackAndContext* callback_and_context) {
267 v8::Isolate* isolate = callback_and_context->isolate();
268 v8::HandleScope scope(isolate);
269 v8::Local<v8::Context> context = callback_and_context->GetContext();
270 v8::Context::Scope context_scope(context);
271 WebLocalFrame* frame = WebLocalFrame::frameForContext(context);
272 if (frame) {
273 frame->callFunctionEvenIfScriptDisabled(
274 callback_and_context->GetCallback(), v8::Object::New(isolate), 0, NULL);
278 bool BeginSmoothScroll(v8::Isolate* isolate,
279 float pixels_to_scroll,
280 v8::Local<v8::Function> callback,
281 int gesture_source_type,
282 const std::string& direction,
283 float speed_in_pixels_s,
284 bool prevent_fling,
285 float start_x,
286 float start_y) {
287 GpuBenchmarkingContext context;
288 if (!context.Init(false))
289 return false;
291 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
292 float page_scale_factor = context.web_view()->pageScaleFactor();
294 if (gesture_source_type == SyntheticGestureParams::MOUSE_INPUT) {
295 // Ensure the mouse is centered and visible, in case it will
296 // trigger any hover or mousemove effects.
297 context.web_view()->setIsActive(true);
298 blink::WebRect contentRect =
299 context.web_view()->mainFrame()->visibleContentRect();
300 blink::WebMouseEvent mouseMove;
301 mouseMove.type = blink::WebInputEvent::MouseMove;
302 mouseMove.x = (contentRect.x + contentRect.width / 2) * page_scale_factor;
303 mouseMove.y = (contentRect.y + contentRect.height / 2) * page_scale_factor;
304 context.web_view()->handleInputEvent(mouseMove);
305 context.web_view()->setCursorVisibilityState(true);
308 scoped_refptr<CallbackAndContext> callback_and_context =
309 new CallbackAndContext(
310 isolate, callback, context.web_frame()->mainWorldScriptContext());
312 scoped_ptr<SyntheticSmoothScrollGestureParams> gesture_params(
313 new SyntheticSmoothScrollGestureParams);
315 if (gesture_source_type < 0 ||
316 gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
317 return false;
319 gesture_params->gesture_source_type =
320 static_cast<SyntheticGestureParams::GestureSourceType>(
321 gesture_source_type);
323 gesture_params->speed_in_pixels_s = speed_in_pixels_s;
324 gesture_params->prevent_fling = prevent_fling;
326 gesture_params->anchor.SetPoint(start_x * page_scale_factor,
327 start_y * page_scale_factor);
329 float distance_length = pixels_to_scroll * page_scale_factor;
330 gfx::Vector2dF distance;
331 if (direction == "down")
332 distance.set_y(-distance_length);
333 else if (direction == "up")
334 distance.set_y(distance_length);
335 else if (direction == "right")
336 distance.set_x(-distance_length);
337 else if (direction == "left")
338 distance.set_x(distance_length);
339 else if (direction == "upleft") {
340 distance.set_y(distance_length);
341 distance.set_x(distance_length);
342 } else if (direction == "upright") {
343 distance.set_y(distance_length);
344 distance.set_x(-distance_length);
345 } else if (direction == "downleft") {
346 distance.set_y(-distance_length);
347 distance.set_x(distance_length);
348 } else if (direction == "downright") {
349 distance.set_y(-distance_length);
350 distance.set_x(-distance_length);
351 } else {
352 return false;
354 gesture_params->distances.push_back(distance);
356 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
357 // progress, we will leak the callback and context. This needs to be fixed,
358 // somehow.
359 context.render_view_impl()->QueueSyntheticGesture(
360 gesture_params.Pass(),
361 base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
363 return true;
366 bool BeginSmoothDrag(v8::Isolate* isolate,
367 float start_x,
368 float start_y,
369 float end_x,
370 float end_y,
371 v8::Local<v8::Function> callback,
372 int gesture_source_type,
373 float speed_in_pixels_s) {
374 GpuBenchmarkingContext context;
375 if (!context.Init(false))
376 return false;
377 scoped_refptr<CallbackAndContext> callback_and_context =
378 new CallbackAndContext(isolate, callback,
379 context.web_frame()->mainWorldScriptContext());
381 scoped_ptr<SyntheticSmoothDragGestureParams> gesture_params(
382 new SyntheticSmoothDragGestureParams);
384 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
385 float page_scale_factor = context.web_view()->pageScaleFactor();
387 gesture_params->start_point.SetPoint(start_x * page_scale_factor,
388 start_y * page_scale_factor);
389 gfx::PointF end_point(end_x * page_scale_factor,
390 end_y * page_scale_factor);
391 gfx::Vector2dF distance = end_point - gesture_params->start_point;
392 gesture_params->distances.push_back(distance);
393 gesture_params->speed_in_pixels_s = speed_in_pixels_s * page_scale_factor;
394 gesture_params->gesture_source_type =
395 static_cast<SyntheticGestureParams::GestureSourceType>(
396 gesture_source_type);
398 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
399 // progress, we will leak the callback and context. This needs to be fixed,
400 // somehow.
401 context.render_view_impl()->QueueSyntheticGesture(
402 gesture_params.Pass(),
403 base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
405 return true;
408 } // namespace
410 gin::WrapperInfo GpuBenchmarking::kWrapperInfo = {gin::kEmbedderNativeGin};
412 // static
413 void GpuBenchmarking::Install(blink::WebFrame* frame) {
414 v8::Isolate* isolate = blink::mainThreadIsolate();
415 v8::HandleScope handle_scope(isolate);
416 v8::Local<v8::Context> context = frame->mainWorldScriptContext();
417 if (context.IsEmpty())
418 return;
420 v8::Context::Scope context_scope(context);
422 gin::Handle<GpuBenchmarking> controller =
423 gin::CreateHandle(isolate, new GpuBenchmarking());
424 if (controller.IsEmpty())
425 return;
427 v8::Local<v8::Object> chrome = GetOrCreateChromeObject(isolate,
428 context->Global());
429 chrome->Set(gin::StringToV8(isolate, "gpuBenchmarking"), controller.ToV8());
432 GpuBenchmarking::GpuBenchmarking() {
435 GpuBenchmarking::~GpuBenchmarking() {
438 gin::ObjectTemplateBuilder GpuBenchmarking::GetObjectTemplateBuilder(
439 v8::Isolate* isolate) {
440 return gin::Wrappable<GpuBenchmarking>::GetObjectTemplateBuilder(isolate)
441 .SetMethod("setNeedsDisplayOnAllLayers",
442 &GpuBenchmarking::SetNeedsDisplayOnAllLayers)
443 .SetMethod("setRasterizeOnlyVisibleContent",
444 &GpuBenchmarking::SetRasterizeOnlyVisibleContent)
445 .SetMethod("printToSkPicture", &GpuBenchmarking::PrintToSkPicture)
446 .SetValue("DEFAULT_INPUT", 0)
447 .SetValue("TOUCH_INPUT", 1)
448 .SetValue("MOUSE_INPUT", 2)
449 .SetMethod("gestureSourceTypeSupported",
450 &GpuBenchmarking::GestureSourceTypeSupported)
451 .SetMethod("smoothScrollBy", &GpuBenchmarking::SmoothScrollBy)
452 .SetMethod("smoothDrag", &GpuBenchmarking::SmoothDrag)
453 .SetMethod("swipe", &GpuBenchmarking::Swipe)
454 .SetMethod("scrollBounce", &GpuBenchmarking::ScrollBounce)
455 // TODO(dominikg): Remove once JS interface changes have rolled into
456 // stable.
457 .SetValue("newPinchInterface", true)
458 .SetMethod("pinchBy", &GpuBenchmarking::PinchBy)
459 .SetMethod("tap", &GpuBenchmarking::Tap)
460 .SetMethod("clearImageCache", &GpuBenchmarking::ClearImageCache)
461 .SetMethod("runMicroBenchmark", &GpuBenchmarking::RunMicroBenchmark)
462 .SetMethod("sendMessageToMicroBenchmark",
463 &GpuBenchmarking::SendMessageToMicroBenchmark)
464 .SetMethod("hasGpuProcess", &GpuBenchmarking::HasGpuProcess);
467 void GpuBenchmarking::SetNeedsDisplayOnAllLayers() {
468 GpuBenchmarkingContext context;
469 if (!context.Init(true))
470 return;
472 context.compositor()->SetNeedsDisplayOnAllLayers();
475 void GpuBenchmarking::SetRasterizeOnlyVisibleContent() {
476 GpuBenchmarkingContext context;
477 if (!context.Init(true))
478 return;
480 context.compositor()->SetRasterizeOnlyVisibleContent();
483 void GpuBenchmarking::PrintToSkPicture(v8::Isolate* isolate,
484 const std::string& dirname) {
485 GpuBenchmarkingContext context;
486 if (!context.Init(true))
487 return;
489 const cc::Layer* root_layer = context.compositor()->GetRootLayer();
490 if (!root_layer)
491 return;
493 base::FilePath dirpath = base::FilePath::FromUTF8Unsafe(dirname);
494 if (!base::CreateDirectory(dirpath) ||
495 !base::PathIsWritable(dirpath)) {
496 std::string msg("Path is not writable: ");
497 msg.append(dirpath.MaybeAsASCII());
498 isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(
499 isolate, msg.c_str(), v8::String::kNormalString, msg.length())));
500 return;
503 SkPictureSerializer serializer(dirpath);
504 serializer.Serialize(root_layer);
507 bool GpuBenchmarking::GestureSourceTypeSupported(int gesture_source_type) {
508 if (gesture_source_type < 0 ||
509 gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
510 return false;
513 return SyntheticGestureParams::IsGestureSourceTypeSupported(
514 static_cast<SyntheticGestureParams::GestureSourceType>(
515 gesture_source_type));
518 bool GpuBenchmarking::SmoothScrollBy(gin::Arguments* args) {
519 GpuBenchmarkingContext context;
520 if (!context.Init(true))
521 return false;
523 float page_scale_factor = context.web_view()->pageScaleFactor();
524 blink::WebRect rect = context.render_view_impl()->windowRect();
526 float pixels_to_scroll = 0;
527 v8::Local<v8::Function> callback;
528 float start_x = rect.width / (page_scale_factor * 2);
529 float start_y = rect.height / (page_scale_factor * 2);
530 int gesture_source_type = SyntheticGestureParams::DEFAULT_INPUT;
531 std::string direction = "down";
532 float speed_in_pixels_s = 800;
534 if (!GetOptionalArg(args, &pixels_to_scroll) ||
535 !GetOptionalArg(args, &callback) ||
536 !GetOptionalArg(args, &start_x) ||
537 !GetOptionalArg(args, &start_y) ||
538 !GetOptionalArg(args, &gesture_source_type) ||
539 !GetOptionalArg(args, &direction) ||
540 !GetOptionalArg(args, &speed_in_pixels_s)) {
541 return false;
544 return BeginSmoothScroll(args->isolate(),
545 pixels_to_scroll,
546 callback,
547 gesture_source_type,
548 direction,
549 speed_in_pixels_s,
550 true,
551 start_x,
552 start_y);
555 bool GpuBenchmarking::SmoothDrag(gin::Arguments* args) {
556 GpuBenchmarkingContext context;
557 if (!context.Init(true))
558 return false;
560 float start_x;
561 float start_y;
562 float end_x;
563 float end_y;
564 v8::Local<v8::Function> callback;
565 int gesture_source_type = SyntheticGestureParams::DEFAULT_INPUT;
566 float speed_in_pixels_s = 800;
568 if (!GetArg(args, &start_x) ||
569 !GetArg(args, &start_y) ||
570 !GetArg(args, &end_x) ||
571 !GetArg(args, &end_y) ||
572 !GetOptionalArg(args, &callback) ||
573 !GetOptionalArg(args, &gesture_source_type) ||
574 !GetOptionalArg(args, &speed_in_pixels_s)) {
575 return false;
578 return BeginSmoothDrag(args->isolate(),
579 start_x,
580 start_y,
581 end_x,
582 end_y,
583 callback,
584 gesture_source_type,
585 speed_in_pixels_s);
588 bool GpuBenchmarking::Swipe(gin::Arguments* args) {
589 GpuBenchmarkingContext context;
590 if (!context.Init(true))
591 return false;
593 float page_scale_factor = context.web_view()->pageScaleFactor();
594 blink::WebRect rect = context.render_view_impl()->windowRect();
596 std::string direction = "up";
597 float pixels_to_scroll = 0;
598 v8::Local<v8::Function> callback;
599 float start_x = rect.width / (page_scale_factor * 2);
600 float start_y = rect.height / (page_scale_factor * 2);
601 float speed_in_pixels_s = 800;
603 if (!GetOptionalArg(args, &direction) ||
604 !GetOptionalArg(args, &pixels_to_scroll) ||
605 !GetOptionalArg(args, &callback) ||
606 !GetOptionalArg(args, &start_x) ||
607 !GetOptionalArg(args, &start_y) ||
608 !GetOptionalArg(args, &speed_in_pixels_s)) {
609 return false;
612 return BeginSmoothScroll(args->isolate(),
613 -pixels_to_scroll,
614 callback,
615 1, // TOUCH_INPUT
616 direction,
617 speed_in_pixels_s,
618 false,
619 start_x,
620 start_y);
623 bool GpuBenchmarking::ScrollBounce(gin::Arguments* args) {
624 GpuBenchmarkingContext context;
625 if (!context.Init(false))
626 return false;
628 float page_scale_factor = context.web_view()->pageScaleFactor();
629 blink::WebRect rect = context.render_view_impl()->windowRect();
631 std::string direction = "down";
632 float distance_length = 0;
633 float overscroll_length = 0;
634 int repeat_count = 1;
635 v8::Local<v8::Function> callback;
636 float start_x = rect.width / (page_scale_factor * 2);
637 float start_y = rect.height / (page_scale_factor * 2);
638 float speed_in_pixels_s = 800;
640 if (!GetOptionalArg(args, &direction) ||
641 !GetOptionalArg(args, &distance_length) ||
642 !GetOptionalArg(args, &overscroll_length) ||
643 !GetOptionalArg(args, &repeat_count) ||
644 !GetOptionalArg(args, &callback) ||
645 !GetOptionalArg(args, &start_x) ||
646 !GetOptionalArg(args, &start_y) ||
647 !GetOptionalArg(args, &speed_in_pixels_s)) {
648 return false;
651 scoped_refptr<CallbackAndContext> callback_and_context =
652 new CallbackAndContext(args->isolate(),
653 callback,
654 context.web_frame()->mainWorldScriptContext());
656 scoped_ptr<SyntheticSmoothScrollGestureParams> gesture_params(
657 new SyntheticSmoothScrollGestureParams);
659 gesture_params->speed_in_pixels_s = speed_in_pixels_s;
661 gesture_params->anchor.SetPoint(start_x * page_scale_factor,
662 start_y * page_scale_factor);
664 distance_length *= page_scale_factor;
665 overscroll_length *= page_scale_factor;
666 gfx::Vector2dF distance;
667 gfx::Vector2dF overscroll;
668 if (direction == "down") {
669 distance.set_y(-distance_length);
670 overscroll.set_y(overscroll_length);
671 } else if (direction == "up") {
672 distance.set_y(distance_length);
673 overscroll.set_y(-overscroll_length);
674 } else if (direction == "right") {
675 distance.set_x(-distance_length);
676 overscroll.set_x(overscroll_length);
677 } else if (direction == "left") {
678 distance.set_x(distance_length);
679 overscroll.set_x(-overscroll_length);
680 } else {
681 return false;
684 for (int i = 0; i < repeat_count; i++) {
685 gesture_params->distances.push_back(distance);
686 gesture_params->distances.push_back(-distance + overscroll);
689 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
690 // progress, we will leak the callback and context. This needs to be fixed,
691 // somehow.
692 context.render_view_impl()->QueueSyntheticGesture(
693 gesture_params.Pass(),
694 base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
696 return true;
699 bool GpuBenchmarking::PinchBy(gin::Arguments* args) {
700 GpuBenchmarkingContext context;
701 if (!context.Init(false))
702 return false;
704 float scale_factor;
705 float anchor_x;
706 float anchor_y;
707 v8::Local<v8::Function> callback;
708 float relative_pointer_speed_in_pixels_s = 800;
711 if (!GetArg(args, &scale_factor) ||
712 !GetArg(args, &anchor_x) ||
713 !GetArg(args, &anchor_y) ||
714 !GetOptionalArg(args, &callback) ||
715 !GetOptionalArg(args, &relative_pointer_speed_in_pixels_s)) {
716 return false;
719 scoped_ptr<SyntheticPinchGestureParams> gesture_params(
720 new SyntheticPinchGestureParams);
722 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
723 float page_scale_factor = context.web_view()->pageScaleFactor();
725 gesture_params->scale_factor = scale_factor;
726 gesture_params->anchor.SetPoint(anchor_x * page_scale_factor,
727 anchor_y * page_scale_factor);
728 gesture_params->relative_pointer_speed_in_pixels_s =
729 relative_pointer_speed_in_pixels_s;
731 scoped_refptr<CallbackAndContext> callback_and_context =
732 new CallbackAndContext(args->isolate(),
733 callback,
734 context.web_frame()->mainWorldScriptContext());
737 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
738 // progress, we will leak the callback and context. This needs to be fixed,
739 // somehow.
740 context.render_view_impl()->QueueSyntheticGesture(
741 gesture_params.Pass(),
742 base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
744 return true;
747 bool GpuBenchmarking::Tap(gin::Arguments* args) {
748 GpuBenchmarkingContext context;
749 if (!context.Init(false))
750 return false;
752 float position_x;
753 float position_y;
754 v8::Local<v8::Function> callback;
755 int duration_ms = 50;
756 int gesture_source_type = SyntheticGestureParams::DEFAULT_INPUT;
758 if (!GetArg(args, &position_x) ||
759 !GetArg(args, &position_y) ||
760 !GetOptionalArg(args, &callback) ||
761 !GetOptionalArg(args, &duration_ms) ||
762 !GetOptionalArg(args, &gesture_source_type)) {
763 return false;
766 scoped_ptr<SyntheticTapGestureParams> gesture_params(
767 new SyntheticTapGestureParams);
769 // Convert coordinates from CSS pixels to density independent pixels (DIPs).
770 float page_scale_factor = context.web_view()->pageScaleFactor();
772 gesture_params->position.SetPoint(position_x * page_scale_factor,
773 position_y * page_scale_factor);
774 gesture_params->duration_ms = duration_ms;
776 if (gesture_source_type < 0 ||
777 gesture_source_type > SyntheticGestureParams::GESTURE_SOURCE_TYPE_MAX) {
778 return false;
780 gesture_params->gesture_source_type =
781 static_cast<SyntheticGestureParams::GestureSourceType>(
782 gesture_source_type);
784 scoped_refptr<CallbackAndContext> callback_and_context =
785 new CallbackAndContext(args->isolate(),
786 callback,
787 context.web_frame()->mainWorldScriptContext());
789 // TODO(nduca): If the render_view_impl is destroyed while the gesture is in
790 // progress, we will leak the callback and context. This needs to be fixed,
791 // somehow.
792 context.render_view_impl()->QueueSyntheticGesture(
793 gesture_params.Pass(),
794 base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
796 return true;
799 void GpuBenchmarking::ClearImageCache() {
800 WebImageCache::clear();
803 int GpuBenchmarking::RunMicroBenchmark(gin::Arguments* args) {
804 GpuBenchmarkingContext context;
805 if (!context.Init(true))
806 return 0;
808 std::string name;
809 v8::Local<v8::Function> callback;
810 v8::Local<v8::Object> arguments;
812 if (!GetArg(args, &name) || !GetArg(args, &callback) ||
813 !GetOptionalArg(args, &arguments)) {
814 return 0;
817 scoped_refptr<CallbackAndContext> callback_and_context =
818 new CallbackAndContext(args->isolate(),
819 callback,
820 context.web_frame()->mainWorldScriptContext());
822 scoped_ptr<V8ValueConverter> converter =
823 make_scoped_ptr(V8ValueConverter::create());
824 v8::Local<v8::Context> v8_context = callback_and_context->GetContext();
825 scoped_ptr<base::Value> value =
826 make_scoped_ptr(converter->FromV8Value(arguments, v8_context));
828 return context.compositor()->ScheduleMicroBenchmark(
829 name,
830 value.Pass(),
831 base::Bind(&OnMicroBenchmarkCompleted, callback_and_context));
834 bool GpuBenchmarking::SendMessageToMicroBenchmark(
835 int id,
836 v8::Local<v8::Object> message) {
837 GpuBenchmarkingContext context;
838 if (!context.Init(true))
839 return false;
841 scoped_ptr<V8ValueConverter> converter =
842 make_scoped_ptr(V8ValueConverter::create());
843 v8::Local<v8::Context> v8_context =
844 context.web_frame()->mainWorldScriptContext();
845 scoped_ptr<base::Value> value =
846 make_scoped_ptr(converter->FromV8Value(message, v8_context));
848 return context.compositor()->SendMessageToMicroBenchmark(id, value.Pass());
851 bool GpuBenchmarking::HasGpuProcess() {
852 GpuChannelHost* gpu_channel = RenderThreadImpl::current()->GetGpuChannel();
853 return !!gpu_channel;
856 } // namespace content