2 * Copyright (C) 2011 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include "web/tests/FrameTestHelpers.h"
34 #include "platform/testing/URLTestHelpers.h"
35 #include "platform/testing/UnitTestHelpers.h"
36 #include "public/platform/Platform.h"
37 #include "public/platform/WebData.h"
38 #include "public/platform/WebString.h"
39 #include "public/platform/WebThread.h"
40 #include "public/platform/WebURLRequest.h"
41 #include "public/platform/WebURLResponse.h"
42 #include "public/platform/WebUnitTestSupport.h"
43 #include "public/web/WebRemoteFrame.h"
44 #include "public/web/WebSettings.h"
45 #include "public/web/WebTreeScopeType.h"
46 #include "public/web/WebViewClient.h"
47 #include "web/WebLocalFrameImpl.h"
48 #include "wtf/StdLibExtras.h"
51 namespace FrameTestHelpers
{
55 // The frame test helpers coordinate frame loads in a carefully choreographed
56 // dance. Since the parser is threaded, simply spinning the run loop once is not
57 // enough to ensure completion of a load. Instead, the following pattern is
58 // used to ensure that tests see the final state:
59 // 1. Post a task to trigger a load (LoadTask/LoadHTMLStringTask/ReloadTask).
60 // 2. Enter the run loop.
61 // 3. Posted task triggers the load, and starts pumping pending resource
62 // requests using ServeAsyncRequestsTask.
63 // 4. TestWebFrameClient watches for didStartLoading/didStopLoading calls,
64 // keeping track of how many loads it thinks are in flight.
65 // 5. While ServeAsyncRequestsTask observes TestWebFrameClient to still have
66 // loads in progress, it posts itself back to the run loop.
67 // 6. When ServeAsyncRequestsTask notices there are no more loads in progress,
68 // it exits the run loop.
69 // 7. At this point, all parsing, resource loads, and layout should be finished.
70 TestWebFrameClient
* testClientForFrame(WebFrame
* frame
)
72 return static_cast<TestWebFrameClient
*>(toWebLocalFrameImpl(frame
)->client());
75 class ServeAsyncRequestsTask
: public WebTaskRunner::Task
{
77 explicit ServeAsyncRequestsTask(TestWebFrameClient
* client
)
84 Platform::current()->unitTestSupport()->serveAsynchronousMockedRequests();
85 if (m_client
->isLoading())
86 Platform::current()->currentThread()->taskRunner()->postTask(FROM_HERE
, new ServeAsyncRequestsTask(m_client
));
88 Platform::current()->unitTestSupport()->exitRunLoop();
92 TestWebFrameClient
* const m_client
;
95 void pumpPendingRequests(WebFrame
* frame
)
97 Platform::current()->currentThread()->taskRunner()->postTask(FROM_HERE
, new ServeAsyncRequestsTask(testClientForFrame(frame
)));
98 Platform::current()->unitTestSupport()->enterRunLoop();
101 class LoadTask
: public WebTaskRunner::Task
{
103 LoadTask(WebFrame
* frame
, const WebURLRequest
& request
)
111 m_frame
->loadRequest(m_request
);
115 WebFrame
* const m_frame
;
116 const WebURLRequest m_request
;
119 class LoadHTMLStringTask
: public WebTaskRunner::Task
{
121 LoadHTMLStringTask(WebFrame
* frame
, const std::string
& html
, const WebURL
& baseURL
)
130 m_frame
->loadHTMLString(WebData(m_html
.data(), m_html
.size()), m_baseURL
);
134 WebFrame
* const m_frame
;
135 const std::string m_html
;
136 const WebURL m_baseURL
;
139 class LoadHistoryItemTask
: public WebTaskRunner::Task
{
141 LoadHistoryItemTask(WebFrame
* frame
, const WebHistoryItem
& item
, WebHistoryLoadType loadType
, WebURLRequest::CachePolicy cachePolicy
)
144 , m_loadType(loadType
)
145 , m_cachePolicy(cachePolicy
)
151 m_frame
->loadHistoryItem(m_item
, m_loadType
, m_cachePolicy
);
155 WebFrame
* const m_frame
;
156 const WebHistoryItem m_item
;
157 const WebHistoryLoadType m_loadType
;
158 const WebURLRequest::CachePolicy m_cachePolicy
;
161 class ReloadTask
: public WebTaskRunner::Task
{
163 ReloadTask(WebFrame
* frame
, bool ignoreCache
)
165 , m_ignoreCache(ignoreCache
)
171 m_frame
->reload(m_ignoreCache
);
175 WebFrame
* const m_frame
;
176 const bool m_ignoreCache
;
179 TestWebFrameClient
* defaultWebFrameClient()
181 DEFINE_STATIC_LOCAL(TestWebFrameClient
, client
, ());
185 WebViewClient
* defaultWebViewClient()
187 DEFINE_STATIC_LOCAL(TestWebViewClient
, client
, ());
193 void loadFrame(WebFrame
* frame
, const std::string
& url
)
195 WebURLRequest urlRequest
;
196 urlRequest
.initialize();
197 urlRequest
.setURL(URLTestHelpers::toKURL(url
));
199 Platform::current()->currentThread()->taskRunner()->postTask(FROM_HERE
, new LoadTask(frame
, urlRequest
));
200 pumpPendingRequests(frame
);
203 void loadHTMLString(WebFrame
* frame
, const std::string
& html
, const WebURL
& baseURL
)
205 Platform::current()->currentThread()->taskRunner()->postTask(FROM_HERE
, new LoadHTMLStringTask(frame
, html
, baseURL
));
206 pumpPendingRequests(frame
);
209 void loadHistoryItem(WebFrame
* frame
, const WebHistoryItem
& item
, WebHistoryLoadType loadType
, WebURLRequest::CachePolicy cachePolicy
)
211 Platform::current()->currentThread()->taskRunner()->postTask(FROM_HERE
, new LoadHistoryItemTask(frame
, item
, loadType
, cachePolicy
));
212 pumpPendingRequests(frame
);
215 void reloadFrame(WebFrame
* frame
)
217 Platform::current()->currentThread()->taskRunner()->postTask(FROM_HERE
, new ReloadTask(frame
, false));
218 pumpPendingRequests(frame
);
221 void reloadFrameIgnoringCache(WebFrame
* frame
)
223 Platform::current()->currentThread()->taskRunner()->postTask(FROM_HERE
, new ReloadTask(frame
, true));
224 pumpPendingRequests(frame
);
227 void pumpPendingRequestsDoNotUse(WebFrame
* frame
)
229 pumpPendingRequests(frame
);
232 WebViewHelper::WebViewHelper(SettingOverrider
* settingOverrider
)
234 , m_settingOverrider(settingOverrider
)
238 WebViewHelper::~WebViewHelper()
243 WebViewImpl
* WebViewHelper::initialize(bool enableJavascript
, TestWebFrameClient
* webFrameClient
, WebViewClient
* webViewClient
, void (*updateSettingsFunc
)(WebSettings
*))
248 webFrameClient
= defaultWebFrameClient();
250 webViewClient
= defaultWebViewClient();
251 m_webView
= WebViewImpl::create(webViewClient
);
252 m_webView
->settings()->setJavaScriptEnabled(enableJavascript
);
253 m_webView
->settings()->setPluginsEnabled(true);
254 if (updateSettingsFunc
)
255 updateSettingsFunc(m_webView
->settings());
257 m_webView
->settings()->setDeviceSupportsMouse(false);
258 if (m_settingOverrider
)
259 m_settingOverrider
->overrideSettings(m_webView
->settings());
261 m_webView
->setDefaultPageScaleLimits(1, 4);
262 m_webView
->setMainFrame(WebLocalFrameImpl::create(WebTreeScopeType::Document
, webFrameClient
));
267 WebViewImpl
* WebViewHelper::initializeAndLoad(const std::string
& url
, bool enableJavascript
, TestWebFrameClient
* webFrameClient
, WebViewClient
* webViewClient
, void (*updateSettingsFunc
)(WebSettings
*))
269 initialize(enableJavascript
, webFrameClient
, webViewClient
, updateSettingsFunc
);
271 loadFrame(webView()->mainFrame(), url
);
273 return webViewImpl();
276 void WebViewHelper::reset()
279 ASSERT(m_webView
->mainFrame()->isWebRemoteFrame() || !testClientForFrame(m_webView
->mainFrame())->isLoading());
285 TestWebFrameClient::TestWebFrameClient() : m_loadsInProgress(0)
289 WebFrame
* TestWebFrameClient::createChildFrame(WebLocalFrame
* parent
, WebTreeScopeType scope
, const WebString
& frameName
, WebSandboxFlags sandboxFlags
)
291 WebFrame
* frame
= WebLocalFrame::create(scope
, this);
292 parent
->appendChild(frame
);
296 void TestWebFrameClient::frameDetached(WebFrame
* frame
, DetachType type
)
298 if (type
== DetachType::Remove
&& frame
->parent())
299 frame
->parent()->removeChild(frame
);
303 void TestWebFrameClient::didStartLoading(bool)
308 void TestWebFrameClient::didStopLoading()
310 ASSERT(m_loadsInProgress
> 0);
314 void TestWebFrameClient::waitForLoadToComplete()
317 // We call runPendingTasks multiple times as single call of
318 // runPendingTasks may not be enough.
319 // runPendingTasks only ensures that main thread task queue is empty,
320 // and asynchronous parsing make use of off main thread HTML parser.
321 testing::runPendingTasks();
325 Platform::current()->yieldCurrentThread();
329 TestWebRemoteFrameClient::TestWebRemoteFrameClient()
330 : m_frame(WebRemoteFrame::create(WebTreeScopeType::Document
, this))
334 void TestWebRemoteFrameClient::frameDetached(DetachType type
)
336 if (type
== DetachType::Remove
&& m_frame
->parent())
337 m_frame
->parent()->removeChild(m_frame
);
341 void TestWebViewClient::initializeLayerTreeView()
343 m_layerTreeView
= adoptPtr(Platform::current()->unitTestSupport()->createLayerTreeViewForTesting());
344 ASSERT(m_layerTreeView
);
347 } // namespace FrameTestHelpers