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(InstantiateWebLayer(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 694