2 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Collabora Ltd. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include "PluginView.h"
32 #include "DocumentLoader.h"
34 #include "EventNames.h"
35 #include "FrameLoader.h"
36 #include "FrameLoadRequest.h"
37 #include "FrameTree.h"
39 #include "FrameView.h"
40 #include "GraphicsContext.h"
42 #include "HTMLNames.h"
43 #include "HTMLPlugInElement.h"
44 #include "JSDOMWindow.h"
45 #include "KeyboardEvent.h"
46 #include "MIMETypeRegistry.h"
47 #include "MouseEvent.h"
49 #include "FocusController.h"
50 #include "PlatformMouseEvent.h"
51 #include "PluginMessageThrottlerWin.h"
52 #include "PluginPackage.h"
53 #include "PluginMainThreadScheduler.h"
54 #include "JSDOMBinding.h"
55 #include "ScriptController.h"
56 #include "PluginDatabase.h"
57 #include "PluginDebug.h"
58 #include "PluginPackage.h"
59 #include "c_instance.h"
60 #include "npruntime_impl.h"
61 #include "runtime_root.h"
64 #include <runtime/JSLock.h>
65 #include <runtime/JSValue.h>
66 #include <wtf/ASCIICType.h>
72 static inline HWND
windowHandleForPlatformWidget(PlatformWidget widget
)
77 return widget
->winId();
94 using namespace HTMLNames
;
96 const LPCWSTR kWebPluginViewdowClassName
= L
"WebPluginView";
97 const LPCWSTR kWebPluginViewProperty
= L
"WebPluginViewProperty";
99 static const char* MozillaUserAgent
= "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0";
101 // The code used to hook BeginPaint/EndPaint originally came from
102 // <http://www.fengyuan.com/article/wmprint.html>.
103 // Copyright (C) 2000 by Feng Yuan (www.fengyuan.com).
105 static unsigned beginPaintSysCall
;
106 static BYTE
* beginPaint
;
108 static unsigned endPaintSysCall
;
109 static BYTE
* endPaint
;
111 HDC WINAPI
PluginView::hookedBeginPaint(HWND hWnd
, PAINTSTRUCT
* lpPaint
)
113 #if (COMPILER(MINGW))
118 PluginView
* pluginView
= reinterpret_cast<PluginView
*>(GetProp(hWnd
, kWebPluginViewProperty
));
119 if (pluginView
&& pluginView
->m_wmPrintHDC
) {
120 // We're secretly handling WM_PRINTCLIENT, so set up the PAINTSTRUCT so
121 // that the plugin will paint into the HDC we provide.
122 memset(lpPaint
, 0, sizeof(PAINTSTRUCT
));
123 lpPaint
->hdc
= pluginView
->m_wmPrintHDC
;
124 GetClientRect(hWnd
, &lpPaint
->rcPaint
);
125 return pluginView
->m_wmPrintHDC
;
128 // Call through to the original BeginPaint.
129 __asm mov eax
, beginPaintSysCall
132 __asm call beginPaint
136 BOOL WINAPI
PluginView::hookedEndPaint(HWND hWnd
, const PAINTSTRUCT
* lpPaint
)
138 #if (COMPILER(MINGW))
143 PluginView
* pluginView
= reinterpret_cast<PluginView
*>(GetProp(hWnd
, kWebPluginViewProperty
));
144 if (pluginView
&& pluginView
->m_wmPrintHDC
) {
145 // We're secretly handling WM_PRINTCLIENT, so we don't have to do any
150 // Call through to the original EndPaint.
151 __asm mov eax
, endPaintSysCall
158 #if (!COMPILER(MINGW))
159 static void hook(const char* module
, const char* proc
, unsigned& sysCallID
, BYTE
*& pProc
, const void* pNewProc
)
161 // See <http://www.fengyuan.com/article/wmprint.html> for an explanation of
162 // how this function works.
164 HINSTANCE hMod
= GetModuleHandleA(module
);
166 pProc
= reinterpret_cast<BYTE
*>(GetProcAddress(hMod
, proc
));
168 if (pProc
[0] != 0xB8)
171 // FIXME: Should we be reading the bytes one-by-one instead of doing an
173 sysCallID
= *reinterpret_cast<unsigned*>(pProc
+ 1);
176 if (!VirtualProtect(pProc
, 5, PAGE_EXECUTE_READWRITE
, &flOldProtect
))
180 *reinterpret_cast<unsigned*>(pProc
+ 1) = reinterpret_cast<intptr_t>(pNewProc
) - reinterpret_cast<intptr_t>(pProc
+ 5);
185 static void setUpOffscreenPaintingHooks(HDC (WINAPI
*hookedBeginPaint
)(HWND
, PAINTSTRUCT
*), BOOL (WINAPI
*hookedEndPaint
)(HWND
, const PAINTSTRUCT
*))
187 static bool haveHooked
= false;
192 // Most (all?) windowed plugins don't seem to respond to WM_PRINTCLIENT, so
193 // we hook into BeginPaint/EndPaint to allow their normal WM_PAINT handling
194 // to draw into a given HDC. Note that this hooking affects the entire
196 hook("user32.dll", "BeginPaint", beginPaintSysCall
, beginPaint
, hookedBeginPaint
);
197 hook("user32.dll", "EndPaint", endPaintSysCall
, endPaint
, hookedEndPaint
);
201 static bool registerPluginView()
203 static bool haveRegisteredWindowClass
= false;
204 if (haveRegisteredWindowClass
)
207 haveRegisteredWindowClass
= true;
210 Page::setInstanceHandle((HINSTANCE
)(qWinAppInst()));
213 ASSERT(Page::instanceHandle());
217 wcex
.cbSize
= sizeof(WNDCLASSEX
);
219 wcex
.style
= CS_DBLCLKS
;
220 wcex
.lpfnWndProc
= DefWindowProc
;
223 wcex
.hInstance
= Page::instanceHandle();
225 wcex
.hCursor
= LoadCursor(0, IDC_ARROW
);
226 wcex
.hbrBackground
= (HBRUSH
)COLOR_WINDOW
;
227 wcex
.lpszMenuName
= 0;
228 wcex
.lpszClassName
= kWebPluginViewdowClassName
;
231 return !!RegisterClassEx(&wcex
);
234 LRESULT CALLBACK
PluginView::PluginViewWndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
236 PluginView
* pluginView
= reinterpret_cast<PluginView
*>(GetProp(hWnd
, kWebPluginViewProperty
));
238 return pluginView
->wndProc(hWnd
, message
, wParam
, lParam
);
241 static bool isWindowsMessageUserGesture(UINT message
)
255 PluginView::wndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
257 // <rdar://5711136> Sometimes Flash will call SetCapture before creating
258 // a full-screen window and will not release it, which causes the
259 // full-screen window to never receive mouse events. We set/release capture
260 // on mouse down/up before sending the event to the plug-in to prevent that.
274 if (message
== m_lastMessage
&&
275 m_plugin
->quirks().contains(PluginQuirkDontCallWndProcForSameMessageRecursively
) &&
276 m_isCallingPluginWndProc
)
279 if (message
== WM_USER
+ 1 &&
280 m_plugin
->quirks().contains(PluginQuirkThrottleWMUserPlusOneMessages
)) {
281 if (!m_messageThrottler
)
282 m_messageThrottler
.set(new PluginMessageThrottlerWin(this));
284 m_messageThrottler
->appendMessage(hWnd
, message
, wParam
, lParam
);
288 m_lastMessage
= message
;
289 m_isCallingPluginWndProc
= true;
291 // If the plug-in doesn't explicitly support changing the pop-up state, we enable
292 // popups for all user gestures.
293 // Note that we need to pop the state in a timer, because the Flash plug-in
294 // pops up windows in response to a posted message.
295 if (m_plugin
->pluginFuncs()->version
< NPVERS_HAS_POPUPS_ENABLED_STATE
&&
296 isWindowsMessageUserGesture(message
) && !m_popPopupsStateTimer
.isActive()) {
298 pushPopupsEnabledState(true);
300 m_popPopupsStateTimer
.startOneShot(0);
303 if (message
== WM_PRINTCLIENT
) {
304 // Most (all?) windowed plugins don't respond to WM_PRINTCLIENT, so we
305 // change the message to WM_PAINT and rely on our hooked versions of
306 // BeginPaint/EndPaint to make the plugin draw into the given HDC.
308 m_wmPrintHDC
= reinterpret_cast<HDC
>(wParam
);
311 // Call the plug-in's window proc.
312 LRESULT result
= ::CallWindowProc(m_pluginWndProc
, hWnd
, message
, wParam
, lParam
);
316 m_isCallingPluginWndProc
= false;
321 void PluginView::updatePluginWidget()
326 ASSERT(parent()->isFrameView());
327 FrameView
* frameView
= static_cast<FrameView
*>(parent());
329 IntRect oldWindowRect
= m_windowRect
;
330 IntRect oldClipRect
= m_clipRect
;
332 m_windowRect
= IntRect(frameView
->contentsToWindow(frameRect().location()), frameRect().size());
333 m_clipRect
= windowClipRect();
334 m_clipRect
.move(-m_windowRect
.x(), -m_windowRect
.y());
336 if (platformPluginWidget() && (m_windowRect
!= oldWindowRect
|| m_clipRect
!= oldClipRect
)) {
339 setCallingPlugin(true);
341 // To prevent flashes while scrolling, we disable drawing during the window
342 // update process by clipping the window to the zero rect.
344 bool clipToZeroRect
= !m_plugin
->quirks().contains(PluginQuirkDontClipToZeroRectWhenScrolling
);
346 if (clipToZeroRect
) {
347 rgn
= ::CreateRectRgn(0, 0, 0, 0);
348 ::SetWindowRgn(platformPluginWidget(), rgn
, FALSE
);
350 rgn
= ::CreateRectRgn(m_clipRect
.x(), m_clipRect
.y(), m_clipRect
.right(), m_clipRect
.bottom());
351 ::SetWindowRgn(platformPluginWidget(), rgn
, TRUE
);
354 if (m_windowRect
!= oldWindowRect
)
355 ::MoveWindow(platformPluginWidget(), m_windowRect
.x(), m_windowRect
.y(), m_windowRect
.width(), m_windowRect
.height(), TRUE
);
357 if (clipToZeroRect
) {
358 rgn
= ::CreateRectRgn(m_clipRect
.x(), m_clipRect
.y(), m_clipRect
.right(), m_clipRect
.bottom());
359 ::SetWindowRgn(platformPluginWidget(), rgn
, TRUE
);
362 setCallingPlugin(false);
366 void PluginView::setFocus()
368 if (platformPluginWidget())
369 SetFocus(platformPluginWidget());
374 void PluginView::show()
376 setSelfVisible(true);
378 if (isParentVisible() && platformPluginWidget())
379 ShowWindow(platformPluginWidget(), SW_SHOWNA
);
384 void PluginView::hide()
386 setSelfVisible(false);
388 if (isParentVisible() && platformPluginWidget())
389 ShowWindow(platformPluginWidget(), SW_HIDE
);
394 bool PluginView::dispatchNPEvent(NPEvent
& npEvent
)
396 if (!m_plugin
->pluginFuncs()->event
)
399 bool shouldPop
= false;
401 if (m_plugin
->pluginFuncs()->version
< NPVERS_HAS_POPUPS_ENABLED_STATE
&& isWindowsMessageUserGesture(npEvent
.event
)) {
402 pushPopupsEnabledState(true);
406 JSC::JSLock::DropAllLocks
dropAllLocks(false);
407 setCallingPlugin(true);
408 bool result
= m_plugin
->pluginFuncs()->event(m_instance
, &npEvent
);
409 setCallingPlugin(false);
412 popPopupsEnabledState();
417 void PluginView::paintWindowedPluginIntoContext(GraphicsContext
* context
, const IntRect
& rect
) const
419 ASSERT(m_isWindowed
);
420 ASSERT(context
->shouldIncludeChildWindows());
422 ASSERT(parent()->isFrameView());
423 IntPoint locationInWindow
= static_cast<FrameView
*>(parent())->contentsToWindow(frameRect().location());
425 HDC hdc
= context
->getWindowsContext(frameRect(), false);
427 XFORM originalTransform
;
428 GetWorldTransform(hdc
, &originalTransform
);
430 // The plugin expects the DC to be in client coordinates, so we translate
431 // the DC to make that so.
432 XFORM transform
= originalTransform
;
433 transform
.eDx
= locationInWindow
.x();
434 transform
.eDy
= locationInWindow
.y();
436 SetWorldTransform(hdc
, &transform
);
438 SendMessage(platformPluginWidget(), WM_PRINTCLIENT
, reinterpret_cast<WPARAM
>(hdc
), PRF_CLIENT
| PRF_CHILDREN
| PRF_OWNED
);
440 SetWorldTransform(hdc
, &originalTransform
);
442 context
->releaseWindowsContext(hdc
, frameRect(), false);
445 void PluginView::paint(GraphicsContext
* context
, const IntRect
& rect
)
448 // Draw the "missing plugin" image
449 paintMissingPluginIcon(context
, rect
);
453 if (context
->paintingDisabled())
457 if (context
->shouldIncludeChildWindows())
458 paintWindowedPluginIntoContext(context
, rect
);
462 ASSERT(parent()->isFrameView());
463 IntRect rectInWindow
= static_cast<FrameView
*>(parent())->contentsToWindow(frameRect());
464 HDC hdc
= context
->getWindowsContext(rectInWindow
, m_isTransparent
);
467 // On Safari/Windows without transparency layers the GraphicsContext returns the HDC
468 // of the window and the plugin expects that the passed in DC has window coordinates.
469 // In the Qt port we always draw in an offscreen buffer and therefore need to preserve
470 // the translation set in getWindowsContext.
472 if (!context
->inTransparencyLayer()) {
474 GetWorldTransform(hdc
, &transform
);
477 SetWorldTransform(hdc
, &transform
);
481 m_npWindow
.type
= NPWindowTypeDrawable
;
482 m_npWindow
.window
= hdc
;
484 IntPoint p
= static_cast<FrameView
*>(parent())->contentsToWindow(frameRect().location());
487 memset(&windowpos
, 0, sizeof(windowpos
));
491 windowpos
.cx
= frameRect().width();
492 windowpos
.cy
= frameRect().height();
494 npEvent
.event
= WM_WINDOWPOSCHANGED
;
495 npEvent
.lParam
= reinterpret_cast<uint32
>(&windowpos
);
498 dispatchNPEvent(npEvent
);
500 setNPWindowRect(frameRect());
502 npEvent
.event
= WM_PAINT
;
503 npEvent
.wParam
= reinterpret_cast<uint32
>(hdc
);
505 // This is supposed to be a pointer to the dirty rect, but it seems that the Flash plugin
506 // ignores it so we just pass null.
509 dispatchNPEvent(npEvent
);
511 context
->releaseWindowsContext(hdc
, frameRect(), m_isTransparent
);
514 void PluginView::handleKeyboardEvent(KeyboardEvent
* event
)
518 npEvent
.wParam
= event
->keyCode();
520 if (event
->type() == eventNames().keydownEvent
) {
521 npEvent
.event
= WM_KEYDOWN
;
523 } else if (event
->type() == eventNames().keyupEvent
) {
524 npEvent
.event
= WM_KEYUP
;
525 npEvent
.lParam
= 0x8000;
528 JSC::JSLock::DropAllLocks
dropAllLocks(false);
529 if (!dispatchNPEvent(npEvent
))
530 event
->setDefaultHandled();
533 extern HCURSOR lastSetCursor
;
534 extern bool ignoreNextSetCursor
;
536 void PluginView::handleMouseEvent(MouseEvent
* event
)
540 IntPoint p
= static_cast<FrameView
*>(parent())->contentsToWindow(IntPoint(event
->pageX(), event
->pageY()));
542 npEvent
.lParam
= MAKELPARAM(p
.x(), p
.y());
545 if (event
->ctrlKey())
546 npEvent
.wParam
|= MK_CONTROL
;
547 if (event
->shiftKey())
548 npEvent
.wParam
|= MK_SHIFT
;
550 if (event
->type() == eventNames().mousemoveEvent
||
551 event
->type() == eventNames().mouseoutEvent
||
552 event
->type() == eventNames().mouseoverEvent
) {
553 npEvent
.event
= WM_MOUSEMOVE
;
554 if (event
->buttonDown())
555 switch (event
->button()) {
557 npEvent
.wParam
|= MK_LBUTTON
;
560 npEvent
.wParam
|= MK_MBUTTON
;
563 npEvent
.wParam
|= MK_RBUTTON
;
567 else if (event
->type() == eventNames().mousedownEvent
) {
568 focusPluginElement();
569 switch (event
->button()) {
571 npEvent
.event
= WM_LBUTTONDOWN
;
574 npEvent
.event
= WM_MBUTTONDOWN
;
577 npEvent
.event
= WM_RBUTTONDOWN
;
580 } else if (event
->type() == eventNames().mouseupEvent
) {
581 switch (event
->button()) {
583 npEvent
.event
= WM_LBUTTONUP
;
586 npEvent
.event
= WM_MBUTTONUP
;
589 npEvent
.event
= WM_RBUTTONUP
;
595 JSC::JSLock::DropAllLocks
dropAllLocks(false);
596 if (!dispatchNPEvent(npEvent
))
597 event
->setDefaultHandled();
600 // Currently, Widget::setCursor is always called after this function in EventHandler.cpp
601 // and since we don't want that we set ignoreNextSetCursor to true here to prevent that.
602 ignoreNextSetCursor
= true;
603 lastSetCursor
= ::GetCursor();
607 void PluginView::setParent(ScrollView
* parent
)
609 Widget::setParent(parent
);
614 if (!platformPluginWidget())
617 // If the plug-in window or one of its children have the focus, we need to
618 // clear it to prevent the web view window from being focused because that can
619 // trigger a layout while the plugin element is being detached.
620 HWND focusedWindow
= ::GetFocus();
621 if (platformPluginWidget() == focusedWindow
|| ::IsChild(platformPluginWidget(), focusedWindow
))
627 void PluginView::setParentVisible(bool visible
)
629 if (isParentVisible() == visible
)
632 Widget::setParentVisible(visible
);
634 if (isSelfVisible() && platformPluginWidget()) {
636 ShowWindow(platformPluginWidget(), SW_SHOWNA
);
638 ShowWindow(platformPluginWidget(), SW_HIDE
);
642 void PluginView::setNPWindowRect(const IntRect
& rect
)
647 IntPoint p
= static_cast<FrameView
*>(parent())->contentsToWindow(rect
.location());
648 m_npWindow
.x
= p
.x();
649 m_npWindow
.y
= p
.y();
651 m_npWindow
.width
= rect
.width();
652 m_npWindow
.height
= rect
.height();
654 m_npWindow
.clipRect
.left
= 0;
655 m_npWindow
.clipRect
.top
= 0;
656 m_npWindow
.clipRect
.right
= rect
.width();
657 m_npWindow
.clipRect
.bottom
= rect
.height();
659 if (m_plugin
->pluginFuncs()->setwindow
) {
660 JSC::JSLock::DropAllLocks
dropAllLocks(false);
661 setCallingPlugin(true);
662 m_plugin
->pluginFuncs()->setwindow(m_instance
, &m_npWindow
);
663 setCallingPlugin(false);
668 ASSERT(platformPluginWidget());
670 WNDPROC currentWndProc
= (WNDPROC
)GetWindowLongPtr(platformPluginWidget(), GWLP_WNDPROC
);
671 if (currentWndProc
!= PluginViewWndProc
)
672 m_pluginWndProc
= (WNDPROC
)SetWindowLongPtr(platformPluginWidget(), GWLP_WNDPROC
, (LONG
)PluginViewWndProc
);
676 void PluginView::stop()
681 HashSet
<RefPtr
<PluginStream
> > streams
= m_streams
;
682 HashSet
<RefPtr
<PluginStream
> >::iterator end
= streams
.end();
683 for (HashSet
<RefPtr
<PluginStream
> >::iterator it
= streams
.begin(); it
!= end
; ++it
) {
685 disconnectStream((*it
).get());
688 ASSERT(m_streams
.isEmpty());
692 // Unsubclass the window
694 WNDPROC currentWndProc
= (WNDPROC
)GetWindowLongPtr(platformPluginWidget(), GWLP_WNDPROC
);
696 if (currentWndProc
== PluginViewWndProc
)
697 SetWindowLongPtr(platformPluginWidget(), GWLP_WNDPROC
, (LONG
)m_pluginWndProc
);
700 JSC::JSLock::DropAllLocks
dropAllLocks(false);
703 m_npWindow
.window
= 0;
704 if (m_plugin
->pluginFuncs()->setwindow
&& !m_plugin
->quirks().contains(PluginQuirkDontSetNullWindowHandleOnDestroy
)) {
705 setCallingPlugin(true);
706 m_plugin
->pluginFuncs()->setwindow(m_instance
, &m_npWindow
);
707 setCallingPlugin(false);
710 PluginMainThreadScheduler::scheduler().unregisterPlugin(m_instance
);
712 // Destroy the plugin
713 NPSavedData
* savedData
= 0;
714 setCallingPlugin(true);
715 NPError npErr
= m_plugin
->pluginFuncs()->destroy(m_instance
, &savedData
);
716 setCallingPlugin(false);
721 NPN_MemFree(savedData
->buf
);
722 NPN_MemFree(savedData
);
725 m_instance
->pdata
= 0;
728 const char* PluginView::userAgentStatic()
733 const char* PluginView::userAgent()
735 if (m_plugin
->quirks().contains(PluginQuirkWantsMozillaUserAgent
))
736 return MozillaUserAgent
;
738 if (m_userAgent
.isNull())
739 m_userAgent
= m_parentFrame
->loader()->userAgent(m_url
).utf8();
740 return m_userAgent
.data();
743 NPError
PluginView::handlePostReadFile(Vector
<char>& buffer
, uint32 len
, const char* buf
)
745 String
filename(buf
, len
);
747 if (filename
.startsWith("file:///"))
748 filename
= filename
.substring(8);
751 WIN32_FILE_ATTRIBUTE_DATA attrs
;
752 if (GetFileAttributesExW(filename
.charactersWithNullTermination(), GetFileExInfoStandard
, &attrs
) == 0)
753 return NPERR_FILE_NOT_FOUND
;
755 if (attrs
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
756 return NPERR_FILE_NOT_FOUND
;
758 HANDLE fileHandle
= CreateFileW(filename
.charactersWithNullTermination(), FILE_READ_DATA
, FILE_SHARE_READ
, 0, OPEN_EXISTING
, 0, 0);
760 if (fileHandle
== INVALID_HANDLE_VALUE
)
761 return NPERR_FILE_NOT_FOUND
;
763 buffer
.resize(attrs
.nFileSizeLow
);
766 int retval
= ReadFile(fileHandle
, buffer
.data(), attrs
.nFileSizeLow
, &bytesRead
, 0);
768 CloseHandle(fileHandle
);
770 if (retval
== 0 || bytesRead
!= attrs
.nFileSizeLow
)
771 return NPERR_FILE_NOT_FOUND
;
773 return NPERR_NO_ERROR
;
776 NPError
PluginView::getValueStatic(NPNVariable variable
, void* value
)
778 return NPERR_GENERIC_ERROR
;
781 NPError
PluginView::getValue(NPNVariable variable
, void* value
)
784 #if ENABLE(NETSCAPE_PLUGIN_API)
785 case NPNVWindowNPObject
: {
786 if (m_isJavaScriptPaused
)
787 return NPERR_GENERIC_ERROR
;
789 NPObject
* windowScriptObject
= m_parentFrame
->script()->windowScriptNPObject();
791 // Return value is expected to be retained, as described here: <http://www.mozilla.org/projects/plugin/npruntime.html>
792 if (windowScriptObject
)
793 _NPN_RetainObject(windowScriptObject
);
795 void** v
= (void**)value
;
796 *v
= windowScriptObject
;
798 return NPERR_NO_ERROR
;
801 case NPNVPluginElementNPObject
: {
802 if (m_isJavaScriptPaused
)
803 return NPERR_GENERIC_ERROR
;
805 NPObject
* pluginScriptObject
= 0;
807 if (m_element
->hasTagName(appletTag
) || m_element
->hasTagName(embedTag
) || m_element
->hasTagName(objectTag
))
808 pluginScriptObject
= static_cast<HTMLPlugInElement
*>(m_element
)->getNPObject();
810 // Return value is expected to be retained, as described here: <http://www.mozilla.org/projects/plugin/npruntime.html>
811 if (pluginScriptObject
)
812 _NPN_RetainObject(pluginScriptObject
);
814 void** v
= (void**)value
;
815 *v
= pluginScriptObject
;
817 return NPERR_NO_ERROR
;
821 case NPNVnetscapeWindow
: {
822 HWND
* w
= reinterpret_cast<HWND
*>(value
);
824 *w
= windowHandleForPlatformWidget(parent() ? parent()->hostWindow()->platformWindow() : 0);
826 return NPERR_NO_ERROR
;
829 case NPNVSupportsWindowless
: {
830 NPBool
*result
= reinterpret_cast<NPBool
*>(value
);
834 return NPERR_NO_ERROR
;
838 return NPERR_GENERIC_ERROR
;
842 void PluginView::invalidateRect(const IntRect
& rect
)
845 RECT invalidRect
= { rect
.x(), rect
.y(), rect
.right(), rect
.bottom() };
846 ::InvalidateRect(platformPluginWidget(), &invalidRect
, false);
850 invalidateWindowlessPluginRect(rect
);
853 void PluginView::invalidateRect(NPRect
* rect
)
860 IntRect
r(rect
->left
, rect
->top
, rect
->right
- rect
->left
, rect
->bottom
- rect
->top
);
863 RECT invalidRect
= { r
.x(), r
.y(), r
.right(), r
.bottom() };
864 InvalidateRect(platformPluginWidget(), &invalidRect
, FALSE
);
866 if (m_plugin
->quirks().contains(PluginQuirkThrottleInvalidate
)) {
867 m_invalidRects
.append(r
);
868 if (!m_invalidateTimer
.isActive())
869 m_invalidateTimer
.startOneShot(0.001);
875 void PluginView::invalidateRegion(NPRegion region
)
882 if (GetRgnBox(region
, &r
) == 0) {
887 IntRect
rect(IntPoint(r
.left
, r
.top
), IntSize(r
.right
-r
.left
, r
.bottom
-r
.top
));
888 invalidateRect(rect
);
891 void PluginView::forceRedraw()
894 ::UpdateWindow(platformPluginWidget());
896 ::UpdateWindow(windowHandleForPlatformWidget(parent() ? parent()->hostWindow()->platformWindow() : 0));
899 PluginView::~PluginView()
902 m_instance
->ndata
= 0;
905 deleteAllValues(m_requests
);
907 freeStringArray(m_paramNames
, m_paramCount
);
908 freeStringArray(m_paramValues
, m_paramCount
);
910 if (platformPluginWidget())
911 DestroyWindow(platformPluginWidget());
913 m_parentFrame
->script()->cleanupScriptObjectsForPlugin(this);
915 if (m_plugin
&& !m_plugin
->quirks().contains(PluginQuirkDontUnloadPlugin
))
919 void PluginView::init()
921 if (m_haveInitialized
)
923 m_haveInitialized
= true;
926 ASSERT(m_status
== PluginStatusCanNotFindPlugin
);
930 if (!m_plugin
->load()) {
932 m_status
= PluginStatusCanNotLoadPlugin
;
937 m_status
= PluginStatusCanNotLoadPlugin
;
942 registerPluginView();
943 #if (!COMPILER(MINGW))
944 setUpOffscreenPaintingHooks(hookedBeginPaint
, hookedEndPaint
);
946 DWORD flags
= WS_CHILD
;
950 HWND parentWindowHandle
= windowHandleForPlatformWidget(m_parentFrame
->view()->hostWindow()->platformWindow());
951 HWND window
= ::CreateWindowEx(0, kWebPluginViewdowClassName
, 0, flags
,
952 0, 0, 0, 0, parentWindowHandle
, 0, Page::instanceHandle(), 0);
953 #if PLATFORM(WIN_OS) && PLATFORM(QT)
956 setPlatformWidget(window
);
959 // Calling SetWindowLongPtrA here makes the window proc ASCII, which is required by at least
960 // the Shockwave Director plug-in.
961 #if PLATFORM(WIN_OS) && PLATFORM(X86_64) && COMPILER(MSVC)
962 ::SetWindowLongPtrA(platformPluginWidget(), GWLP_WNDPROC
, (LONG_PTR
)DefWindowProcA
);
964 ::SetWindowLongPtrA(platformPluginWidget(), GWL_WNDPROC
, (LONG
)DefWindowProcA
);
966 SetProp(platformPluginWidget(), kWebPluginViewProperty
, this);
968 m_npWindow
.type
= NPWindowTypeWindow
;
969 m_npWindow
.window
= platformPluginWidget();
971 m_npWindow
.type
= NPWindowTypeDrawable
;
972 m_npWindow
.window
= 0;
975 if (!m_plugin
->quirks().contains(PluginQuirkDeferFirstSetWindowCall
))
976 setNPWindowRect(frameRect());
978 m_status
= PluginStatusLoadedSuccessfully
;
981 } // namespace WebCore