Don't hang in WebKitAPITest if no messages have been posted
[WebKit-https.git] / WebKitTools / WebKitAPITest / tests / WebViewDestruction.cpp
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 COMPtr<IWebView> createWebView(const HostWindow& window)
52 {
53     COMPtr<IWebView> webView;
54     if (FAILED(WebKitCreateInstance(__uuidof(WebView), &webView)))
55         return 0;
56
57     if (FAILED(webView->setHostWindow(reinterpret_cast<OLE_HANDLE>(window.window()))))
58         return 0;
59
60     if (FAILED(webView->initWithFrame(window.clientRect(), 0, 0)))
61         return 0;
62
63     return webView;
64 }
65
66 static void runMessagePump(DWORD timeoutMilliseconds)
67 {
68     DWORD startTickCount = GetTickCount();
69     MSG msg;
70     BOOL result;
71     while ((result = PeekMessageW(&msg, 0, 0, 0, PM_REMOVE)) && GetTickCount() - startTickCount <= timeoutMilliseconds) {
72         if (result == -1)
73             break;
74         TranslateMessage(&msg);
75         DispatchMessage(&msg);
76     }
77 }
78
79 // Tests that calling IWebView::close without calling DestroyWindow, then releasing a WebView doesn't crash. <http://webkit.org/b/32827>
80 TEST(WebViewDestruction, CloseWithoutDestroyWindow)
81 {
82     HostWindow window;
83     TEST_ASSERT(window.initialize());
84     COMPtr<IWebView> webView = createWebView(window);
85     TEST_ASSERT(webView);
86
87     TEST_ASSERT(SUCCEEDED(webView->close()));
88
89     // Allow window messages to be processed to trigger the crash.
90     runMessagePump(50);
91
92     // We haven't crashed. Release the WebView and ensure that its view window gets destroyed and the WebView doesn't leak.
93     COMPtr<IWebViewPrivate> viewPrivate(Query, webView);
94     TEST_ASSERT(viewPrivate);
95
96     HWND viewWindow;
97     TEST_ASSERT(SUCCEEDED(viewPrivate->viewWindow(reinterpret_cast<OLE_HANDLE*>(&viewWindow))));
98     TEST_ASSERT(viewWindow);
99
100     int currentWebViewCount = webViewCount();
101     TEST_ASSERT(currentWebViewCount > 0);
102
103     webView = 0;
104     viewPrivate = 0;
105
106     TEST_ASSERT(webViewCount() == currentWebViewCount - 1);
107     TEST_ASSERT(!IsWindow(viewWindow));
108 }
109
110 // Tests that calling IWebView::mainFrame after calling IWebView::close doesn't crash. <http://webkit.org/b/32868>
111 TEST(WebViewDestruction, MainFrameAfterClose)
112 {
113     HostWindow window;
114     TEST_ASSERT(window.initialize());
115     COMPtr<IWebView> webView = createWebView(window);
116     TEST_ASSERT(webView);
117
118     TEST_ASSERT(SUCCEEDED(webView->close()));
119     COMPtr<IWebFrame> mainFrame;
120     TEST_ASSERT(SUCCEEDED(webView->mainFrame(&mainFrame)));
121 }
122
123 // Tests that releasing a WebView without calling IWebView::close or DestroyWindow doesn't leak. <http://webkit.org/b/33162>
124 TEST(WebViewDestruction, NoCloseOrDestroyWindow)
125 {
126     HostWindow window;
127     TEST_ASSERT(window.initialize());
128     COMPtr<IWebView> webView = createWebView(window);
129     TEST_ASSERT(webView);
130
131     webView = 0;
132     TEST_ASSERT(!webViewCount());
133 }
134
135 } // namespace WebKitAPITest