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