Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / content / renderer / browser_render_view_browsertest.cc
1 // Copyright 2014 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 // Browser tests targeted at the RenderView that run in browser context.
6 // Note that these tests rely on single-process mode, and hence may be
7 // disabled in some configurations (check gyp files).
8
9 #include "base/basictypes.h"
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/command_line.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "content/public/browser/browser_context.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "content/public/browser/render_frame_host.h"
17 #include "content/public/browser/render_process_host.h"
18 #include "content/public/browser/web_contents.h"
19 #include "content/public/common/content_switches.h"
20 #include "content/public/renderer/render_view.h"
21 #include "content/public/test/browser_test_utils.h"
22 #include "content/public/test/test_utils.h"
23 #include "content/shell/browser/shell.h"
24 #include "content/shell/browser/shell_browser_context.h"
25 #include "content/shell/browser/shell_content_browser_client.h"
26 #include "content/shell/common/shell_content_client.h"
27 #include "content/shell/renderer/shell_content_renderer_client.h"
28 #include "content/test/content_browser_test.h"
29 #include "content/test/content_browser_test_utils.h"
30 #include "net/base/net_errors.h"
31 #include "net/disk_cache/disk_cache.h"
32 #include "net/http/failing_http_transaction_factory.h"
33 #include "net/http/http_cache.h"
34 #include "net/url_request/url_request_context.h"
35 #include "net/url_request/url_request_context_getter.h"
36 #include "testing/gtest/include/gtest/gtest.h"
37 #include "third_party/WebKit/public/platform/WebURLError.h"
38 #include "third_party/WebKit/public/platform/WebURLRequest.h"
39 #include "third_party/WebKit/public/web/WebFrame.h"
40
41 namespace content {
42
43 namespace {
44
45 class TestShellContentRendererClient : public ShellContentRendererClient {
46  public:
47   TestShellContentRendererClient()
48       : latest_error_valid_(false),
49         latest_error_reason_(0),
50         latest_error_stale_copy_in_cache_(false) {}
51
52   virtual void GetNavigationErrorStrings(
53       content::RenderView* render_view,
54       blink::WebFrame* frame,
55       const blink::WebURLRequest& failed_request,
56       const blink::WebURLError& error,
57       std::string* error_html,
58       base::string16* error_description) OVERRIDE {
59     if (error_html)
60       *error_html = "A suffusion of yellow.";
61     latest_error_valid_ = true;
62     latest_error_reason_ = error.reason;
63     latest_error_stale_copy_in_cache_ = error.staleCopyInCache;
64   }
65
66   bool GetLatestError(int* error_code, bool* stale_cache_entry_present) {
67     if (latest_error_valid_) {
68       *error_code = latest_error_reason_;
69       *stale_cache_entry_present = latest_error_stale_copy_in_cache_;
70     }
71     return latest_error_valid_;
72   }
73
74  private:
75   bool latest_error_valid_;
76   int latest_error_reason_;
77   bool latest_error_stale_copy_in_cache_;
78 };
79
80 // Must be called on IO thread.
81 void InterceptNetworkTransactions(net::URLRequestContextGetter* getter,
82                                   net::Error error) {
83   DCHECK(content::BrowserThread::CurrentlyOn(BrowserThread::IO));
84   net::HttpCache* cache(
85       getter->GetURLRequestContext()->http_transaction_factory()->GetCache());
86   DCHECK(cache);
87   scoped_ptr<net::FailingHttpTransactionFactory> factory(
88       new net::FailingHttpTransactionFactory(cache->GetSession(), error));
89   // Throw away old version; since this is a browser test, there is no
90   // need to restore the old state.
91   cache->SetHttpNetworkTransactionFactoryForTesting(
92       factory.PassAs<net::HttpTransactionFactory>());
93 }
94
95 void CallOnUIThreadValidatingReturn(const base::Closure& callback,
96                                     int rv) {
97   DCHECK_EQ(net::OK, rv);
98   BrowserThread::PostTask(
99       BrowserThread::UI, FROM_HERE, callback);
100 }
101
102 // Must be called on IO thread.  The callback will be called on
103 // completion of cache clearing on the UI thread.
104 void BackendClearCache(scoped_ptr<disk_cache::Backend*> backend,
105                        const base::Closure& callback,
106                        int rv) {
107   DCHECK(*backend);
108   DCHECK_EQ(net::OK, rv);
109   (*backend)->DoomAllEntries(
110       base::Bind(&CallOnUIThreadValidatingReturn, callback));
111 }
112
113 // Must be called on IO thread.  The callback will be called on
114 // completion of cache clearing on the UI thread.
115 void ClearCache(net::URLRequestContextGetter* getter,
116                 const base::Closure& callback) {
117   DCHECK(content::BrowserThread::CurrentlyOn(BrowserThread::IO));
118   net::HttpCache* cache(
119       getter->GetURLRequestContext()->http_transaction_factory()->GetCache());
120   DCHECK(cache);
121   scoped_ptr<disk_cache::Backend*> backend(new disk_cache::Backend*);
122   *backend = NULL;
123   disk_cache::Backend** backend_ptr = backend.get();
124
125   net::CompletionCallback backend_callback(
126       base::Bind(&BackendClearCache, base::Passed(backend.Pass()), callback));
127
128   // backend_ptr is valid until all copies of backend_callback go out
129   // of scope.
130   if (net::OK == cache->GetBackend(backend_ptr, backend_callback)) {
131     // The call completed synchronously, so GetBackend didn't run the callback.
132     backend_callback.Run(net::OK);
133   }
134 }
135
136 }  // namespace
137
138 class RenderViewBrowserTest : public ContentBrowserTest {
139  public:
140   RenderViewBrowserTest() : renderer_client_(NULL) {}
141
142   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
143     // This method is needed to allow interaction with in-process renderer
144     // and use of a test ContentRendererClient.
145     command_line->AppendSwitch(switches::kSingleProcess);
146   }
147
148   virtual void SetUp() OVERRIDE {
149     // Override setting of renderer client.
150     renderer_client_ = new TestShellContentRendererClient();
151     SetContentRendererClient(
152         scoped_ptr<ContentRendererClient>(renderer_client_).Pass());
153
154     ContentBrowserTest::SetUp();
155   }
156
157   // Navigates to the given URL and waits for |num_navigations| to occur, and
158   // the title to change to |expected_title|.
159   void NavigateToURLAndWaitForTitle(const GURL& url,
160                                     const std::string& expected_title,
161                                     int num_navigations) {
162     content::TitleWatcher title_watcher(
163         shell()->web_contents(), base::ASCIIToUTF16(expected_title));
164
165     content::NavigateToURLBlockUntilNavigationsComplete(
166         shell(), url, num_navigations);
167
168     EXPECT_EQ(base::ASCIIToUTF16(expected_title),
169               title_watcher.WaitAndGetTitle());
170   }
171
172   // Returns true if there is a valid error stored; in this case
173   // |*error_code| and |*stale_cache_entry_present| will be updated
174   // appropriately.
175   // Must be called after the renderer thread is created.
176   bool GetLatestErrorFromRendererClient(
177       int* error_code, bool* stale_cache_entry_present) {
178     bool result = false;
179
180     PostTaskToInProcessRendererAndWait(
181         base::Bind(&RenderViewBrowserTest::GetLatestErrorFromRendererClient0,
182                    renderer_client_, &result, error_code,
183                    stale_cache_entry_present));
184     return result;
185   }
186
187  private:
188   // Must be run on renderer thread.
189   static void GetLatestErrorFromRendererClient0(
190       TestShellContentRendererClient* renderer_client,
191       bool* result, int* error_code, bool* stale_cache_entry_present) {
192     *result = renderer_client->GetLatestError(
193         error_code, stale_cache_entry_present);
194   }
195
196   // Actually owned by the superclass, so safe to keep a bare pointer.
197   TestShellContentRendererClient* renderer_client_;
198 };
199
200 #if defined(OS_ANDROID)
201 // Flaky https://crbug.com/341745
202 #define MAYBE_ConfirmCacheInformationPlumbed DISABLED_ConfirmCacheInformationPlumbed
203 #else
204 #define MAYBE_ConfirmCacheInformationPlumbed ConfirmCacheInformationPlumbed
205 #endif
206
207 IN_PROC_BROWSER_TEST_F(RenderViewBrowserTest,
208                        MAYBE_ConfirmCacheInformationPlumbed) {
209   ASSERT_TRUE(test_server()->Start());
210
211   // Load URL with "nocache" set, to create stale cache.
212   GURL test_url(test_server()->GetURL("files/nocache.html"));
213   NavigateToURLAndWaitForTitle(test_url, "Nocache Test Page", 1);
214
215   // Reload same URL after forcing an error from the the network layer;
216   // confirm that the error page is told the cached copy exists.
217   int renderer_id =
218       shell()->web_contents()->GetMainFrame()->GetProcess()->GetID();
219   scoped_refptr<net::URLRequestContextGetter> url_request_context_getter =
220       ShellContentBrowserClient::Get()->browser_context()->
221           GetRequestContextForRenderProcess(renderer_id);
222   BrowserThread::PostTask(
223       BrowserThread::IO, FROM_HERE,
224       base::Bind(&InterceptNetworkTransactions, url_request_context_getter,
225                  net::ERR_FAILED));
226
227   // An error results in one completed navigation.
228   NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1);
229   int error_code = net::OK;
230   bool stale_cache_entry_present = false;
231   ASSERT_TRUE(GetLatestErrorFromRendererClient(
232       &error_code, &stale_cache_entry_present));
233   EXPECT_EQ(net::ERR_FAILED, error_code);
234   EXPECT_TRUE(stale_cache_entry_present);
235
236   // Clear the cache and repeat; confirm lack of entry in cache reported.
237   scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner;
238   BrowserThread::PostTask(
239       BrowserThread::IO, FROM_HERE,
240       base::Bind(&ClearCache, url_request_context_getter,
241                  runner->QuitClosure()));
242   runner->Run();
243
244   content::NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1);
245
246   error_code = net::OK;
247   stale_cache_entry_present = true;
248   ASSERT_TRUE(GetLatestErrorFromRendererClient(
249       &error_code, &stale_cache_entry_present));
250   EXPECT_EQ(net::ERR_FAILED, error_code);
251   EXPECT_FALSE(stale_cache_entry_present);
252 }
253
254 }  // namespace content