- add sources.
[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/renderer/fetchers/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/timer/timer.h"
12 #include "content/public/common/content_switches.h"
13 #include "content/public/common/url_constants.h"
14 #include "content/public/renderer/render_view.h"
15 #include "content/public/test/test_utils.h"
16 #include "content/shell/browser/shell.h"
17 #include "content/test/content_browser_test.h"
18 #include "content/test/content_browser_test_utils.h"
19 #include "third_party/WebKit/public/platform/WebURLResponse.h"
20 #include "third_party/WebKit/public/web/WebFrame.h"
21 #include "third_party/WebKit/public/web/WebView.h"
22
23 using WebKit::WebFrame;
24 using WebKit::WebURLRequest;
25 using WebKit::WebURLResponse;
26
27 namespace content {
28
29 static const int kMaxWaitTimeMs = 5000;
30
31 class FetcherDelegate {
32  public:
33   FetcherDelegate()
34       : completed_(false),
35         timed_out_(false) {
36     // Start a repeating timer waiting for the download to complete.  The
37     // callback has to be a static function, so we hold on to our instance.
38     FetcherDelegate::instance_ = this;
39     StartTimer();
40   }
41
42   virtual ~FetcherDelegate() {}
43
44   ResourceFetcher::Callback NewCallback() {
45     return base::Bind(&FetcherDelegate::OnURLFetchComplete,
46                       base::Unretained(this));
47   }
48
49   virtual void OnURLFetchComplete(const WebURLResponse& response,
50                                   const std::string& data) {
51     response_ = response;
52     data_ = data;
53     completed_ = true;
54     timer_.Stop();
55     if (!timed_out_)
56       quit_task_.Run();
57   }
58
59   bool completed() const { return completed_; }
60   bool timed_out() const { return timed_out_; }
61
62   std::string data() const { return data_; }
63   const WebURLResponse& response() const { return response_; }
64
65   // Wait for the request to complete or timeout.
66   void WaitForResponse() {
67     scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner;
68     quit_task_ = runner->QuitClosure();
69     runner->Run();
70   }
71
72   void StartTimer() {
73     timer_.Start(FROM_HERE,
74                  base::TimeDelta::FromMilliseconds(kMaxWaitTimeMs),
75                  this,
76                  &FetcherDelegate::TimerFired);
77   }
78
79   void TimerFired() {
80     ASSERT_FALSE(completed_);
81
82     timed_out_ = true;
83     if (!completed_)
84       quit_task_.Run();
85     FAIL() << "fetch timed out";
86   }
87
88   static FetcherDelegate* instance_;
89
90  private:
91   base::OneShotTimer<FetcherDelegate> timer_;
92   bool completed_;
93   bool timed_out_;
94   WebURLResponse response_;
95   std::string data_;
96   base::Closure quit_task_;
97 };
98
99 FetcherDelegate* FetcherDelegate::instance_ = NULL;
100
101 class EvilFetcherDelegate : public FetcherDelegate {
102  public:
103   virtual ~EvilFetcherDelegate() {}
104
105   void SetFetcher(ResourceFetcher* fetcher) {
106     fetcher_.reset(fetcher);
107   }
108
109   virtual void OnURLFetchComplete(const WebURLResponse& response,
110                                   const std::string& data) OVERRIDE {
111     // Destroy the ResourceFetcher here.  We are testing that upon returning
112     // to the ResourceFetcher that it does not crash.
113     fetcher_.reset();
114     FetcherDelegate::OnURLFetchComplete(response, data);
115   }
116
117  private:
118   scoped_ptr<ResourceFetcher> fetcher_;
119 };
120
121 class ResourceFetcherTests : public ContentBrowserTest {
122  public:
123   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
124     command_line->AppendSwitch(switches::kSingleProcess);
125 #if defined(OS_WIN) && defined(USE_AURA)
126     // Don't want to try to create a GPU process.
127     command_line->AppendSwitch(switches::kDisableAcceleratedCompositing);
128 #endif
129   }
130
131   RenderView* GetRenderView() {
132     // We could have the test on the UI thread get the WebContent's routing ID,
133     // but we know this will be the first RV so skip that and just hardcode it.
134     return RenderView::FromRoutingID(1);
135   }
136
137   void ResourceFetcherDownloadOnRenderer(const GURL& url) {
138     WebFrame* frame = GetRenderView()->GetWebView()->mainFrame();
139
140     scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate);
141     scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcher(
142         url, frame, WebURLRequest::TargetIsMainFrame, delegate->NewCallback()));
143
144     delegate->WaitForResponse();
145
146     ASSERT_TRUE(delegate->completed());
147     EXPECT_EQ(delegate->response().httpStatusCode(), 200);
148     std::string text = delegate->data();
149     EXPECT_TRUE(text.find("Basic html test.") != std::string::npos);
150   }
151
152   void ResourceFetcher404OnRenderer(const GURL& url) {
153     WebFrame* frame = GetRenderView()->GetWebView()->mainFrame();
154
155     scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate);
156     scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcher(
157         url, frame, WebURLRequest::TargetIsMainFrame, delegate->NewCallback()));
158
159     delegate->WaitForResponse();
160
161     ASSERT_TRUE(delegate->completed());
162     EXPECT_EQ(delegate->response().httpStatusCode(), 404);
163     EXPECT_TRUE(delegate->data().find("Not Found.") != std::string::npos);
164   }
165
166   void ResourceFetcherDidFailOnRenderer() {
167     WebFrame* frame = GetRenderView()->GetWebView()->mainFrame();
168
169     // Try to fetch a page on a site that doesn't exist.
170     GURL url("http://localhost:1339/doesnotexist");
171     scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate);
172     scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcher(
173         url, frame, WebURLRequest::TargetIsMainFrame, delegate->NewCallback()));
174
175     delegate->WaitForResponse();
176
177     // When we fail, we still call the Delegate callback but we pass in empty
178     // values.
179     EXPECT_TRUE(delegate->completed());
180     EXPECT_TRUE(delegate->response().isNull());
181     EXPECT_EQ(delegate->data(), std::string());
182     EXPECT_FALSE(delegate->timed_out());
183   }
184
185   void ResourceFetcherTimeoutOnRenderer(const GURL& url) {
186     WebFrame* frame = GetRenderView()->GetWebView()->mainFrame();
187
188     scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate);
189     scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcherWithTimeout(
190         url, frame, WebURLRequest::TargetIsMainFrame,
191         0, delegate->NewCallback()));
192
193     delegate->WaitForResponse();
194
195     // When we timeout, we still call the Delegate callback but we pass in empty
196     // values.
197     EXPECT_TRUE(delegate->completed());
198     EXPECT_TRUE(delegate->response().isNull());
199     EXPECT_EQ(delegate->data(), std::string());
200     EXPECT_FALSE(delegate->timed_out());
201   }
202
203   void ResourceFetcherDeletedInCallbackOnRenderer(const GURL& url) {
204     WebFrame* frame = GetRenderView()->GetWebView()->mainFrame();
205
206     scoped_ptr<EvilFetcherDelegate> delegate(new EvilFetcherDelegate);
207     scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcherWithTimeout(
208         url, frame, WebURLRequest::TargetIsMainFrame,
209         0, delegate->NewCallback()));
210     delegate->SetFetcher(fetcher.release());
211
212     delegate->WaitForResponse();
213     EXPECT_FALSE(delegate->timed_out());
214   }
215 };
216
217 // Test a fetch from the test server.
218 // If this flakes, use http://crbug.com/51622.
219 IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcherDownload) {
220   // Need to spin up the renderer.
221   NavigateToURL(shell(), GURL(kAboutBlankURL));
222
223   ASSERT_TRUE(test_server()->Start());
224   GURL url(test_server()->GetURL("files/simple_page.html"));
225
226   PostTaskToInProcessRendererAndWait(
227         base::Bind(&ResourceFetcherTests::ResourceFetcherDownloadOnRenderer,
228                    base::Unretained(this), url));
229 }
230
231 IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcher404) {
232   // Need to spin up the renderer.
233   NavigateToURL(shell(), GURL(kAboutBlankURL));
234
235   // Test 404 response.
236   ASSERT_TRUE(test_server()->Start());
237   GURL url = test_server()->GetURL("files/thisfiledoesntexist.html");
238
239   PostTaskToInProcessRendererAndWait(
240         base::Bind(&ResourceFetcherTests::ResourceFetcher404OnRenderer,
241                    base::Unretained(this), url));
242 }
243
244 // If this flakes, use http://crbug.com/51622.
245 IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcherDidFail) {
246   // Need to spin up the renderer.
247   NavigateToURL(shell(), GURL(kAboutBlankURL));
248
249   PostTaskToInProcessRendererAndWait(
250         base::Bind(&ResourceFetcherTests::ResourceFetcherDidFailOnRenderer,
251                    base::Unretained(this)));
252 }
253
254 IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcherTimeout) {
255   // Need to spin up the renderer.
256   NavigateToURL(shell(), GURL(kAboutBlankURL));
257
258   // Grab a page that takes at least 1 sec to respond, but set the fetcher to
259   // timeout in 0 sec.
260   ASSERT_TRUE(test_server()->Start());
261   GURL url(test_server()->GetURL("slow?1"));
262
263   PostTaskToInProcessRendererAndWait(
264         base::Bind(&ResourceFetcherTests::ResourceFetcherTimeoutOnRenderer,
265                    base::Unretained(this), url));
266 }
267
268 IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcherDeletedInCallback) {
269   // Need to spin up the renderer.
270   NavigateToURL(shell(), GURL(kAboutBlankURL));
271
272   // Grab a page that takes at least 1 sec to respond, but set the fetcher to
273   // timeout in 0 sec.
274   ASSERT_TRUE(test_server()->Start());
275   GURL url(test_server()->GetURL("slow?1"));
276
277   PostTaskToInProcessRendererAndWait(
278         base::Bind(
279             &ResourceFetcherTests::ResourceFetcherDeletedInCallbackOnRenderer,
280             base::Unretained(this), url));
281 }
282
283 }  // namespace content