2 * Copyright (C) 2009 Google Inc. All rights reserved.
3 * Copyright (C) 2014 Opera Software ASA. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
15 * * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include "web/WebPluginContainerImpl.h"
35 #include "bindings/core/v8/ScriptController.h"
36 #include "bindings/core/v8/ScriptSourceCode.h"
37 #include "bindings/core/v8/V8Element.h"
38 #include "bindings/core/v8/V8NPObject.h"
39 #include "core/HTMLNames.h"
40 #include "core/clipboard/DataObject.h"
41 #include "core/clipboard/DataTransfer.h"
42 #include "core/events/DragEvent.h"
43 #include "core/events/GestureEvent.h"
44 #include "core/events/KeyboardEvent.h"
45 #include "core/events/MouseEvent.h"
46 #include "core/events/TouchEvent.h"
47 #include "core/events/WheelEvent.h"
48 #include "core/frame/EventHandlerRegistry.h"
49 #include "core/frame/FrameView.h"
50 #include "core/frame/LocalFrame.h"
51 #include "core/html/HTMLFormElement.h"
52 #include "core/html/HTMLPlugInElement.h"
53 #include "core/input/EventHandler.h"
54 #include "core/layout/HitTestResult.h"
55 #include "core/layout/LayoutBox.h"
56 #include "core/layout/LayoutPart.h"
57 #include "core/loader/FrameLoadRequest.h"
58 #include "core/page/FocusController.h"
59 #include "core/page/Page.h"
60 #include "core/page/scrolling/ScrollingCoordinator.h"
61 #include "core/paint/DeprecatedPaintLayer.h"
62 #include "core/paint/LayoutObjectDrawingRecorder.h"
63 #include "modules/plugins/PluginOcclusionSupport.h"
64 #include "platform/HostWindow.h"
65 #include "platform/KeyboardCodes.h"
66 #include "platform/PlatformGestureEvent.h"
67 #include "platform/UserGestureIndicator.h"
68 #include "platform/exported/WrappedResourceResponse.h"
69 #include "platform/graphics/GraphicsContext.h"
70 #include "platform/graphics/GraphicsLayer.h"
71 #include "platform/scroll/ScrollAnimator.h"
72 #include "platform/scroll/ScrollbarTheme.h"
73 #include "public/platform/Platform.h"
74 #include "public/platform/WebClipboard.h"
75 #include "public/platform/WebCompositorSupport.h"
76 #include "public/platform/WebCursorInfo.h"
77 #include "public/platform/WebDragData.h"
78 #include "public/platform/WebExternalTextureLayer.h"
79 #include "public/platform/WebRect.h"
80 #include "public/platform/WebString.h"
81 #include "public/platform/WebURL.h"
82 #include "public/platform/WebURLError.h"
83 #include "public/platform/WebURLRequest.h"
84 #include "public/web/WebElement.h"
85 #include "public/web/WebInputEvent.h"
86 #include "public/web/WebPlugin.h"
87 #include "public/web/WebPrintParams.h"
88 #include "public/web/WebPrintPresetOptions.h"
89 #include "public/web/WebViewClient.h"
90 #include "web/ChromeClientImpl.h"
91 #include "web/WebDataSourceImpl.h"
92 #include "web/WebInputEventConversion.h"
93 #include "web/WebViewImpl.h"
94 #include "wtf/Assertions.h"
98 // Public methods --------------------------------------------------------------
100 void WebPluginContainerImpl::setFrameRect(const IntRect
& frameRect
)
102 Widget::setFrameRect(frameRect
);
106 void WebPluginContainerImpl::layoutIfNeeded()
108 RELEASE_ASSERT(m_webPlugin
);
109 m_webPlugin
->layoutIfNeeded();
112 void WebPluginContainerImpl::paint(GraphicsContext
* context
, const IntRect
& rect
)
117 // Don't paint anything if the plugin doesn't intersect.
118 if (!frameRect().intersects(rect
))
121 if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*context
, *m_element
->layoutObject(), DisplayItem::Type::WebPlugin
, LayoutPoint()))
124 LayoutObjectDrawingRecorder
drawingRecorder(*context
, *m_element
->layoutObject(), DisplayItem::Type::WebPlugin
, rect
, LayoutPoint());
127 ASSERT(parent()->isFrameView());
128 FrameView
* view
= toFrameView(parent());
130 // The plugin is positioned in the root frame's coordinates, so it needs to
131 // be painted in them too.
132 IntPoint origin
= view
->contentsToRootFrame(IntPoint(0, 0));
133 context
->translate(static_cast<float>(-origin
.x()), static_cast<float>(-origin
.y()));
135 WebCanvas
* canvas
= context
->canvas();
137 IntRect windowRect
= view
->contentsToRootFrame(rect
);
138 m_webPlugin
->paint(canvas
, windowRect
);
143 void WebPluginContainerImpl::invalidateRect(const IntRect
& rect
)
148 LayoutBox
* layoutObject
= toLayoutBox(m_element
->layoutObject());
152 IntRect dirtyRect
= rect
;
154 layoutObject
->borderLeft() + layoutObject
->paddingLeft(),
155 layoutObject
->borderTop() + layoutObject
->paddingTop());
157 m_pendingInvalidationRect
.unite(dirtyRect
);
159 layoutObject
->setMayNeedPaintInvalidation();
162 void WebPluginContainerImpl::setFocus(bool focused
, WebFocusType focusType
)
164 Widget::setFocus(focused
, focusType
);
165 m_webPlugin
->updateFocus(focused
, focusType
);
168 void WebPluginContainerImpl::show()
170 setSelfVisible(true);
171 m_webPlugin
->updateVisibility(true);
176 void WebPluginContainerImpl::hide()
178 setSelfVisible(false);
179 m_webPlugin
->updateVisibility(false);
184 void WebPluginContainerImpl::handleEvent(Event
* event
)
186 if (!m_webPlugin
->acceptsInputEvents())
189 RefPtrWillBeRawPtr
<WebPluginContainerImpl
> protector(this);
190 // The events we pass are defined at:
191 // http://devedge-temp.mozilla.org/library/manuals/2002/plugin/1.0/structures5.html#1000000
192 // Don't take the documentation as truth, however. There are many cases
193 // where mozilla behaves differently than the spec.
194 if (event
->isMouseEvent())
195 handleMouseEvent(toMouseEvent(event
));
196 else if (event
->isWheelEvent())
197 handleWheelEvent(toWheelEvent(event
));
198 else if (event
->isKeyboardEvent())
199 handleKeyboardEvent(toKeyboardEvent(event
));
200 else if (event
->isTouchEvent())
201 handleTouchEvent(toTouchEvent(event
));
202 else if (event
->isGestureEvent())
203 handleGestureEvent(toGestureEvent(event
));
204 else if (event
->isDragEvent() && m_webPlugin
->canProcessDrag())
205 handleDragEvent(toDragEvent(event
));
207 // FIXME: it would be cleaner if Widget::handleEvent returned true/false and
208 // HTMLPluginElement called setDefaultHandled or defaultEventHandler.
209 if (!event
->defaultHandled())
210 m_element
->Node::defaultEventHandler(event
);
213 void WebPluginContainerImpl::frameRectsChanged()
215 Widget::frameRectsChanged();
219 void WebPluginContainerImpl::widgetPositionsUpdated()
221 Widget::widgetPositionsUpdated();
225 void WebPluginContainerImpl::eventListenersRemoved()
227 // We're no longer registered to receive touch events, so don't try to remove
228 // the touch event handlers in our destructor.
229 m_touchEventRequestType
= TouchEventRequestTypeNone
;
232 void WebPluginContainerImpl::setParentVisible(bool parentVisible
)
234 // We override this function to make sure that geometry updates are sent
235 // over to the plugin. For e.g. when a plugin is instantiated it does not
236 // have a valid parent. As a result the first geometry update from webkit
237 // is ignored. This function is called when the plugin eventually gets a
240 if (isParentVisible() == parentVisible
)
241 return; // No change.
243 Widget::setParentVisible(parentVisible
);
244 if (!isSelfVisible())
245 return; // This widget has explicitely been marked as not visible.
248 m_webPlugin
->updateVisibility(isVisible());
251 void WebPluginContainerImpl::setParent(Widget
* widget
)
253 // We override this function so that if the plugin is windowed, we can call
254 // NPP_SetWindow at the first possible moment. This ensures that
255 // NPP_SetWindow is called before the manual load data is sent to a plugin.
256 // If this order is reversed, Flash won't load videos.
258 Widget::setParent(widget
);
261 else if (m_webPlugin
)
262 m_webPlugin
->containerDidDetachFromParent();
265 void WebPluginContainerImpl::setPlugin(WebPlugin
* plugin
)
267 if (plugin
!= m_webPlugin
) {
268 m_element
->resetInstance();
269 m_webPlugin
= plugin
;
273 float WebPluginContainerImpl::deviceScaleFactor()
275 Page
* page
= m_element
->document().page();
278 return page
->deviceScaleFactor();
281 float WebPluginContainerImpl::pageScaleFactor()
283 Page
* page
= m_element
->document().page();
286 return page
->pageScaleFactor();
289 float WebPluginContainerImpl::pageZoomFactor()
291 LocalFrame
* frame
= m_element
->document().frame();
294 return frame
->pageZoomFactor();
297 void WebPluginContainerImpl::setWebLayer(WebLayer
* layer
)
299 if (m_webLayer
== layer
)
303 GraphicsLayer::unregisterContentsLayer(m_webLayer
);
305 GraphicsLayer::registerContentsLayer(layer
);
307 // If either of the layers is null we need to switch between hardware
308 // and software compositing.
309 bool needsCompositingUpdate
= !m_webLayer
|| !layer
;
313 if (!needsCompositingUpdate
)
321 m_element
->setNeedsCompositingUpdate();
324 bool WebPluginContainerImpl::supportsPaginatedPrint() const
326 return m_webPlugin
->supportsPaginatedPrint();
329 bool WebPluginContainerImpl::isPrintScalingDisabled() const
331 return m_webPlugin
->isPrintScalingDisabled();
334 bool WebPluginContainerImpl::getPrintPresetOptionsFromDocument(WebPrintPresetOptions
* presetOptions
) const
336 return m_webPlugin
->getPrintPresetOptionsFromDocument(presetOptions
);
339 int WebPluginContainerImpl::printBegin(const WebPrintParams
& printParams
) const
341 return m_webPlugin
->printBegin(printParams
);
344 void WebPluginContainerImpl::printPage(int pageNumber
, GraphicsContext
* gc
, const IntRect
& printRect
)
346 if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*gc
, *m_element
->layoutObject(), DisplayItem::Type::WebPlugin
, LayoutPoint()))
349 LayoutObjectDrawingRecorder
drawingRecorder(*gc
, *m_element
->layoutObject(), DisplayItem::Type::WebPlugin
, printRect
, LayoutPoint());
351 WebCanvas
* canvas
= gc
->canvas();
352 m_webPlugin
->printPage(pageNumber
, canvas
);
356 void WebPluginContainerImpl::printEnd()
358 m_webPlugin
->printEnd();
361 void WebPluginContainerImpl::copy()
363 if (!m_webPlugin
->hasSelection())
366 Platform::current()->clipboard()->writeHTML(m_webPlugin
->selectionAsMarkup(), WebURL(), m_webPlugin
->selectionAsText(), false);
369 bool WebPluginContainerImpl::executeEditCommand(const WebString
& name
)
371 if (m_webPlugin
->executeEditCommand(name
))
381 bool WebPluginContainerImpl::executeEditCommand(const WebString
& name
, const WebString
& value
)
383 return m_webPlugin
->executeEditCommand(name
, value
);
386 WebElement
WebPluginContainerImpl::element()
388 return WebElement(m_element
);
391 void WebPluginContainerImpl::invalidate()
393 Widget::invalidate();
396 void WebPluginContainerImpl::invalidateRect(const WebRect
& rect
)
398 invalidateRect(static_cast<IntRect
>(rect
));
401 void WebPluginContainerImpl::scrollRect(const WebRect
& rect
)
403 invalidateRect(rect
);
406 void WebPluginContainerImpl::setNeedsLayout()
408 if (m_element
->layoutObject())
409 m_element
->layoutObject()->setNeedsLayoutAndFullPaintInvalidation("Plugin needs layout");
412 void WebPluginContainerImpl::reportGeometry()
414 // We cannot compute geometry without a parent or layoutObject.
415 if (!parent() || !m_element
|| !m_element
->layoutObject())
418 IntRect windowRect
, clipRect
, unobscuredRect
;
419 Vector
<IntRect
> cutOutRects
;
420 calculateGeometry(windowRect
, clipRect
, unobscuredRect
, cutOutRects
);
422 m_webPlugin
->updateGeometry(windowRect
, clipRect
, unobscuredRect
, cutOutRects
, isVisible());
425 void WebPluginContainerImpl::allowScriptObjects()
429 void WebPluginContainerImpl::clearScriptObjects()
434 frame()->script().cleanupScriptObjectsForPlugin(this);
437 NPObject
* WebPluginContainerImpl::scriptableObjectForElement()
439 return m_element
->getNPObject();
442 v8::Local
<v8::Object
> WebPluginContainerImpl::v8ObjectForElement()
444 LocalFrame
* frame
= m_element
->document().frame();
446 return v8::Local
<v8::Object
>();
448 if (!frame
->script().canExecuteScripts(NotAboutToExecuteScript
))
449 return v8::Local
<v8::Object
>();
451 ScriptState
* scriptState
= ScriptState::forMainWorld(frame
);
452 if (!scriptState
->contextIsValid())
453 return v8::Local
<v8::Object
>();
455 v8::Local
<v8::Value
> v8value
= toV8(m_element
.get(), scriptState
->context()->Global(), scriptState
->isolate());
456 if (v8value
.IsEmpty())
457 return v8::Local
<v8::Object
>();
458 ASSERT(v8value
->IsObject());
460 return v8::Local
<v8::Object
>::Cast(v8value
);
463 WebString
WebPluginContainerImpl::executeScriptURL(const WebURL
& url
, bool popupsAllowed
)
465 LocalFrame
* frame
= m_element
->document().frame();
469 const KURL
& kurl
= url
;
470 ASSERT(kurl
.protocolIs("javascript"));
472 String script
= decodeURLEscapeSequences(
473 kurl
.string().substring(strlen("javascript:")));
475 UserGestureIndicator
gestureIndicator(popupsAllowed
? DefinitelyProcessingNewUserGesture
: PossiblyProcessingUserGesture
);
476 v8::HandleScope
handleScope(toIsolate(frame
));
477 v8::Local
<v8::Value
> result
= frame
->script().executeScriptInMainWorldAndReturnValue(ScriptSourceCode(script
));
479 // Failure is reported as a null string.
480 if (result
.IsEmpty() || !result
->IsString())
482 return toCoreString(v8::Local
<v8::String
>::Cast(result
));
485 void WebPluginContainerImpl::loadFrameRequest(const WebURLRequest
& request
, const WebString
& target
, bool notifyNeeded
, void* notifyData
)
487 LocalFrame
* frame
= m_element
->document().frame();
488 if (!frame
|| !frame
->loader().documentLoader())
489 return; // FIXME: send a notification in this case?
492 // FIXME: This is a bit of hack to allow us to observe completion of
493 // our frame request. It would be better to evolve FrameLoader to
494 // support a completion callback instead.
495 OwnPtr
<WebPluginLoadObserver
> observer
= adoptPtr(new WebPluginLoadObserver(this, request
.url(), notifyData
));
496 // FIXME: Calling get here is dangerous! What if observer is freed?
497 m_pluginLoadObservers
.append(observer
.get());
498 WebDataSourceImpl::setNextPluginLoadObserver(observer
.release());
501 FrameLoadRequest
frameRequest(frame
->document(), request
.toResourceRequest(), target
);
502 frame
->loader().load(frameRequest
);
505 bool WebPluginContainerImpl::isRectTopmost(const WebRect
& rect
)
507 // Disallow access to the frame during dispose(), because it is not guaranteed to
508 // be valid memory once this object has started disposal. In particular, we might be being
509 // disposed because the frame has already be deleted and then something else dropped the
510 // last reference to the this object.
511 if (m_inDispose
|| !m_element
)
514 LocalFrame
* frame
= m_element
->document().frame();
518 IntRect
documentRect(x() + rect
.x
, y() + rect
.y
, rect
.width
, rect
.height
);
519 // hitTestResultAtPoint() takes a padding rectangle.
520 // FIXME: We'll be off by 1 when the width or height is even.
521 LayoutPoint center
= documentRect
.center();
522 // Make the rect we're checking (the point surrounded by padding rects) contained inside the requested rect. (Note that -1/2 is 0.)
523 LayoutSize
padding((documentRect
.width() - 1) / 2, (documentRect
.height() - 1) / 2);
524 HitTestResult result
= frame
->eventHandler().hitTestResultAtPoint(center
, HitTestRequest::ReadOnly
| HitTestRequest::Active
| HitTestRequest::ListBased
, padding
);
525 const HitTestResult::NodeSet
& nodes
= result
.listBasedTestResult();
526 if (nodes
.size() != 1)
528 return nodes
.first().get() == m_element
;
531 void WebPluginContainerImpl::requestTouchEventType(TouchEventRequestType requestType
)
533 if (m_touchEventRequestType
== requestType
)
536 if (m_element
->document().frameHost()) {
537 EventHandlerRegistry
& registry
= m_element
->document().frameHost()->eventHandlerRegistry();
538 if (requestType
!= TouchEventRequestTypeNone
&& m_touchEventRequestType
== TouchEventRequestTypeNone
)
539 registry
.didAddEventHandler(*m_element
, EventHandlerRegistry::TouchEvent
);
540 else if (requestType
== TouchEventRequestTypeNone
&& m_touchEventRequestType
!= TouchEventRequestTypeNone
)
541 registry
.didRemoveEventHandler(*m_element
, EventHandlerRegistry::TouchEvent
);
543 m_touchEventRequestType
= requestType
;
546 void WebPluginContainerImpl::setWantsWheelEvents(bool wantsWheelEvents
)
548 if (m_wantsWheelEvents
== wantsWheelEvents
)
550 m_wantsWheelEvents
= wantsWheelEvents
;
551 if (Page
* page
= m_element
->document().page()) {
552 if (ScrollingCoordinator
* scrollingCoordinator
= page
->scrollingCoordinator()) {
553 if (parent() && parent()->isFrameView())
554 scrollingCoordinator
->notifyLayoutUpdated();
559 WebPoint
WebPluginContainerImpl::rootFrameToLocalPoint(const WebPoint
& pointInRootFrame
)
561 FrameView
* view
= toFrameView(parent());
563 return pointInRootFrame
;
564 WebPoint pointInContent
= view
->rootFrameToContents(pointInRootFrame
);
565 return roundedIntPoint(m_element
->layoutObject()->absoluteToLocal(FloatPoint(pointInContent
), UseTransforms
));
568 WebPoint
WebPluginContainerImpl::localToRootFramePoint(const WebPoint
& pointInLocal
)
570 FrameView
* view
= toFrameView(parent());
573 IntPoint absolutePoint
= roundedIntPoint(m_element
->layoutObject()->localToAbsolute(FloatPoint(pointInLocal
), UseTransforms
));
574 return view
->contentsToRootFrame(absolutePoint
);
577 void WebPluginContainerImpl::didReceiveResponse(const ResourceResponse
& response
)
579 // Make sure that the plugin receives window geometry before data, or else
580 // plugins misbehave.
583 WrappedResourceResponse
urlResponse(response
);
584 m_webPlugin
->didReceiveResponse(urlResponse
);
587 void WebPluginContainerImpl::didReceiveData(const char *data
, int dataLength
)
589 m_webPlugin
->didReceiveData(data
, dataLength
);
592 void WebPluginContainerImpl::didFinishLoading()
594 m_webPlugin
->didFinishLoading();
597 void WebPluginContainerImpl::didFailLoading(const ResourceError
& error
)
599 m_webPlugin
->didFailLoading(error
);
602 WebLayer
* WebPluginContainerImpl::platformLayer() const
607 v8::Local
<v8::Object
> WebPluginContainerImpl::scriptableObject(v8::Isolate
* isolate
)
610 // With Oilpan, on plugin element detach dispose() will be called to safely
611 // clear out references, including the pre-emptive destruction of the plugin.
613 // It clearly has no scriptable object if in such a disposed state.
615 return v8::Local
<v8::Object
>();
618 // The plugin may be destroyed due to re-entrancy when calling
619 // v8ScriptableObject below. crbug.com/458776. Hold a reference to the
620 // plugin container to prevent this from happening. For Oilpan, 'this'
621 // is already stack reachable, so redundant.
622 RefPtrWillBeRawPtr
<WebPluginContainerImpl
> protector(this);
624 v8::Local
<v8::Object
> object
= m_webPlugin
->v8ScriptableObject(isolate
);
626 // If the plugin has been destroyed and the reference on the stack is the
627 // only one left, then don't return the scriptable object.
633 return v8::Local
<v8::Object
>();
635 if (!object
.IsEmpty()) {
636 // WebPlugin implementation can't provide the obsolete NPObject at the same time:
637 ASSERT(!m_webPlugin
->scriptableObject());
641 NPObject
* npObject
= m_webPlugin
->scriptableObject();
643 return createV8ObjectForNPObject(isolate
, npObject
, 0);
644 return v8::Local
<v8::Object
>();
647 bool WebPluginContainerImpl::getFormValue(String
& value
)
650 if (m_webPlugin
->getFormValue(webValue
)) {
657 bool WebPluginContainerImpl::supportsKeyboardFocus() const
659 return m_webPlugin
->supportsKeyboardFocus();
662 bool WebPluginContainerImpl::supportsInputMethod() const
664 return m_webPlugin
->supportsInputMethod();
667 bool WebPluginContainerImpl::canProcessDrag() const
669 return m_webPlugin
->canProcessDrag();
672 bool WebPluginContainerImpl::wantsWheelEvents()
674 return m_wantsWheelEvents
;
677 void WebPluginContainerImpl::willDestroyPluginLoadObserver(WebPluginLoadObserver
* observer
)
679 size_t pos
= m_pluginLoadObservers
.find(observer
);
680 if (pos
== kNotFound
)
682 m_pluginLoadObservers
.remove(pos
);
685 // Private methods -------------------------------------------------------------
687 WebPluginContainerImpl::WebPluginContainerImpl(HTMLPlugInElement
* element
, WebPlugin
* webPlugin
)
688 : LocalFrameLifecycleObserver(element
->document().frame())
690 , m_webPlugin(webPlugin
)
691 , m_webLayer(nullptr)
692 , m_touchEventRequestType(TouchEventRequestTypeNone
)
693 , m_wantsWheelEvents(false)
696 , m_shouldDisposePlugin(false)
701 WebPluginContainerImpl::~WebPluginContainerImpl()
704 if (m_shouldDisposePlugin
)
706 // The plugin container must have been disposed of by now.
707 ASSERT(!m_webPlugin
);
713 void WebPluginContainerImpl::dispose()
717 if (m_element
&& m_touchEventRequestType
!= TouchEventRequestTypeNone
&& m_element
->document().frameHost())
718 m_element
->document().frameHost()->eventHandlerRegistry().didRemoveEventHandler(*m_element
, EventHandlerRegistry::TouchEvent
);
720 for (size_t i
= 0; i
< m_pluginLoadObservers
.size(); ++i
)
721 m_pluginLoadObservers
[i
]->clearPluginContainer();
724 m_webPlugin
->destroy();
725 m_webPlugin
= nullptr;
728 GraphicsLayer::unregisterContentsLayer(m_webLayer
);
729 m_webLayer
= nullptr;
732 m_pluginLoadObservers
.clear();
737 void WebPluginContainerImpl::shouldDisposePlugin()
739 // If the LocalFrame is still alive, but the plugin element isn't, the
740 // LocalFrame will set m_shouldDisposePlugin via its weak pointer
741 // callback. This is a signal that the plugin container
742 // must dispose of its plugin when finalizing. The LocalFrame and
743 // all objects accessible from it can safely be accessed, but not
744 // the plugin element itself.
745 ASSERT(!m_shouldDisposePlugin
);
746 m_shouldDisposePlugin
= true;
751 DEFINE_TRACE(WebPluginContainerImpl
)
753 visitor
->trace(m_element
);
754 LocalFrameLifecycleObserver::trace(visitor
);
755 PluginView::trace(visitor
);
758 void WebPluginContainerImpl::handleMouseEvent(MouseEvent
* event
)
760 ASSERT(parent()->isFrameView());
762 // We cache the parent FrameView here as the plugin widget could be deleted
763 // in the call to HandleEvent. See http://b/issue?id=1362948
764 FrameView
* parentView
= toFrameView(parent());
766 WebMouseEventBuilder
webEvent(this, m_element
->layoutObject(), *event
);
767 if (webEvent
.type
== WebInputEvent::Undefined
)
770 if (event
->type() == EventTypeNames::mousedown
)
773 WebCursorInfo cursorInfo
;
774 if (m_webPlugin
->handleInputEvent(webEvent
, cursorInfo
))
775 event
->setDefaultHandled();
777 // A windowless plugin can change the cursor in response to a mouse move
778 // event. We need to reflect the changed cursor in the frame view as the
779 // mouse is moved in the boundaries of the windowless plugin.
780 Page
* page
= parentView
->frame().page();
783 toChromeClientImpl(page
->chromeClient()).setCursorForPlugin(cursorInfo
);
786 void WebPluginContainerImpl::handleDragEvent(MouseEvent
* event
)
788 ASSERT(event
->isDragEvent());
790 WebDragStatus dragStatus
= WebDragStatusUnknown
;
791 if (event
->type() == EventTypeNames::dragenter
)
792 dragStatus
= WebDragStatusEnter
;
793 else if (event
->type() == EventTypeNames::dragleave
)
794 dragStatus
= WebDragStatusLeave
;
795 else if (event
->type() == EventTypeNames::dragover
)
796 dragStatus
= WebDragStatusOver
;
797 else if (event
->type() == EventTypeNames::drop
)
798 dragStatus
= WebDragStatusDrop
;
800 if (dragStatus
== WebDragStatusUnknown
)
803 DataTransfer
* dataTransfer
= event
->dataTransfer();
804 WebDragData dragData
= dataTransfer
->dataObject()->toWebDragData();
805 WebDragOperationsMask dragOperationMask
= static_cast<WebDragOperationsMask
>(dataTransfer
->sourceOperation());
806 WebPoint
dragScreenLocation(event
->screenX(), event
->screenY());
807 WebPoint
dragLocation(event
->absoluteLocation().x() - location().x(), event
->absoluteLocation().y() - location().y());
809 m_webPlugin
->handleDragStatusUpdate(dragStatus
, dragData
, dragOperationMask
, dragLocation
, dragScreenLocation
);
812 void WebPluginContainerImpl::handleWheelEvent(WheelEvent
* event
)
814 WebMouseWheelEventBuilder
webEvent(this, m_element
->layoutObject(), *event
);
815 if (webEvent
.type
== WebInputEvent::Undefined
)
818 WebCursorInfo cursorInfo
;
819 if (m_webPlugin
->handleInputEvent(webEvent
, cursorInfo
))
820 event
->setDefaultHandled();
823 void WebPluginContainerImpl::handleKeyboardEvent(KeyboardEvent
* event
)
825 WebKeyboardEventBuilder
webEvent(*event
);
826 if (webEvent
.type
== WebInputEvent::Undefined
)
829 if (webEvent
.type
== WebInputEvent::KeyDown
) {
831 if (webEvent
.modifiers
== WebInputEvent::MetaKey
833 if (webEvent
.modifiers
== WebInputEvent::ControlKey
835 && (webEvent
.windowsKeyCode
== VKEY_C
|| webEvent
.windowsKeyCode
== VKEY_INSERT
)
836 // Only copy if there's a selection, so that we only ever do this
837 // for Pepper plugins that support copying. Windowless NPAPI
838 // plugins will get the event as before.
839 && m_webPlugin
->hasSelection()) {
841 event
->setDefaultHandled();
846 const WebInputEvent
* currentInputEvent
= WebViewImpl::currentInputEvent();
848 // Copy stashed info over, and only copy here in order not to interfere
849 // the ctrl-c logic above.
850 if (currentInputEvent
851 && WebInputEvent::isKeyboardEventType(currentInputEvent
->type
)) {
852 webEvent
.modifiers
|= currentInputEvent
->modifiers
&
853 (WebInputEvent::CapsLockOn
| WebInputEvent::NumLockOn
);
856 // Give the client a chance to issue edit comamnds.
857 WebViewImpl
* view
= WebViewImpl::fromPage(m_element
->document().frame()->page());
858 if (m_webPlugin
->supportsEditCommands() && view
->client())
859 view
->client()->handleCurrentKeyboardEvent();
861 WebCursorInfo cursorInfo
;
862 if (m_webPlugin
->handleInputEvent(webEvent
, cursorInfo
))
863 event
->setDefaultHandled();
866 void WebPluginContainerImpl::handleTouchEvent(TouchEvent
* event
)
868 switch (m_touchEventRequestType
) {
869 case TouchEventRequestTypeNone
:
871 case TouchEventRequestTypeRaw
: {
872 WebTouchEventBuilder
webEvent(m_element
->layoutObject(), *event
);
873 if (webEvent
.type
== WebInputEvent::Undefined
)
876 if (event
->type() == EventTypeNames::touchstart
)
879 WebCursorInfo cursorInfo
;
880 if (m_webPlugin
->handleInputEvent(webEvent
, cursorInfo
))
881 event
->setDefaultHandled();
882 // FIXME: Can a plugin change the cursor from a touch-event callback?
885 case TouchEventRequestTypeSynthesizedMouse
:
886 synthesizeMouseEventIfPossible(event
);
891 void WebPluginContainerImpl::handleGestureEvent(GestureEvent
* event
)
893 WebGestureEventBuilder
webEvent(m_element
->layoutObject(), *event
);
894 if (webEvent
.type
== WebInputEvent::Undefined
)
896 if (event
->type() == EventTypeNames::gesturetapdown
)
898 WebCursorInfo cursorInfo
;
899 if (m_webPlugin
->handleInputEvent(webEvent
, cursorInfo
)) {
900 event
->setDefaultHandled();
904 // FIXME: Can a plugin change the cursor from a touch-event callback?
907 void WebPluginContainerImpl::synthesizeMouseEventIfPossible(TouchEvent
* event
)
909 WebMouseEventBuilder
webEvent(this, m_element
->layoutObject(), *event
);
910 if (webEvent
.type
== WebInputEvent::Undefined
)
913 WebCursorInfo cursorInfo
;
914 if (m_webPlugin
->handleInputEvent(webEvent
, cursorInfo
))
915 event
->setDefaultHandled();
918 void WebPluginContainerImpl::focusPlugin()
920 LocalFrame
& containingFrame
= toFrameView(parent())->frame();
921 if (Page
* currentPage
= containingFrame
.page())
922 currentPage
->focusController().setFocusedElement(m_element
, &containingFrame
);
924 containingFrame
.document()->setFocusedElement(m_element
);
927 void WebPluginContainerImpl::issuePaintInvalidations()
929 if (m_pendingInvalidationRect
.isEmpty())
932 LayoutBox
* layoutObject
= toLayoutBox(m_element
->layoutObject());
936 layoutObject
->invalidatePaintRectangle(LayoutRect(m_pendingInvalidationRect
));
937 m_pendingInvalidationRect
= IntRect();
940 void WebPluginContainerImpl::calculateGeometry(IntRect
& windowRect
, IntRect
& clipRect
, IntRect
& unobscuredRect
, Vector
<IntRect
>& cutOutRects
)
942 windowRect
= toFrameView(parent())->contentsToRootFrame(frameRect());
944 // Calculate a clip-rect so that we don't overlap the scrollbars, etc.
945 clipRect
= convertToContainingWindow(IntRect(0, 0, width(), height()));
946 unobscuredRect
= clipRect
;
948 // document().layoutView() can be 0 when we receive messages from the
949 // plugins while we are destroying a frame.
950 // FIXME: Can we just check m_element->document().isActive() ?
951 if (m_element
->layoutObject()->document().layoutView()) {
952 // Take our element and get the clip rect from the enclosing layer and
954 IntRect elementUnobscuredRect
;
955 IntRect elementWindowClipRect
= m_element
->document().view()->clipRectsForFrameOwner(m_element
, &elementUnobscuredRect
);
956 clipRect
.intersect(elementWindowClipRect
);
957 unobscuredRect
.intersect(elementUnobscuredRect
);
960 clipRect
.move(-windowRect
.x(), -windowRect
.y());
961 unobscuredRect
.move(-windowRect
.x(), -windowRect
.y());
963 getPluginOcclusions(m_element
, this->parent(), frameRect(), cutOutRects
);
964 // Convert to the plugin position.
965 for (size_t i
= 0; i
< cutOutRects
.size(); i
++)
966 cutOutRects
[i
].move(-frameRect().x(), -frameRect().y());