• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>
WebKitCreateInstance(REFCLSID clsid,T ** object)35 static HRESULT WebKitCreateInstance(REFCLSID clsid, T** object)
36 {
37     return WebKitCreateInstance(clsid, 0, __uuidof(T), reinterpret_cast<void**>(object));
38 }
39 
webViewCount()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 
createAndInitializeWebView(COMPtr<IWebView> & outWebView,HostWindow & window,HWND & viewWindow)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 
runMessagePump(DWORD timeoutMilliseconds)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 
finishWebViewDestructionTest(COMPtr<IWebView> & webView,HWND viewWindow)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.
TEST(WebViewDestruction,NoInitWithFrame)97 TEST(WebViewDestruction, NoInitWithFrame)
98 {
99     COMPtr<IWebView> webView;
100     TEST_ASSERT(SUCCEEDED(WebKitCreateInstance(__uuidof(WebView), &webView)));
101 
102     finishWebViewDestructionTest(webView, 0);
103 }
104 
TEST(WebViewDestruction,CloseWithoutInitWithFrame)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>
TEST(WebViewDestruction,NoCloseOrDestroyViewWindow)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>
TEST(WebViewDestruction,CloseWithoutDestroyViewWindow)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 
TEST(WebViewDestruction,DestroyViewWindowWithoutClose)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 
TEST(WebViewDestruction,CloseThenDestroyViewWindow)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 
TEST(WebViewDestruction,DestroyViewWindowThenClose)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 
TEST(WebViewDestruction,DestroyHostWindow)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 
TEST(WebViewDestruction,DestroyHostWindowThenClose)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 
TEST(WebViewDestruction,CloseThenDestroyHostWindow)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>
TEST(WebViewDestruction,MainFrameAfterClose)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