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