Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / content / renderer / resource_fetcher_browsertest.cc
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.
4
5 #include "content/public/renderer/resource_fetcher.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/command_line.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/time/time.h"
12 #include "base/timer/timer.h"
13 #include "content/public/common/content_switches.h"
14 #include "content/public/common/url_constants.h"
15 #include "content/public/renderer/render_view.h"
16 #include "content/public/test/content_browser_test.h"
17 #include "content/public/test/content_browser_test_utils.h"
18 #include "content/public/test/test_utils.h"
19 #include "content/shell/browser/shell.h"
20 #include "third_party/WebKit/public/platform/WebURLResponse.h"
21 #include "third_party/WebKit/public/web/WebFrame.h"
22 #include "third_party/WebKit/public/web/WebView.h"
23
24 using blink::WebFrame;
25 using blink::WebURLRequest;
26 using blink::WebURLResponse;
27
28 namespace {
29
30 // The first RenderFrame is routing ID 1, and the first RenderView is 2.
31 const int kRenderViewRoutingId = 2;
32
33 }
34
35 namespace content {
36
37 static const int kMaxWaitTimeMs = 5000;
38
39 class FetcherDelegate {
40  public:
41   FetcherDelegate()
42       : completed_(false),
43         timed_out_(false) {
44     // Start a repeating timer waiting for the download to complete.  The
45     // callback has to be a static function, so we hold on to our instance.
46     FetcherDelegate::instance_ = this;
47     StartTimer();
48   }
49
50   virtual ~FetcherDelegate() {}
51
52   ResourceFetcher::Callback NewCallback() {
53     return base::Bind(&FetcherDelegate::OnURLFetchComplete,
54                       base::Unretained(this));
55   }
56
57   virtual void OnURLFetchComplete(const WebURLResponse& response,
58                                   const std::string& data) {
59     response_ = response;
60     data_ = data;
61     completed_ = true;
62     timer_.Stop();
63     if (!timed_out_)
64       quit_task_.Run();
65   }
66
67   bool completed() const { return completed_; }
68   bool timed_out() const { return timed_out_; }
69
70   std::string data() const { return data_; }
71   const WebURLResponse& response() const { return response_; }
72
73   // Wait for the request to complete or timeout.
74   void WaitForResponse() {
75     scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner;
76     quit_task_ = runner->QuitClosure();
77     runner->Run();
78   }
79
80   void StartTimer() {
81     timer_.Start(FROM_HERE,
82                  base::TimeDelta::FromMilliseconds(kMaxWaitTimeMs),
83                  this,
84                  &FetcherDelegate::TimerFired);
85   }
86
87   void TimerFired() {
88     ASSERT_FALSE(completed_);
89
90     timed_out_ = true;
91     if (!completed_)
92       quit_task_.Run();
93     FAIL() << "fetch timed out";
94   }
95
96   static FetcherDelegate* instance_;
97
98  private:
99   base::OneShotTimer<FetcherDelegate> timer_;
100   bool completed_;
101   bool timed_out_;
102   WebURLResponse response_;
103   std::string data_;
104   base::Closure quit_task_;
105 };
106
107 FetcherDelegate* FetcherDelegate::instance_ = NULL;
108
109 class EvilFetcherDelegate : public FetcherDelegate {
110  public:
111   virtual ~EvilFetcherDelegate() {}
112
113   void SetFetcher(ResourceFetcher* fetcher) {
114     fetcher_.reset(fetcher);
115   }
116
117   virtual void OnURLFetchComplete(const WebURLResponse& response,
118                                   const std::string& data) OVERRIDE {
119     FetcherDelegate::OnURLFetchComplete(response, data);
120
121     // Destroy the ResourceFetcher here.  We are testing that upon returning
122     // to the ResourceFetcher that it does not crash.  This must be done after
123     // calling FetcherDelegate::OnURLFetchComplete, since deleting the fetcher
124     // invalidates |response| and |data|.
125     fetcher_.reset();
126   }
127
128  private:
129   scoped_ptr<ResourceFetcher> fetcher_;
130 };
131
132 class ResourceFetcherTests : public ContentBrowserTest {
133  public:
134   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
135     command_line->AppendSwitch(switches::kSingleProcess);
136 #if defined(OS_WIN)
137     // Don't want to try to create a GPU process.
138     command_line->AppendSwitch(switches::kDisableGpu);
139 #endif
140   }
141
142   RenderView* GetRenderView() {
143     // We could have the test on the UI thread get the WebContent's routing ID,
144     // but we know this will be the first RV so skip that and just hardcode it.
145     return RenderView::FromRoutingID(kRenderViewRoutingId);
146   }
147
148   void ResourceFetcherDownloadOnRenderer(const GURL& url) {
149     WebFrame* frame = GetRenderView()->GetWebView()->mainFrame();
150
151     scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate);
152     scoped_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(url));
153     fetcher->Start(frame,
154                    WebURLRequest::RequestContextInternal,
155                    WebURLRequest::FrameTypeNone,
156                    ResourceFetcher::PLATFORM_LOADER,
157                    delegate->NewCallback());
158
159     delegate->WaitForResponse();
160
161     ASSERT_TRUE(delegate->completed());
162     EXPECT_EQ(delegate->response().httpStatusCode(), 200);
163     std::string text = delegate->data();
164     EXPECT_TRUE(text.find("Basic html test.") != std::string::npos);
165   }
166
167   void ResourceFetcher404OnRenderer(const GURL& url) {
168     WebFrame* frame = GetRenderView()->GetWebView()->mainFrame();
169
170     scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate);
171     scoped_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(url));
172     fetcher->Start(frame,
173                    WebURLRequest::RequestContextInternal,
174                    WebURLRequest::FrameTypeNone,
175                    ResourceFetcher::PLATFORM_LOADER,
176                    delegate->NewCallback());
177
178     delegate->WaitForResponse();
179
180     ASSERT_TRUE(delegate->completed());
181     EXPECT_EQ(delegate->response().httpStatusCode(), 404);
182     EXPECT_TRUE(delegate->data().find("Not Found.") != std::string::npos);
183   }
184
185   void ResourceFetcherDidFailOnRenderer() {
186     WebFrame* frame = GetRenderView()->GetWebView()->mainFrame();
187
188     // Try to fetch a page on a site that doesn't exist.
189     GURL url("http://localhost:1339/doesnotexist");
190     scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate);
191     scoped_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(url));
192     fetcher->Start(frame,
193                    WebURLRequest::RequestContextInternal,
194                    WebURLRequest::FrameTypeNone,
195                    ResourceFetcher::PLATFORM_LOADER,
196                    delegate->NewCallback());
197
198     delegate->WaitForResponse();
199
200     // When we fail, we still call the Delegate callback but we pass in empty
201     // values.
202     EXPECT_TRUE(delegate->completed());
203     EXPECT_TRUE(delegate->response().isNull());
204     EXPECT_EQ(delegate->data(), std::string());
205     EXPECT_FALSE(delegate->timed_out());
206   }
207
208   void ResourceFetcherTimeoutOnRenderer(const GURL& url) {
209     WebFrame* frame = GetRenderView()->GetWebView()->mainFrame();
210
211     scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate);
212     scoped_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(url));
213     fetcher->Start(frame,
214                    WebURLRequest::RequestContextInternal,
215                    WebURLRequest::FrameTypeNone,
216                    ResourceFetcher::PLATFORM_LOADER,
217                    delegate->NewCallback());
218     fetcher->SetTimeout(base::TimeDelta());
219
220     delegate->WaitForResponse();
221
222     // When we timeout, we still call the Delegate callback but we pass in empty
223     // values.
224     EXPECT_TRUE(delegate->completed());
225     EXPECT_TRUE(delegate->response().isNull());
226     EXPECT_EQ(delegate->data(), std::string());
227     EXPECT_FALSE(delegate->timed_out());
228   }
229
230   void ResourceFetcherDeletedInCallbackOnRenderer(const GURL& url) {
231     WebFrame* frame = GetRenderView()->GetWebView()->mainFrame();
232
233     scoped_ptr<EvilFetcherDelegate> delegate(new EvilFetcherDelegate);
234     scoped_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(url));
235     fetcher->Start(frame,
236                    WebURLRequest::RequestContextInternal,
237                    WebURLRequest::FrameTypeNone,
238                    ResourceFetcher::PLATFORM_LOADER,
239                    delegate->NewCallback());
240     fetcher->SetTimeout(base::TimeDelta());
241     delegate->SetFetcher(fetcher.release());
242
243     delegate->WaitForResponse();
244     EXPECT_FALSE(delegate->timed_out());
245   }
246
247   void ResourceFetcherPost(const GURL& url) {
248     const char* kBody = "Really nifty POST body!";
249
250     WebFrame* frame = GetRenderView()->GetWebView()->mainFrame();
251
252     scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate);
253     scoped_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(url));
254     fetcher->SetMethod("POST");
255     fetcher->SetBody(kBody);
256     fetcher->Start(frame,
257                    WebURLRequest::RequestContextInternal,
258                    WebURLRequest::FrameTypeNone,
259                    ResourceFetcher::PLATFORM_LOADER,
260                    delegate->NewCallback());
261
262     delegate->WaitForResponse();
263     ASSERT_TRUE(delegate->completed());
264     EXPECT_EQ(delegate->response().httpStatusCode(), 200);
265     EXPECT_EQ(kBody, delegate->data());
266   }
267
268   void ResourceFetcherSetHeader(const GURL& url) {
269     const char* kHeader = "Rather boring header.";
270
271     WebFrame* frame = GetRenderView()->GetWebView()->mainFrame();
272
273     scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate);
274     scoped_ptr<ResourceFetcher> fetcher(ResourceFetcher::Create(url));
275     fetcher->SetHeader("header", kHeader);
276     fetcher->Start(frame,
277                    WebURLRequest::RequestContextInternal,
278                    WebURLRequest::FrameTypeNone,
279                    ResourceFetcher::PLATFORM_LOADER,
280                    delegate->NewCallback());
281
282     delegate->WaitForResponse();
283     ASSERT_TRUE(delegate->completed());
284     EXPECT_EQ(delegate->response().httpStatusCode(), 200);
285     EXPECT_EQ(kHeader, delegate->data());
286   }
287 };
288
289 #if defined(OS_ANDROID)
290 // Disable (http://crbug.com/248796).
291 #define MAYBE_ResourceFetcher404 DISABLED_ResourceFetcher404
292 #define MAYBE_ResourceFetcherDeletedInCallback \
293   DISABLED_ResourceFetcherDeletedInCallback
294 #define MAYBE_ResourceFetcherTimeout DISABLED_ResourceFetcherTimeout
295 #define MAYBE_ResourceFetcherDownload DISABLED_ResourceFetcherDownload
296 // Disable (http://crbug.com/341142).
297 #define MAYBE_ResourceFetcherPost DISABLED_ResourceFetcherPost
298 #define MAYBE_ResourceFetcherSetHeader DISABLED_ResourceFetcherSetHeader
299 #else
300 #define MAYBE_ResourceFetcher404 ResourceFetcher404
301 #define MAYBE_ResourceFetcherDeletedInCallback ResourceFetcherDeletedInCallback
302 #define MAYBE_ResourceFetcherTimeout ResourceFetcherTimeout
303 #define MAYBE_ResourceFetcherDownload ResourceFetcherDownload
304 #define MAYBE_ResourceFetcherPost ResourceFetcherPost
305 #define MAYBE_ResourceFetcherSetHeader ResourceFetcherSetHeader
306 #endif
307
308 // Test a fetch from the test server.
309 // If this flakes, use http://crbug.com/51622.
310 IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, MAYBE_ResourceFetcherDownload) {
311   // Need to spin up the renderer.
312   NavigateToURL(shell(), GURL(url::kAboutBlankURL));
313
314   ASSERT_TRUE(test_server()->Start());
315   GURL url(test_server()->GetURL("files/simple_page.html"));
316
317   PostTaskToInProcessRendererAndWait(
318         base::Bind(&ResourceFetcherTests::ResourceFetcherDownloadOnRenderer,
319                    base::Unretained(this), url));
320 }
321
322 IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, MAYBE_ResourceFetcher404) {
323   // Need to spin up the renderer.
324   NavigateToURL(shell(), GURL(url::kAboutBlankURL));
325
326   // Test 404 response.
327   ASSERT_TRUE(test_server()->Start());
328   GURL url = test_server()->GetURL("files/thisfiledoesntexist.html");
329
330   PostTaskToInProcessRendererAndWait(
331         base::Bind(&ResourceFetcherTests::ResourceFetcher404OnRenderer,
332                    base::Unretained(this), url));
333 }
334
335 // If this flakes, use http://crbug.com/51622.
336 IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcherDidFail) {
337   // Need to spin up the renderer.
338   NavigateToURL(shell(), GURL(url::kAboutBlankURL));
339
340   PostTaskToInProcessRendererAndWait(
341         base::Bind(&ResourceFetcherTests::ResourceFetcherDidFailOnRenderer,
342                    base::Unretained(this)));
343 }
344
345 IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, MAYBE_ResourceFetcherTimeout) {
346   // Need to spin up the renderer.
347   NavigateToURL(shell(), GURL(url::kAboutBlankURL));
348
349   // Grab a page that takes at least 1 sec to respond, but set the fetcher to
350   // timeout in 0 sec.
351   ASSERT_TRUE(test_server()->Start());
352   GURL url(test_server()->GetURL("slow?1"));
353
354   PostTaskToInProcessRendererAndWait(
355         base::Bind(&ResourceFetcherTests::ResourceFetcherTimeoutOnRenderer,
356                    base::Unretained(this), url));
357 }
358
359 IN_PROC_BROWSER_TEST_F(ResourceFetcherTests,
360                        MAYBE_ResourceFetcherDeletedInCallback) {
361   // Need to spin up the renderer.
362   NavigateToURL(shell(), GURL(url::kAboutBlankURL));
363
364   // Grab a page that takes at least 1 sec to respond, but set the fetcher to
365   // timeout in 0 sec.
366   ASSERT_TRUE(test_server()->Start());
367   GURL url(test_server()->GetURL("slow?1"));
368
369   PostTaskToInProcessRendererAndWait(
370         base::Bind(
371             &ResourceFetcherTests::ResourceFetcherDeletedInCallbackOnRenderer,
372             base::Unretained(this), url));
373 }
374
375
376
377 // Test that ResourceFetchers can handle POSTs.
378 IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, MAYBE_ResourceFetcherPost) {
379   // Need to spin up the renderer.
380   NavigateToURL(shell(), GURL(url::kAboutBlankURL));
381
382   // Grab a page that echos the POST body.
383   ASSERT_TRUE(test_server()->Start());
384   GURL url(test_server()->GetURL("echo"));
385
386   PostTaskToInProcessRendererAndWait(
387         base::Bind(
388             &ResourceFetcherTests::ResourceFetcherPost,
389             base::Unretained(this), url));
390 }
391
392 // Test that ResourceFetchers can set headers.
393 IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, MAYBE_ResourceFetcherSetHeader) {
394   // Need to spin up the renderer.
395   NavigateToURL(shell(), GURL(url::kAboutBlankURL));
396
397   // Grab a page that echos the POST body.
398   ASSERT_TRUE(test_server()->Start());
399   GURL url(test_server()->GetURL("echoheader?header"));
400
401   PostTaskToInProcessRendererAndWait(
402         base::Bind(
403             &ResourceFetcherTests::ResourceFetcherSetHeader,
404             base::Unretained(this), url));
405 }
406
407 }  // namespace content