diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-05 14:34:32 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-05 14:34:32 -0800 |
commit | 635860845790a19bf50bbc51ba8fb66a96dde068 (patch) | |
tree | ef6ad9ff73a5b57f65249d4232a202fa77e6a140 /WebCore/plugins/win | |
parent | 8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2 (diff) | |
download | external_webkit-635860845790a19bf50bbc51ba8fb66a96dde068.zip external_webkit-635860845790a19bf50bbc51ba8fb66a96dde068.tar.gz external_webkit-635860845790a19bf50bbc51ba8fb66a96dde068.tar.bz2 |
auto import from //depot/cupcake/@136594
Diffstat (limited to 'WebCore/plugins/win')
-rw-r--r-- | WebCore/plugins/win/PluginPackageWin.cpp | 5 | ||||
-rw-r--r-- | WebCore/plugins/win/PluginViewWin.cpp | 157 |
2 files changed, 136 insertions, 26 deletions
diff --git a/WebCore/plugins/win/PluginPackageWin.cpp b/WebCore/plugins/win/PluginPackageWin.cpp index d2c26e2..fe9b544 100644 --- a/WebCore/plugins/win/PluginPackageWin.cpp +++ b/WebCore/plugins/win/PluginPackageWin.cpp @@ -162,13 +162,14 @@ void PluginPackage::determineQuirks(const String& mimeType) bool PluginPackage::fetchInfo() { DWORD versionInfoSize, zeroHandle; - versionInfoSize = GetFileVersionInfoSizeW(m_path.charactersWithNullTermination(), &zeroHandle); + versionInfoSize = GetFileVersionInfoSizeW(const_cast<UChar*>(m_path.charactersWithNullTermination()), &zeroHandle); if (versionInfoSize == 0) return false; OwnArrayPtr<char> versionInfoData(new char[versionInfoSize]); - if (!GetFileVersionInfoW(m_path.charactersWithNullTermination(), 0, versionInfoSize, versionInfoData.get())) + if (!GetFileVersionInfoW(const_cast<UChar*>(m_path.charactersWithNullTermination()), + 0, versionInfoSize, versionInfoData.get())) return false; m_name = getVersionInfo(versionInfoData.get(), "ProductName"); diff --git a/WebCore/plugins/win/PluginViewWin.cpp b/WebCore/plugins/win/PluginViewWin.cpp index 127d3fc..895338e 100644 --- a/WebCore/plugins/win/PluginViewWin.cpp +++ b/WebCore/plugins/win/PluginViewWin.cpp @@ -99,6 +99,92 @@ const LPCWSTR kWebPluginViewProperty = L"WebPluginViewProperty"; static const char* MozillaUserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0"; +// The code used to hook BeginPaint/EndPaint originally came from +// <http://www.fengyuan.com/article/wmprint.html>. +// Copyright (C) 2000 by Feng Yuan (www.fengyuan.com). + +static unsigned beginPaintSysCall; +static BYTE* beginPaint; + +static unsigned endPaintSysCall; +static BYTE* endPaint; + +HDC WINAPI PluginView::hookedBeginPaint(HWND hWnd, PAINTSTRUCT* lpPaint) +{ + PluginView* pluginView = reinterpret_cast<PluginView*>(GetProp(hWnd, kWebPluginViewProperty)); + if (pluginView && pluginView->m_wmPrintHDC) { + // We're secretly handling WM_PRINTCLIENT, so set up the PAINTSTRUCT so + // that the plugin will paint into the HDC we provide. + memset(lpPaint, 0, sizeof(PAINTSTRUCT)); + lpPaint->hdc = pluginView->m_wmPrintHDC; + GetClientRect(hWnd, &lpPaint->rcPaint); + return pluginView->m_wmPrintHDC; + } + + // Call through to the original BeginPaint. + __asm mov eax, beginPaintSysCall + __asm push lpPaint + __asm push hWnd + __asm call beginPaint +} + +BOOL WINAPI PluginView::hookedEndPaint(HWND hWnd, const PAINTSTRUCT* lpPaint) +{ + PluginView* pluginView = reinterpret_cast<PluginView*>(GetProp(hWnd, kWebPluginViewProperty)); + if (pluginView && pluginView->m_wmPrintHDC) { + // We're secretly handling WM_PRINTCLIENT, so we don't have to do any + // cleanup. + return TRUE; + } + + // Call through to the original EndPaint. + __asm mov eax, endPaintSysCall + __asm push lpPaint + __asm push hWnd + __asm call endPaint +} + +static void hook(const char* module, const char* proc, unsigned& sysCallID, BYTE*& pProc, const void* pNewProc) +{ + // See <http://www.fengyuan.com/article/wmprint.html> for an explanation of + // how this function works. + + HINSTANCE hMod = GetModuleHandleA(module); + + pProc = reinterpret_cast<BYTE*>(GetProcAddress(hMod, proc)); + + if (pProc[0] != 0xB8) + return; + + // FIXME: Should we be reading the bytes one-by-one instead of doing an + // unaligned read? + sysCallID = *reinterpret_cast<unsigned*>(pProc + 1); + + DWORD flOldProtect; + if (!VirtualProtect(pProc, 5, PAGE_EXECUTE_READWRITE, &flOldProtect)) + return; + + pProc[0] = 0xE9; + *reinterpret_cast<unsigned*>(pProc + 1) = reinterpret_cast<intptr_t>(pNewProc) - reinterpret_cast<intptr_t>(pProc + 5); + + pProc += 5; +} + +static void setUpOffscreenPaintingHooks(HDC (WINAPI*hookedBeginPaint)(HWND, PAINTSTRUCT*), BOOL (WINAPI*hookedEndPaint)(HWND, const PAINTSTRUCT*)) +{ + static bool haveHooked = false; + if (haveHooked) + return; + haveHooked = true; + + // Most (all?) windowed plugins don't seem to respond to WM_PRINTCLIENT, so + // we hook into BeginPaint/EndPaint to allow their normal WM_PAINT handling + // to draw into a given HDC. Note that this hooking affects the entire + // process. + hook("user32.dll", "BeginPaint", beginPaintSysCall, beginPaint, hookedBeginPaint); + hook("user32.dll", "EndPaint", endPaintSysCall, endPaint, hookedEndPaint); +} + static bool registerPluginView() { static bool haveRegisteredWindowClass = false; @@ -201,15 +287,25 @@ PluginView::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) m_popPopupsStateTimer.startOneShot(0); } + if (message == WM_PRINTCLIENT) { + // Most (all?) windowed plugins don't respond to WM_PRINTCLIENT, so we + // change the message to WM_PAINT and rely on our hooked versions of + // BeginPaint/EndPaint to make the plugin draw into the given HDC. + message = WM_PAINT; + m_wmPrintHDC = reinterpret_cast<HDC>(wParam); + } + // Call the plug-in's window proc. LRESULT result = ::CallWindowProc(m_pluginWndProc, hWnd, message, wParam, lParam); + m_wmPrintHDC = 0; + m_isCallingPluginWndProc = false; return result; } -void PluginView::updatePluginWidget() const +void PluginView::updatePluginWidget() { if (!parent()) return; @@ -282,28 +378,6 @@ void PluginView::hide() Widget::hide(); } -void PluginView::paintMissingPluginIcon(GraphicsContext* context, const IntRect& rect) -{ - static RefPtr<Image> nullPluginImage; - if (!nullPluginImage) - nullPluginImage = Image::loadPlatformResource("nullPlugin"); - - IntRect imageRect(frameRect().x(), frameRect().y(), nullPluginImage->width(), nullPluginImage->height()); - - int xOffset = (frameRect().width() - imageRect.width()) / 2; - int yOffset = (frameRect().height() - imageRect.height()) / 2; - - imageRect.move(xOffset, yOffset); - - if (!rect.intersects(imageRect)) - return; - - context->save(); - context->clip(windowClipRect()); - context->drawImage(nullPluginImage.get(), imageRect.location()); - context->restore(); -} - bool PluginView::dispatchNPEvent(NPEvent& npEvent) { if (!m_plugin->pluginFuncs()->event) @@ -327,6 +401,34 @@ bool PluginView::dispatchNPEvent(NPEvent& npEvent) return result; } +void PluginView::paintWindowedPluginIntoContext(GraphicsContext* context, const IntRect& rect) const +{ + ASSERT(m_isWindowed); + ASSERT(context->shouldIncludeChildWindows()); + + ASSERT(parent()->isFrameView()); + IntPoint locationInWindow = static_cast<FrameView*>(parent())->contentsToWindow(frameRect().location()); + + HDC hdc = context->getWindowsContext(frameRect(), false); + + XFORM originalTransform; + GetWorldTransform(hdc, &originalTransform); + + // The plugin expects the DC to be in client coordinates, so we translate + // the DC to make that so. + XFORM transform = originalTransform; + transform.eDx = locationInWindow.x(); + transform.eDy = locationInWindow.y(); + + SetWorldTransform(hdc, &transform); + + SendMessage(platformPluginWidget(), WM_PRINTCLIENT, reinterpret_cast<WPARAM>(hdc), PRF_CLIENT | PRF_CHILDREN | PRF_OWNED); + + SetWorldTransform(hdc, &originalTransform); + + context->releaseWindowsContext(hdc, frameRect(), false); +} + void PluginView::paint(GraphicsContext* context, const IntRect& rect) { if (!m_isStarted) { @@ -335,9 +437,15 @@ void PluginView::paint(GraphicsContext* context, const IntRect& rect) return; } - if (m_isWindowed || context->paintingDisabled()) + if (context->paintingDisabled()) return; + if (m_isWindowed) { + if (context->shouldIncludeChildWindows()) + paintWindowedPluginIntoContext(context, rect); + return; + } + ASSERT(parent()->isFrameView()); IntRect rectInWindow = static_cast<FrameView*>(parent())->contentsToWindow(frameRect()); HDC hdc = context->getWindowsContext(rectInWindow, m_isTransparent); @@ -822,6 +930,7 @@ void PluginView::init() if (m_isWindowed) { registerPluginView(); + setUpOffscreenPaintingHooks(hookedBeginPaint, hookedEndPaint); DWORD flags = WS_CHILD; if (isSelfVisible()) |