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