Home | History | Annotate | Download | only in win
      1 /*
      2  * Copyright (C) 2010 Apple 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  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
     14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
     17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     23  * THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "WindowedPluginTest.h"
     27 
     28 #include "PluginObject.h"
     29 
     30 using namespace std;
     31 
     32 // NPN_InvalidateRect should invalidate the plugin's HWND.
     33 
     34 static const wchar_t instancePointerProperty[] = L"org.webkit.TestNetscapePlugin.NPNInvalidateRectInvalidatesWindow.InstancePointer";
     35 
     36 class TemporaryWindowMover {
     37 public:
     38     TemporaryWindowMover(HWND);
     39     ~TemporaryWindowMover();
     40 
     41     bool moveSucceeded() const { return m_moveSucceeded; }
     42 
     43 private:
     44     static const UINT standardSetWindowPosFlags = SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER;
     45     bool m_moveSucceeded;
     46     HWND m_window;
     47     RECT m_savedWindowRect;
     48 };
     49 
     50 TemporaryWindowMover::TemporaryWindowMover(HWND window)
     51     : m_window(window)
     52 {
     53     m_moveSucceeded = false;
     54 
     55     if (!::GetWindowRect(m_window, &m_savedWindowRect))
     56         return;
     57 
     58     if (!::SetWindowPos(m_window, 0, 0, 0, 0, 0, SWP_SHOWWINDOW | standardSetWindowPosFlags))
     59         return;
     60 
     61     m_moveSucceeded = true;
     62 };
     63 
     64 TemporaryWindowMover::~TemporaryWindowMover()
     65 {
     66     if (!m_moveSucceeded)
     67         return;
     68 
     69     ::SetWindowPos(m_window, 0, m_savedWindowRect.left, m_savedWindowRect.top, 0, 0, SWP_HIDEWINDOW | standardSetWindowPosFlags);
     70 }
     71 
     72 class NPNInvalidateRectInvalidatesWindow : public WindowedPluginTest {
     73 public:
     74     NPNInvalidateRectInvalidatesWindow(NPP, const string& identifier);
     75     ~NPNInvalidateRectInvalidatesWindow();
     76 
     77 private:
     78     virtual LRESULT wndProc(UINT message, WPARAM, LPARAM, bool& handled);
     79 
     80     void onPaint();
     81     void testInvalidateRect();
     82 
     83     virtual NPError NPP_SetWindow(NPP, NPWindow*);
     84 
     85     TemporaryWindowMover* m_windowMover;
     86 };
     87 
     88 NPNInvalidateRectInvalidatesWindow::NPNInvalidateRectInvalidatesWindow(NPP npp, const string& identifier)
     89     : WindowedPluginTest(npp, identifier)
     90     , m_windowMover(0)
     91 {
     92 }
     93 
     94 NPNInvalidateRectInvalidatesWindow::~NPNInvalidateRectInvalidatesWindow()
     95 {
     96     delete m_windowMover;
     97 }
     98 
     99 NPError NPNInvalidateRectInvalidatesWindow::NPP_SetWindow(NPP instance, NPWindow* npWindow)
    100 {
    101     NPError error = WindowedPluginTest::NPP_SetWindow(instance, npWindow);
    102     if (error != NPERR_NO_ERROR)
    103         return error;
    104 
    105     if (!window())
    106         return NPERR_NO_ERROR;
    107 
    108     // The test harness's window (the one that contains the WebView) is off-screen and hidden.
    109     // We need to move it on-screen and make it visible in order for the plugin's window to
    110     // accumulate an update region when the DWM is disabled.
    111 
    112     HWND testHarnessWindow = ::GetAncestor(window(), GA_ROOT);
    113     if (!testHarnessWindow) {
    114         pluginLog(instance, "Failed to get test harness window");
    115         return NPERR_GENERIC_ERROR;
    116     }
    117 
    118     m_windowMover = new TemporaryWindowMover(testHarnessWindow);
    119     if (!m_windowMover->moveSucceeded()) {
    120         pluginLog(instance, "Failed to move test harness window on-screen");
    121         return NPERR_GENERIC_ERROR;
    122     }
    123 
    124     // Wait until we receive a WM_PAINT message to ensure that the window is on-screen before we do
    125     // the NPN_InvalidateRect test.
    126     waitUntilDone();
    127     return NPERR_NO_ERROR;
    128 }
    129 
    130 LRESULT NPNInvalidateRectInvalidatesWindow::wndProc(UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
    131 {
    132     if (message == WM_PAINT)
    133         onPaint();
    134 
    135     handled = false;
    136     return 0;
    137 }
    138 
    139 void NPNInvalidateRectInvalidatesWindow::onPaint()
    140 {
    141     testInvalidateRect();
    142     notifyDone();
    143     delete m_windowMover;
    144     m_windowMover = 0;
    145 }
    146 
    147 void NPNInvalidateRectInvalidatesWindow::testInvalidateRect()
    148 {
    149     RECT clientRect;
    150     if (!::GetClientRect(window(), &clientRect)) {
    151         pluginLog(m_npp, "::GetClientRect failed");
    152         return;
    153     }
    154 
    155     if (::IsRectEmpty(&clientRect)) {
    156         pluginLog(m_npp, "Plugin's HWND has not been sized when NPP_SetWindow is called");
    157         return;
    158     }
    159 
    160     // Clear the invalid region.
    161     if (!::ValidateRect(window(), 0)) {
    162         pluginLog(m_npp, "::ValidateRect failed");
    163         return;
    164     }
    165 
    166     // Invalidate our lower-right quadrant.
    167     NPRect rectToInvalidate;
    168     rectToInvalidate.left = (clientRect.right - clientRect.left) / 2;
    169     rectToInvalidate.top = (clientRect.bottom - clientRect.top) / 2;
    170     rectToInvalidate.right = clientRect.right;
    171     rectToInvalidate.bottom = clientRect.bottom;
    172     NPN_InvalidateRect(&rectToInvalidate);
    173 
    174     RECT invalidRect;
    175     if (!::GetUpdateRect(window(), &invalidRect, FALSE)) {
    176         pluginLog(m_npp, "::GetUpdateRect failed");
    177         return;
    178     }
    179 
    180     if (invalidRect.left != rectToInvalidate.left || invalidRect.top != rectToInvalidate.top || invalidRect.right != rectToInvalidate.right || invalidRect.bottom != rectToInvalidate.bottom) {
    181         pluginLog(m_npp, "Expected invalid rect {left=%u, top=%u, right=%u, bottom=%u}, but got {left=%d, top=%d, right=%d, bottom=%d}", rectToInvalidate.left, rectToInvalidate.top, rectToInvalidate.right, rectToInvalidate.bottom, invalidRect.left, invalidRect.top, invalidRect.right, invalidRect.bottom);
    182         return;
    183     }
    184 
    185     pluginLog(m_npp, "Plugin's HWND has been invalidated as expected");
    186 }
    187 
    188 static PluginTest::Register<NPNInvalidateRectInvalidatesWindow> registrar("npn-invalidate-rect-invalidates-window");
    189