Home | History | Annotate | Download | only in tests
      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'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
     20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     23  */
     24 
     25 #include "config.h"
     26 
     27 #include "HostWindow.h"
     28 #include "Test.h"
     29 #include <WebCore/COMPtr.h>
     30 #include <WebKit/WebKit.h>
     31 #include <WebKit/WebKitCOMAPI.h>
     32 #include <wtf/PassOwnPtr.h>
     33 
     34 namespace WebKitAPITest {
     35 
     36 template <typename T>
     37 static HRESULT WebKitCreateInstance(REFCLSID clsid, T** object)
     38 {
     39     return WebKitCreateInstance(clsid, 0, __uuidof(T), reinterpret_cast<void**>(object));
     40 }
     41 
     42 static int webViewCount()
     43 {
     44     COMPtr<IWebKitStatistics> statistics;
     45     if (FAILED(WebKitCreateInstance(__uuidof(WebKitStatistics), &statistics)))
     46         return -1;
     47     int count;
     48     if (FAILED(statistics->webViewCount(&count)))
     49         return -1;
     50     return count;
     51 }
     52 
     53 static void createAndInitializeWebView(COMPtr<IWebView>& outWebView, HostWindow& window, HWND& viewWindow)
     54 {
     55     COMPtr<IWebView> webView;
     56     TEST_ASSERT(SUCCEEDED(WebKitCreateInstance(__uuidof(WebView), &webView)));
     57 
     58     TEST_ASSERT(window.initialize());
     59     TEST_ASSERT(SUCCEEDED(webView->setHostWindow(reinterpret_cast<OLE_HANDLE>(window.window()))));
     60     TEST_ASSERT(SUCCEEDED(webView->initWithFrame(window.clientRect(), 0, 0)));
     61 
     62     COMPtr<IWebViewPrivate> viewPrivate(Query, webView);
     63     TEST_ASSERT(viewPrivate);
     64     TEST_ASSERT(SUCCEEDED(viewPrivate->viewWindow(reinterpret_cast<OLE_HANDLE*>(&viewWindow))));
     65     TEST_ASSERT(IsWindow(viewWindow));
     66 
     67     outWebView.adoptRef(webView.releaseRef());
     68 }
     69 
     70 static void runMessagePump(DWORD timeoutMilliseconds)
     71 {
     72     DWORD startTickCount = GetTickCount();
     73     MSG msg;
     74     BOOL result;
     75     while ((result = PeekMessageW(&msg, 0, 0, 0, PM_REMOVE)) && GetTickCount() - startTickCount <= timeoutMilliseconds) {
     76         if (result == -1)
     77             break;
     78         TranslateMessage(&msg);
     79         DispatchMessage(&msg);
     80     }
     81 }
     82 
     83 static void finishWebViewDestructionTest(COMPtr<IWebView>& webView, HWND viewWindow)
     84 {
     85     // Allow window messages to be processed, because in some cases that would trigger a crash (e.g., <http://webkit.org/b/32827>).
     86     runMessagePump(50);
     87 
     88     // We haven't crashed. Release the WebView and ensure that its view window has been destroyed and the WebView doesn't leak.
     89     int currentWebViewCount = webViewCount();
     90     TEST_ASSERT(currentWebViewCount > 0);
     91 
     92     webView = 0;
     93 
     94     TEST_ASSERT(webViewCount() == currentWebViewCount - 1);
     95     TEST_ASSERT(!IsWindow(viewWindow));
     96 }
     97 
     98 // Tests that releasing a WebView without calling IWebView::initWithFrame works.
     99 TEST(WebViewDestruction, NoInitWithFrame)
    100 {
    101     COMPtr<IWebView> webView;
    102     TEST_ASSERT(SUCCEEDED(WebKitCreateInstance(__uuidof(WebView), &webView)));
    103 
    104     finishWebViewDestructionTest(webView, 0);
    105 }
    106 
    107 TEST(WebViewDestruction, CloseWithoutInitWithFrame)
    108 {
    109     COMPtr<IWebView> webView;
    110     TEST_ASSERT(SUCCEEDED(WebKitCreateInstance(__uuidof(WebView), &webView)));
    111 
    112     TEST_ASSERT(SUCCEEDED(webView->close()));
    113 
    114     finishWebViewDestructionTest(webView, 0);
    115 }
    116 
    117 // Tests that releasing a WebView without calling IWebView::close or DestroyWindow doesn't leak. <http://webkit.org/b/33162>
    118 TEST(WebViewDestruction, NoCloseOrDestroyViewWindow)
    119 {
    120     COMPtr<IWebView> webView;
    121     HostWindow window;
    122     HWND viewWindow;
    123     createAndInitializeWebView(webView, window, viewWindow);
    124 
    125     finishWebViewDestructionTest(webView, viewWindow);
    126 }
    127 
    128 // Tests that calling IWebView::close without calling DestroyWindow, then releasing a WebView doesn't crash. <http://webkit.org/b/32827>
    129 TEST(WebViewDestruction, CloseWithoutDestroyViewWindow)
    130 {
    131     COMPtr<IWebView> webView;
    132     HostWindow window;
    133     HWND viewWindow;
    134     createAndInitializeWebView(webView, window, viewWindow);
    135 
    136     TEST_ASSERT(SUCCEEDED(webView->close()));
    137 
    138     finishWebViewDestructionTest(webView, viewWindow);
    139 }
    140 
    141 TEST(WebViewDestruction, DestroyViewWindowWithoutClose)
    142 {
    143     COMPtr<IWebView> webView;
    144     HostWindow window;
    145     HWND viewWindow;
    146     createAndInitializeWebView(webView, window, viewWindow);
    147 
    148     DestroyWindow(viewWindow);
    149 
    150     finishWebViewDestructionTest(webView, viewWindow);
    151 }
    152 
    153 TEST(WebViewDestruction, CloseThenDestroyViewWindow)
    154 {
    155     COMPtr<IWebView> webView;
    156     HostWindow window;
    157     HWND viewWindow;
    158     createAndInitializeWebView(webView, window, viewWindow);
    159 
    160     TEST_ASSERT(SUCCEEDED(webView->close()));
    161     DestroyWindow(viewWindow);
    162 
    163     finishWebViewDestructionTest(webView, viewWindow);
    164 }
    165 
    166 TEST(WebViewDestruction, DestroyViewWindowThenClose)
    167 {
    168     COMPtr<IWebView> webView;
    169     HostWindow window;
    170     HWND viewWindow;
    171     createAndInitializeWebView(webView, window, viewWindow);
    172 
    173     DestroyWindow(viewWindow);
    174     TEST_ASSERT(SUCCEEDED(webView->close()));
    175 
    176     finishWebViewDestructionTest(webView, viewWindow);
    177 }
    178 
    179 TEST(WebViewDestruction, DestroyHostWindow)
    180 {
    181     COMPtr<IWebView> webView;
    182     HostWindow window;
    183     HWND viewWindow;
    184     createAndInitializeWebView(webView, window, viewWindow);
    185 
    186     DestroyWindow(window.window());
    187 
    188     finishWebViewDestructionTest(webView, viewWindow);
    189 }
    190 
    191 TEST(WebViewDestruction, DestroyHostWindowThenClose)
    192 {
    193     COMPtr<IWebView> webView;
    194     HostWindow window;
    195     HWND viewWindow;
    196     createAndInitializeWebView(webView, window, viewWindow);
    197 
    198     DestroyWindow(window.window());
    199     TEST_ASSERT(SUCCEEDED(webView->close()));
    200 
    201     finishWebViewDestructionTest(webView, viewWindow);
    202 }
    203 
    204 TEST(WebViewDestruction, CloseThenDestroyHostWindow)
    205 {
    206     COMPtr<IWebView> webView;
    207     HostWindow window;
    208     HWND viewWindow;
    209     createAndInitializeWebView(webView, window, viewWindow);
    210 
    211     TEST_ASSERT(SUCCEEDED(webView->close()));
    212     DestroyWindow(window.window());
    213 
    214     finishWebViewDestructionTest(webView, viewWindow);
    215 }
    216 
    217 // Tests that calling IWebView::mainFrame after calling IWebView::close doesn't crash. <http://webkit.org/b/32868>
    218 TEST(WebViewDestruction, MainFrameAfterClose)
    219 {
    220     COMPtr<IWebView> webView;
    221     HostWindow window;
    222     HWND viewWindow;
    223     createAndInitializeWebView(webView, window, viewWindow);
    224 
    225     TEST_ASSERT(SUCCEEDED(webView->close()));
    226     COMPtr<IWebFrame> mainFrame;
    227     TEST_ASSERT(SUCCEEDED(webView->mainFrame(&mainFrame)));
    228 
    229     finishWebViewDestructionTest(webView, viewWindow);
    230 }
    231 
    232 } // namespace WebKitAPITest
    233