1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "webkit/glue/resource_fetcher.h"
8 #include "base/bind_helpers.h"
9 #include "base/message_loop.h"
10 #include "base/timer.h"
11 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
12 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLResponse.h"
13 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
14 #include "webkit/glue/unittest_test_server.h"
15 #include "webkit/tools/test_shell/simple_resource_loader_bridge.h"
16 #include "webkit/tools/test_shell/test_shell_test.h"
18 using WebKit::WebFrame
;
19 using WebKit::WebURLRequest
;
20 using WebKit::WebURLResponse
;
21 using webkit_glue::ResourceFetcher
;
22 using webkit_glue::ResourceFetcherWithTimeout
;
26 class ResourceFetcherTests
: public TestShellTest
{
28 UnittestTestServer test_server_
;
31 static const int kMaxWaitTimeMs
= 5000;
33 class FetcherDelegate
{
38 // Start a repeating timer waiting for the download to complete. The
39 // callback has to be a static function, so we hold on to our instance.
40 FetcherDelegate::instance_
= this;
44 virtual ~FetcherDelegate() {}
46 ResourceFetcher::Callback
NewCallback() {
47 return base::Bind(&FetcherDelegate::OnURLFetchComplete
,
48 base::Unretained(this));
51 virtual void OnURLFetchComplete(const WebURLResponse
& response
,
52 const std::string
& data
) {
57 MessageLoop::current()->Quit();
60 bool completed() const { return completed_
; }
61 bool timed_out() const { return timed_out_
; }
63 std::string
data() const { return data_
; }
64 const WebURLResponse
& response() const { return response_
; }
66 // Wait for the request to complete or timeout. We use a loop here b/c the
67 // testing infrastructure (test_shell) can generate spurious calls to the
68 // MessageLoop's Quit method.
69 void WaitForResponse() {
70 while (!completed() && !timed_out())
71 MessageLoop::current()->Run();
75 timer_
.Start(FROM_HERE
,
76 base::TimeDelta::FromMilliseconds(kMaxWaitTimeMs
),
78 &FetcherDelegate::TimerFired
);
82 ASSERT_FALSE(completed_
);
85 MessageLoop::current()->Quit();
86 FAIL() << "fetch timed out";
89 static FetcherDelegate
* instance_
;
92 base::OneShotTimer
<FetcherDelegate
> timer_
;
95 WebURLResponse response_
;
99 FetcherDelegate
* FetcherDelegate::instance_
= NULL
;
101 // Test a fetch from the test server.
102 // Flaky, http://crbug.com/51622.
103 TEST_F(ResourceFetcherTests
, DISABLED_ResourceFetcherDownload
) {
104 ASSERT_TRUE(test_server_
.Start());
106 WebFrame
* frame
= test_shell_
->webView()->mainFrame();
108 GURL
url(test_server_
.GetURL("files/test_shell/index.html"));
109 scoped_ptr
<FetcherDelegate
> delegate(new FetcherDelegate
);
110 scoped_ptr
<ResourceFetcher
> fetcher(new ResourceFetcher(
111 url
, frame
, WebURLRequest::TargetIsMainFrame
, delegate
->NewCallback()));
113 delegate
->WaitForResponse();
115 ASSERT_TRUE(delegate
->completed());
116 EXPECT_EQ(delegate
->response().httpStatusCode(), 200);
117 std::string text
= delegate
->data();
118 EXPECT_TRUE(text
.find("What is this page?") != std::string::npos
);
120 // Test 404 response.
121 url
= test_server_
.GetURL("files/thisfiledoesntexist.html");
122 delegate
.reset(new FetcherDelegate
);
123 fetcher
.reset(new ResourceFetcher(url
, frame
,
124 WebURLRequest::TargetIsMainFrame
,
125 delegate
->NewCallback()));
127 delegate
->WaitForResponse();
129 ASSERT_TRUE(delegate
->completed());
130 EXPECT_EQ(delegate
->response().httpStatusCode(), 404);
131 EXPECT_TRUE(delegate
->data().find("Not Found.") != std::string::npos
);
134 // Flaky, http://crbug.com/51622.
135 TEST_F(ResourceFetcherTests
, DISABLED_ResourceFetcherDidFail
) {
136 ASSERT_TRUE(test_server_
.Start());
138 WebFrame
* frame
= test_shell_
->webView()->mainFrame();
140 // Try to fetch a page on a site that doesn't exist.
141 GURL
url("http://localhost:1339/doesnotexist");
142 scoped_ptr
<FetcherDelegate
> delegate(new FetcherDelegate
);
143 scoped_ptr
<ResourceFetcher
> fetcher(new ResourceFetcher(
144 url
, frame
, WebURLRequest::TargetIsMainFrame
, delegate
->NewCallback()));
146 delegate
->WaitForResponse();
148 // When we fail, we still call the Delegate callback but we pass in empty
150 EXPECT_TRUE(delegate
->completed());
151 EXPECT_TRUE(delegate
->response().isNull());
152 EXPECT_EQ(delegate
->data(), std::string());
153 EXPECT_FALSE(delegate
->timed_out());
156 TEST_F(ResourceFetcherTests
, ResourceFetcherTimeout
) {
157 ASSERT_TRUE(test_server_
.Start());
159 WebFrame
* frame
= test_shell_
->webView()->mainFrame();
161 // Grab a page that takes at least 1 sec to respond, but set the fetcher to
163 GURL
url(test_server_
.GetURL("slow?1"));
164 scoped_ptr
<FetcherDelegate
> delegate(new FetcherDelegate
);
165 scoped_ptr
<ResourceFetcher
> fetcher(new ResourceFetcherWithTimeout(
166 url
, frame
, WebURLRequest::TargetIsMainFrame
,
167 0, delegate
->NewCallback()));
169 delegate
->WaitForResponse();
171 // When we timeout, we still call the Delegate callback but we pass in empty
173 EXPECT_TRUE(delegate
->completed());
174 EXPECT_TRUE(delegate
->response().isNull());
175 EXPECT_EQ(delegate
->data(), std::string());
176 EXPECT_FALSE(delegate
->timed_out());
179 class EvilFetcherDelegate
: public FetcherDelegate
{
181 virtual ~EvilFetcherDelegate() {}
183 void SetFetcher(ResourceFetcher
* fetcher
) {
184 fetcher_
.reset(fetcher
);
187 virtual void OnURLFetchComplete(const WebURLResponse
& response
,
188 const std::string
& data
) {
189 // Destroy the ResourceFetcher here. We are testing that upon returning
190 // to the ResourceFetcher that it does not crash.
192 FetcherDelegate::OnURLFetchComplete(response
, data
);
196 scoped_ptr
<ResourceFetcher
> fetcher_
;
199 TEST_F(ResourceFetcherTests
, ResourceFetcherDeletedInCallback
) {
200 ASSERT_TRUE(test_server_
.Start());
202 WebFrame
* frame
= test_shell_
->webView()->mainFrame();
204 // Grab a page that takes at least 1 sec to respond, but set the fetcher to
206 GURL
url(test_server_
.GetURL("slow?1"));
207 scoped_ptr
<EvilFetcherDelegate
> delegate(new EvilFetcherDelegate
);
208 scoped_ptr
<ResourceFetcher
> fetcher(new ResourceFetcherWithTimeout(
209 url
, frame
, WebURLRequest::TargetIsMainFrame
,
210 0, delegate
->NewCallback()));
211 delegate
->SetFetcher(fetcher
.release());
213 delegate
->WaitForResponse();
214 EXPECT_FALSE(delegate
->timed_out());