Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / content / shell / renderer / test_runner / TestPlugin.cpp
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/shell/renderer/test_runner/TestPlugin.h"
6
7 #include "base/basictypes.h"
8 #include "base/bind.h"
9 #include "base/logging.h"
10 #include "base/memory/shared_memory.h"
11 #include "content/public/renderer/render_thread.h"
12 #include "content/shell/renderer/test_runner/TestCommon.h"
13 #include "content/shell/renderer/test_runner/WebTestDelegate.h"
14 #include "third_party/skia/include/core/SkBitmap.h"
15 #include "third_party/skia/include/core/SkCanvas.h"
16 #include "third_party/skia/include/core/SkColor.h"
17 #include "third_party/WebKit/public/platform/Platform.h"
18 #include "third_party/WebKit/public/platform/WebCompositorSupport.h"
19 #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
20 #include "third_party/WebKit/public/web/WebFrame.h"
21 #include "third_party/WebKit/public/web/WebInputEvent.h"
22 #include "third_party/WebKit/public/web/WebKit.h"
23 #include "third_party/WebKit/public/web/WebPluginParams.h"
24 #include "third_party/WebKit/public/web/WebTouchPoint.h"
25 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
26
27 using namespace blink;
28 using namespace std;
29
30 namespace content {
31
32 namespace {
33
34 // GLenum values copied from gl2.h.
35 #define GL_FALSE                  0
36 #define GL_TRUE                   1
37 #define GL_ONE                    1
38 #define GL_TRIANGLES              0x0004
39 #define GL_ONE_MINUS_SRC_ALPHA    0x0303
40 #define GL_DEPTH_TEST             0x0B71
41 #define GL_BLEND                  0x0BE2
42 #define GL_SCISSOR_TEST           0x0B90
43 #define GL_TEXTURE_2D             0x0DE1
44 #define GL_FLOAT                  0x1406
45 #define GL_RGBA                   0x1908
46 #define GL_UNSIGNED_BYTE          0x1401
47 #define GL_TEXTURE_MAG_FILTER     0x2800
48 #define GL_TEXTURE_MIN_FILTER     0x2801
49 #define GL_TEXTURE_WRAP_S         0x2802
50 #define GL_TEXTURE_WRAP_T         0x2803
51 #define GL_NEAREST                0x2600
52 #define GL_COLOR_BUFFER_BIT       0x4000
53 #define GL_CLAMP_TO_EDGE          0x812F
54 #define GL_ARRAY_BUFFER           0x8892
55 #define GL_STATIC_DRAW            0x88E4
56 #define GL_FRAGMENT_SHADER        0x8B30
57 #define GL_VERTEX_SHADER          0x8B31
58 #define GL_COMPILE_STATUS         0x8B81
59 #define GL_LINK_STATUS            0x8B82
60 #define GL_COLOR_ATTACHMENT0      0x8CE0
61 #define GL_FRAMEBUFFER_COMPLETE   0x8CD5
62 #define GL_FRAMEBUFFER            0x8D40
63
64 void premultiplyAlpha(const unsigned colorIn[3], float alpha, float colorOut[4])
65 {
66     for (int i = 0; i < 3; ++i)
67         colorOut[i] = (colorIn[i] / 255.0f) * alpha;
68
69     colorOut[3] = alpha;
70 }
71
72 const char* pointState(WebTouchPoint::State state)
73 {
74     switch (state) {
75     case WebTouchPoint::StateReleased:
76         return "Released";
77     case WebTouchPoint::StatePressed:
78         return "Pressed";
79     case WebTouchPoint::StateMoved:
80         return "Moved";
81     case WebTouchPoint::StateCancelled:
82         return "Cancelled";
83     default:
84         return "Unknown";
85     }
86 }
87
88 void printTouchList(WebTestDelegate* delegate, const WebTouchPoint* points, int length)
89 {
90     for (int i = 0; i < length; ++i) {
91         char buffer[100];
92         snprintf(buffer,
93                  sizeof(buffer),
94                  "* %.2f, %.2f: %s\n",
95                  points[i].position.x,
96                  points[i].position.y,
97                  pointState(points[i].state));
98         delegate->printMessage(buffer);
99     }
100 }
101
102 void printEventDetails(WebTestDelegate* delegate, const WebInputEvent& event)
103 {
104     if (WebInputEvent::isTouchEventType(event.type)) {
105         const WebTouchEvent& touch = static_cast<const WebTouchEvent&>(event);
106         printTouchList(delegate, touch.touches, touch.touchesLength);
107         printTouchList(delegate, touch.changedTouches, touch.changedTouchesLength);
108         printTouchList(delegate, touch.targetTouches, touch.targetTouchesLength);
109     } else if (WebInputEvent::isMouseEventType(event.type) || event.type == WebInputEvent::MouseWheel) {
110         const WebMouseEvent& mouse = static_cast<const WebMouseEvent&>(event);
111         char buffer[100];
112         snprintf(buffer, sizeof(buffer), "* %d, %d\n", mouse.x, mouse.y);
113         delegate->printMessage(buffer);
114     } else if (WebInputEvent::isGestureEventType(event.type)) {
115         const WebGestureEvent& gesture = static_cast<const WebGestureEvent&>(event);
116         char buffer[100];
117         snprintf(buffer, sizeof(buffer), "* %d, %d\n", gesture.x, gesture.y);
118         delegate->printMessage(buffer);
119     }
120 }
121
122 WebPluginContainer::TouchEventRequestType parseTouchEventRequestType(const WebString& string)
123 {
124     if (string == WebString::fromUTF8("raw"))
125         return WebPluginContainer::TouchEventRequestTypeRaw;
126     if (string == WebString::fromUTF8("synthetic"))
127         return WebPluginContainer::TouchEventRequestTypeSynthesizedMouse;
128     return WebPluginContainer::TouchEventRequestTypeNone;
129 }
130
131 void deferredDelete(void* context)
132 {
133     TestPlugin* plugin = static_cast<TestPlugin*>(context);
134     delete plugin;
135 }
136
137 }
138
139 TestPlugin::TestPlugin(WebFrame* frame, const WebPluginParams& params, WebTestDelegate* delegate)
140     : m_frame(frame)
141     , m_delegate(delegate)
142     , m_container(0)
143     , m_context(0)
144     , m_colorTexture(0)
145     , m_mailboxChanged(false)
146     , m_framebuffer(0)
147     , m_touchEventRequest(WebPluginContainer::TouchEventRequestTypeNone)
148     , m_reRequestTouchEvents(false)
149     , m_printEventDetails(false)
150     , m_printUserGestureStatus(false)
151     , m_canProcessDrag(false)
152     , m_isPersistent(params.mimeType == pluginPersistsMimeType())
153     , m_canCreateWithoutRenderer(params.mimeType == canCreateWithoutRendererMimeType())
154 {
155     const CR_DEFINE_STATIC_LOCAL(WebString, kAttributePrimitive, ("primitive"));
156     const CR_DEFINE_STATIC_LOCAL(WebString, kAttributeBackgroundColor, ("background-color"));
157     const CR_DEFINE_STATIC_LOCAL(WebString, kAttributePrimitiveColor, ("primitive-color"));
158     const CR_DEFINE_STATIC_LOCAL(WebString, kAttributeOpacity, ("opacity"));
159     const CR_DEFINE_STATIC_LOCAL(WebString, kAttributeAcceptsTouch, ("accepts-touch"));
160     const CR_DEFINE_STATIC_LOCAL(WebString, kAttributeReRequestTouchEvents, ("re-request-touch"));
161     const CR_DEFINE_STATIC_LOCAL(WebString, kAttributePrintEventDetails, ("print-event-details"));
162     const CR_DEFINE_STATIC_LOCAL(WebString, kAttributeCanProcessDrag, ("can-process-drag"));
163     const CR_DEFINE_STATIC_LOCAL(WebString, kAttributePrintUserGestureStatus, ("print-user-gesture-status"));
164
165     DCHECK_EQ(params.attributeNames.size(), params.attributeValues.size());
166     size_t size = params.attributeNames.size();
167     for (size_t i = 0; i < size; ++i) {
168         const WebString& attributeName = params.attributeNames[i];
169         const WebString& attributeValue = params.attributeValues[i];
170
171         if (attributeName == kAttributePrimitive)
172             m_scene.primitive = parsePrimitive(attributeValue);
173         else if (attributeName == kAttributeBackgroundColor)
174             parseColor(attributeValue, m_scene.backgroundColor);
175         else if (attributeName == kAttributePrimitiveColor)
176             parseColor(attributeValue, m_scene.primitiveColor);
177         else if (attributeName == kAttributeOpacity)
178             m_scene.opacity = parseOpacity(attributeValue);
179         else if (attributeName == kAttributeAcceptsTouch)
180             m_touchEventRequest = parseTouchEventRequestType(attributeValue);
181         else if (attributeName == kAttributeReRequestTouchEvents)
182             m_reRequestTouchEvents = parseBoolean(attributeValue);
183         else if (attributeName == kAttributePrintEventDetails)
184             m_printEventDetails = parseBoolean(attributeValue);
185         else if (attributeName == kAttributeCanProcessDrag)
186             m_canProcessDrag = parseBoolean(attributeValue);
187         else if (attributeName == kAttributePrintUserGestureStatus)
188             m_printUserGestureStatus = parseBoolean(attributeValue);
189     }
190     if (m_canCreateWithoutRenderer)
191         m_delegate->printMessage(std::string("TestPlugin: canCreateWithoutRenderer\n"));
192 }
193
194 TestPlugin::~TestPlugin()
195 {
196 }
197
198 bool TestPlugin::initialize(WebPluginContainer* container)
199 {
200     WebGraphicsContext3D::Attributes attrs;
201     m_context = Platform::current()->createOffscreenGraphicsContext3D(attrs);
202     if (m_context && !m_context->makeContextCurrent()) {
203         delete m_context;
204         m_context = 0;
205     }
206
207     if (!initScene())
208         return false;
209
210     m_layer = cc::TextureLayer::CreateForMailbox(this);
211     m_webLayer = make_scoped_ptr(new webkit::WebLayerImpl(m_layer));
212     m_container = container;
213     m_container->setWebLayer(m_webLayer.get());
214     if (m_reRequestTouchEvents) {
215         m_container->requestTouchEventType(WebPluginContainer::TouchEventRequestTypeSynthesizedMouse);
216         m_container->requestTouchEventType(WebPluginContainer::TouchEventRequestTypeRaw);
217     }
218     m_container->requestTouchEventType(m_touchEventRequest);
219     m_container->setWantsWheelEvents(true);
220     return true;
221 }
222
223 void TestPlugin::destroy()
224 {
225     if (m_layer.get())
226         m_layer->ClearTexture();
227     if (m_container)
228         m_container->setWebLayer(0);
229     m_webLayer.reset();
230     m_layer = NULL;
231     destroyScene();
232
233     delete m_context;
234     m_context = 0;
235
236     m_container = 0;
237     m_frame = 0;
238
239     Platform::current()->callOnMainThread(deferredDelete, this);
240 }
241
242 NPObject* TestPlugin::scriptableObject()
243 {
244     return 0;
245 }
246
247 bool TestPlugin::canProcessDrag() const
248 {
249     return m_canProcessDrag;
250 }
251
252 void TestPlugin::updateGeometry(const WebRect& frameRect, const WebRect& clipRect, const WebVector<WebRect>& cutOutsRects, bool isVisible)
253 {
254     if (clipRect == m_rect)
255         return;
256     m_rect = clipRect;
257
258     if (m_rect.isEmpty()) {
259         m_textureMailbox = cc::TextureMailbox();
260     } else if (m_context) {
261         m_context->viewport(0, 0, m_rect.width, m_rect.height);
262
263         m_context->bindTexture(GL_TEXTURE_2D, m_colorTexture);
264         m_context->texParameteri(
265             GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
266         m_context->texParameteri(
267             GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
268         m_context->texParameteri(
269             GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
270         m_context->texParameteri(
271             GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
272         m_context->texImage2D(GL_TEXTURE_2D,
273                               0,
274                               GL_RGBA,
275                               m_rect.width,
276                               m_rect.height,
277                               0,
278                               GL_RGBA,
279                               GL_UNSIGNED_BYTE,
280                               0);
281         m_context->bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
282         m_context->framebufferTexture2D(GL_FRAMEBUFFER,
283                                         GL_COLOR_ATTACHMENT0,
284                                         GL_TEXTURE_2D,
285                                         m_colorTexture,
286                                         0);
287
288         drawSceneGL();
289
290         gpu::Mailbox mailbox;
291         m_context->genMailboxCHROMIUM(mailbox.name);
292         m_context->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
293         m_context->flush();
294         uint32 syncPoint = m_context->insertSyncPoint();
295         m_textureMailbox = cc::TextureMailbox(mailbox, GL_TEXTURE_2D, syncPoint);
296     } else {
297         size_t bytes = 4 * m_rect.width * m_rect.height;
298         scoped_ptr<base::SharedMemory> bitmap =
299             RenderThread::Get()->HostAllocateSharedMemoryBuffer(bytes);
300         if (!bitmap->Map(bytes)) {
301             m_textureMailbox = cc::TextureMailbox();
302         } else {
303             drawSceneSoftware(bitmap->memory(), bytes);
304             m_textureMailbox = cc::TextureMailbox(
305                 bitmap.get(), gfx::Size(m_rect.width, m_rect.height));
306             m_sharedBitmap = bitmap.Pass();
307         }
308     }
309
310     m_mailboxChanged = true;
311     m_layer->SetNeedsDisplay();
312 }
313
314 bool TestPlugin::acceptsInputEvents()
315 {
316     return true;
317 }
318
319 bool TestPlugin::isPlaceholder()
320 {
321     return false;
322 }
323
324 static void ignoreReleaseCallback(uint32 sync_point, bool lost) {}
325
326 static void releaseSharedMemory(scoped_ptr<base::SharedMemory> bitmap,
327                                 uint32 sync_point,
328                                 bool lost) {}
329
330 bool TestPlugin::PrepareTextureMailbox(
331     cc::TextureMailbox* mailbox,
332     scoped_ptr<cc::SingleReleaseCallback>* releaseCallback,
333     bool useSharedMemory) {
334     if (!m_mailboxChanged)
335         return false;
336     *mailbox = m_textureMailbox;
337     if (m_textureMailbox.IsTexture()) {
338       *releaseCallback =
339           cc::SingleReleaseCallback::Create(base::Bind(&ignoreReleaseCallback));
340     } else {
341       *releaseCallback = cc::SingleReleaseCallback::Create(
342           base::Bind(&releaseSharedMemory, base::Passed(&m_sharedBitmap)));
343     }
344     m_mailboxChanged = false;
345     return true;
346 }
347
348 TestPlugin::Primitive TestPlugin::parsePrimitive(const WebString& string)
349 {
350     const CR_DEFINE_STATIC_LOCAL(WebString, kPrimitiveNone, ("none"));
351     const CR_DEFINE_STATIC_LOCAL(WebString, kPrimitiveTriangle, ("triangle"));
352
353     Primitive primitive = PrimitiveNone;
354     if (string == kPrimitiveNone)
355         primitive = PrimitiveNone;
356     else if (string == kPrimitiveTriangle)
357         primitive = PrimitiveTriangle;
358     else
359         NOTREACHED();
360     return primitive;
361 }
362
363 // FIXME: This method should already exist. Use it.
364 // For now just parse primary colors.
365 void TestPlugin::parseColor(const WebString& string, unsigned color[3])
366 {
367     color[0] = color[1] = color[2] = 0;
368     if (string == "black")
369         return;
370
371     if (string == "red")
372         color[0] = 255;
373     else if (string == "green")
374         color[1] = 255;
375     else if (string == "blue")
376         color[2] = 255;
377     else
378         NOTREACHED();
379 }
380
381 float TestPlugin::parseOpacity(const WebString& string)
382 {
383     return static_cast<float>(atof(string.utf8().data()));
384 }
385
386 bool TestPlugin::parseBoolean(const WebString& string)
387 {
388     const CR_DEFINE_STATIC_LOCAL(WebString, kPrimitiveTrue, ("true"));
389     return string == kPrimitiveTrue;
390 }
391
392 bool TestPlugin::initScene()
393 {
394     if (!m_context)
395         return true;
396
397     float color[4];
398     premultiplyAlpha(m_scene.backgroundColor, m_scene.opacity, color);
399
400     m_colorTexture = m_context->createTexture();
401     m_framebuffer = m_context->createFramebuffer();
402
403     m_context->viewport(0, 0, m_rect.width, m_rect.height);
404     m_context->disable(GL_DEPTH_TEST);
405     m_context->disable(GL_SCISSOR_TEST);
406
407     m_context->clearColor(color[0], color[1], color[2], color[3]);
408
409     m_context->enable(GL_BLEND);
410     m_context->blendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
411
412     return m_scene.primitive != PrimitiveNone ? initProgram() && initPrimitive() : true;
413 }
414
415 void TestPlugin::drawSceneGL() {
416     m_context->viewport(0, 0, m_rect.width, m_rect.height);
417     m_context->clear(GL_COLOR_BUFFER_BIT);
418
419     if (m_scene.primitive != PrimitiveNone)
420         drawPrimitive();
421 }
422
423 void TestPlugin::drawSceneSoftware(void* memory, size_t bytes) {
424     DCHECK_EQ(bytes, m_rect.width * m_rect.height * 4u);
425
426     SkColor backgroundColor =
427             SkColorSetARGB(static_cast<uint8>(m_scene.opacity * 255),
428                            m_scene.backgroundColor[0],
429                            m_scene.backgroundColor[1],
430                            m_scene.backgroundColor[2]);
431
432     SkBitmap bitmap;
433     bitmap.setConfig(SkBitmap::kARGB_8888_Config, m_rect.width, m_rect.height);
434     bitmap.setPixels(memory);
435     SkCanvas canvas(bitmap);
436     canvas.clear(backgroundColor);
437
438     if (m_scene.primitive != PrimitiveNone) {
439         DCHECK_EQ(PrimitiveTriangle, m_scene.primitive);
440         SkColor foregroundColor =
441                 SkColorSetARGB(static_cast<uint8>(m_scene.opacity * 255),
442                                m_scene.primitiveColor[0],
443                                m_scene.primitiveColor[1],
444                                m_scene.primitiveColor[2]);
445         SkPath trianglePath;
446         trianglePath.moveTo(0.5f * m_rect.width, 0.9f * m_rect.height);
447         trianglePath.lineTo(0.1f * m_rect.width, 0.1f * m_rect.height);
448         trianglePath.lineTo(0.9f * m_rect.width, 0.1f * m_rect.height);
449         SkPaint paint;
450         paint.setColor(foregroundColor);
451         paint.setStyle(SkPaint::kFill_Style);
452         canvas.drawPath(trianglePath, paint);
453     }
454 }
455
456 void TestPlugin::destroyScene()
457 {
458     if (m_scene.program) {
459         m_context->deleteProgram(m_scene.program);
460         m_scene.program = 0;
461     }
462     if (m_scene.vbo) {
463         m_context->deleteBuffer(m_scene.vbo);
464         m_scene.vbo = 0;
465     }
466
467     if (m_framebuffer) {
468         m_context->deleteFramebuffer(m_framebuffer);
469         m_framebuffer = 0;
470     }
471
472     if (m_colorTexture) {
473         m_context->deleteTexture(m_colorTexture);
474         m_colorTexture = 0;
475     }
476 }
477
478 bool TestPlugin::initProgram()
479 {
480     const string vertexSource(
481         "attribute vec4 position;  \n"
482         "void main() {             \n"
483         "  gl_Position = position; \n"
484         "}                         \n"
485     );
486
487     const string fragmentSource(
488         "precision mediump float; \n"
489         "uniform vec4 color;      \n"
490         "void main() {            \n"
491         "  gl_FragColor = color;  \n"
492         "}                        \n"
493     );
494
495     m_scene.program = loadProgram(vertexSource, fragmentSource);
496     if (!m_scene.program)
497         return false;
498
499     m_scene.colorLocation = m_context->getUniformLocation(m_scene.program, "color");
500     m_scene.positionLocation = m_context->getAttribLocation(m_scene.program, "position");
501     return true;
502 }
503
504 bool TestPlugin::initPrimitive()
505 {
506     DCHECK_EQ(m_scene.primitive, PrimitiveTriangle);
507
508     m_scene.vbo = m_context->createBuffer();
509     if (!m_scene.vbo)
510         return false;
511
512     const float vertices[] = {
513         0.0f,  0.8f, 0.0f,
514         -0.8f, -0.8f, 0.0f,
515         0.8f, -0.8f, 0.0f };
516     m_context->bindBuffer(GL_ARRAY_BUFFER, m_scene.vbo);
517     m_context->bufferData(GL_ARRAY_BUFFER, sizeof(vertices), 0, GL_STATIC_DRAW);
518     m_context->bufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
519     return true;
520 }
521
522 void TestPlugin::drawPrimitive()
523 {
524     DCHECK_EQ(m_scene.primitive, PrimitiveTriangle);
525     DCHECK(m_scene.vbo);
526     DCHECK(m_scene.program);
527
528     m_context->useProgram(m_scene.program);
529
530     // Bind primitive color.
531     float color[4];
532     premultiplyAlpha(m_scene.primitiveColor, m_scene.opacity, color);
533     m_context->uniform4f(m_scene.colorLocation, color[0], color[1], color[2], color[3]);
534
535     // Bind primitive vertices.
536     m_context->bindBuffer(GL_ARRAY_BUFFER, m_scene.vbo);
537     m_context->enableVertexAttribArray(m_scene.positionLocation);
538     m_context->vertexAttribPointer(m_scene.positionLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
539     m_context->drawArrays(GL_TRIANGLES, 0, 3);
540 }
541
542 unsigned TestPlugin::loadShader(unsigned type, const string& source)
543 {
544     unsigned shader = m_context->createShader(type);
545     if (shader) {
546         m_context->shaderSource(shader, source.data());
547         m_context->compileShader(shader);
548
549         int compiled = 0;
550         m_context->getShaderiv(shader, GL_COMPILE_STATUS, &compiled);
551         if (!compiled) {
552             m_context->deleteShader(shader);
553             shader = 0;
554         }
555     }
556     return shader;
557 }
558
559 unsigned TestPlugin::loadProgram(const string& vertexSource, const string& fragmentSource)
560 {
561     unsigned vertexShader = loadShader(GL_VERTEX_SHADER, vertexSource);
562     unsigned fragmentShader = loadShader(GL_FRAGMENT_SHADER, fragmentSource);
563     unsigned program = m_context->createProgram();
564     if (vertexShader && fragmentShader && program) {
565         m_context->attachShader(program, vertexShader);
566         m_context->attachShader(program, fragmentShader);
567         m_context->linkProgram(program);
568
569         int linked = 0;
570         m_context->getProgramiv(program, GL_LINK_STATUS, &linked);
571         if (!linked) {
572             m_context->deleteProgram(program);
573             program = 0;
574         }
575     }
576     if (vertexShader)
577         m_context->deleteShader(vertexShader);
578     if (fragmentShader)
579         m_context->deleteShader(fragmentShader);
580
581     return program;
582 }
583
584 bool TestPlugin::handleInputEvent(const WebInputEvent& event, WebCursorInfo& info)
585 {
586     const char* eventName = 0;
587     switch (event.type) {
588     case WebInputEvent::Undefined:           eventName = "unknown"; break;
589
590     case WebInputEvent::MouseDown:           eventName = "MouseDown"; break;
591     case WebInputEvent::MouseUp:             eventName = "MouseUp"; break;
592     case WebInputEvent::MouseMove:           eventName = "MouseMove"; break;
593     case WebInputEvent::MouseEnter:          eventName = "MouseEnter"; break;
594     case WebInputEvent::MouseLeave:          eventName = "MouseLeave"; break;
595     case WebInputEvent::ContextMenu:         eventName = "ContextMenu"; break;
596
597     case WebInputEvent::MouseWheel:          eventName = "MouseWheel"; break;
598
599     case WebInputEvent::RawKeyDown:          eventName = "RawKeyDown"; break;
600     case WebInputEvent::KeyDown:             eventName = "KeyDown"; break;
601     case WebInputEvent::KeyUp:               eventName = "KeyUp"; break;
602     case WebInputEvent::Char:                eventName = "Char"; break;
603
604     case WebInputEvent::GestureScrollBegin:  eventName = "GestureScrollBegin"; break;
605     case WebInputEvent::GestureScrollEnd:    eventName = "GestureScrollEnd"; break;
606     case WebInputEvent::GestureScrollUpdateWithoutPropagation:
607     case WebInputEvent::GestureScrollUpdate: eventName = "GestureScrollUpdate"; break;
608     case WebInputEvent::GestureFlingStart:   eventName = "GestureFlingStart"; break;
609     case WebInputEvent::GestureFlingCancel:  eventName = "GestureFlingCancel"; break;
610     case WebInputEvent::GestureTap:          eventName = "GestureTap"; break;
611     case WebInputEvent::GestureTapUnconfirmed:
612                                              eventName = "GestureTapUnconfirmed"; break;
613     case WebInputEvent::GestureTapDown:      eventName = "GestureTapDown"; break;
614     case WebInputEvent::GestureShowPress:    eventName = "GestureShowPress"; break;
615     case WebInputEvent::GestureTapCancel:    eventName = "GestureTapCancel"; break;
616     case WebInputEvent::GestureDoubleTap:    eventName = "GestureDoubleTap"; break;
617     case WebInputEvent::GestureTwoFingerTap: eventName = "GestureTwoFingerTap"; break;
618     case WebInputEvent::GestureLongPress:    eventName = "GestureLongPress"; break;
619     case WebInputEvent::GestureLongTap:      eventName = "GestureLongTap"; break;
620     case WebInputEvent::GesturePinchBegin:   eventName = "GesturePinchBegin"; break;
621     case WebInputEvent::GesturePinchEnd:     eventName = "GesturePinchEnd"; break;
622     case WebInputEvent::GesturePinchUpdate:  eventName = "GesturePinchUpdate"; break;
623
624     case WebInputEvent::TouchStart:          eventName = "TouchStart"; break;
625     case WebInputEvent::TouchMove:           eventName = "TouchMove"; break;
626     case WebInputEvent::TouchEnd:            eventName = "TouchEnd"; break;
627     case WebInputEvent::TouchCancel:         eventName = "TouchCancel"; break;
628     }
629
630     m_delegate->printMessage(std::string("Plugin received event: ") + (eventName ? eventName : "unknown") + "\n");
631     if (m_printEventDetails)
632         printEventDetails(m_delegate, event);
633     if (m_printUserGestureStatus)
634         m_delegate->printMessage(std::string("* ") + (WebUserGestureIndicator::isProcessingUserGesture() ? "" : "not ") + "handling user gesture\n");
635     if (m_isPersistent)
636         m_delegate->printMessage(std::string("TestPlugin: isPersistent\n"));
637     return false;
638 }
639
640 bool TestPlugin::handleDragStatusUpdate(WebDragStatus dragStatus, const WebDragData&, WebDragOperationsMask, const WebPoint& position, const WebPoint& screenPosition)
641 {
642     const char* dragStatusName = 0;
643     switch (dragStatus) {
644     case WebDragStatusEnter:
645         dragStatusName = "DragEnter";
646         break;
647     case WebDragStatusOver:
648         dragStatusName = "DragOver";
649         break;
650     case WebDragStatusLeave:
651         dragStatusName = "DragLeave";
652         break;
653     case WebDragStatusDrop:
654         dragStatusName = "DragDrop";
655         break;
656     case WebDragStatusUnknown:
657         NOTREACHED();
658     }
659     m_delegate->printMessage(std::string("Plugin received event: ") + dragStatusName + "\n");
660     return false;
661 }
662
663 TestPlugin* TestPlugin::create(WebFrame* frame, const WebPluginParams& params, WebTestDelegate* delegate)
664 {
665     return new TestPlugin(frame, params, delegate);
666 }
667
668 const WebString& TestPlugin::mimeType()
669 {
670     const CR_DEFINE_STATIC_LOCAL(WebString, kMimeType, ("application/x-webkit-test-webplugin"));
671     return kMimeType;
672 }
673
674 const WebString& TestPlugin::canCreateWithoutRendererMimeType()
675 {
676     const CR_DEFINE_STATIC_LOCAL(WebString, kCanCreateWithoutRendererMimeType, ("application/x-webkit-test-webplugin-can-create-without-renderer"));
677     return kCanCreateWithoutRendererMimeType;
678 }
679
680 const WebString& TestPlugin::pluginPersistsMimeType()
681 {
682     const CR_DEFINE_STATIC_LOCAL(WebString, kPluginPersistsMimeType, ("application/x-webkit-test-webplugin-persistent"));
683     return kPluginPersistsMimeType;
684 }
685
686 bool TestPlugin::isSupportedMimeType(const WebString& mimeType)
687 {
688     return mimeType == TestPlugin::mimeType()
689            || mimeType == pluginPersistsMimeType()
690            || mimeType == canCreateWithoutRendererMimeType();
691 }
692
693 }  // namespace content