Update To 11.40.268.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/content_browser_test.h"
23 #include "content/public/test/content_browser_test_utils.h"
24 #include "content/public/test/test_utils.h"
25 #include "content/shell/browser/shell.h"
26 #include "content/shell/browser/shell_browser_context.h"
27 #include "content/shell/browser/shell_content_browser_client.h"
28 #include "content/shell/common/shell_content_client.h"
29 #include "content/shell/renderer/shell_content_renderer_client.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   void GetNavigationErrorStrings(content::RenderView* render_view,
53                                  blink::WebFrame* frame,
54                                  const blink::WebURLRequest& failed_request,
55                                  const blink::WebURLError& error,
56                                  std::string* error_html,
57                                  base::string16* error_description) override {
58     if (error_html)
59       *error_html = "A suffusion of yellow.";
60     latest_error_valid_ = true;
61     latest_error_reason_ = error.reason;
62     latest_error_stale_copy_in_cache_ = error.staleCopyInCache;
63   }
64
65   bool GetLatestError(int* error_code, bool* stale_cache_entry_present) {
66     if (latest_error_valid_) {
67       *error_code = latest_error_reason_;
68       *stale_cache_entry_present = latest_error_stale_copy_in_cache_;
69     }
70     return latest_error_valid_;
71   }
72
73  private:
74   bool latest_error_valid_;
75   int latest_error_reason_;
76   bool latest_error_stale_copy_in_cache_;
77 };
78
79 // Must be called on IO thread.
80 void InterceptNetworkTransactions(net::URLRequestContextGetter* getter,
81                                   net::Error error) {
82   DCHECK(content::BrowserThread::CurrentlyOn(BrowserThread::IO));
83   net::HttpCache* cache(
84       getter->GetURLRequestContext()->http_transaction_factory()->GetCache());
85   DCHECK(cache);
86   scoped_ptr<net::FailingHttpTransactionFactory> factory(
87       new net::FailingHttpTransactionFactory(cache->GetSession(), error));
88   // Throw away old version; since this is a browser test, there is no
89   // need to restore the old state.
90   cache->SetHttpNetworkTransactionFactoryForTesting(factory.Pass());
91 }
92
93 void CallOnUIThreadValidatingReturn(const base::Closure& callback,
94                                     int rv) {
95   DCHECK_EQ(net::OK, rv);
96   BrowserThread::PostTask(
97       BrowserThread::UI, FROM_HERE, callback);
98 }
99
100 // Must be called on IO thread.  The callback will be called on
101 // completion of cache clearing on the UI thread.
102 void BackendClearCache(scoped_ptr<disk_cache::Backend*> backend,
103                        const base::Closure& callback,
104                        int rv) {
105   DCHECK(*backend);
106   DCHECK_EQ(net::OK, rv);
107   (*backend)->DoomAllEntries(
108       base::Bind(&CallOnUIThreadValidatingReturn, callback));
109 }
110
111 // Must be called on IO thread.  The callback will be called on
112 // completion of cache clearing on the UI thread.
113 void ClearCache(net::URLRequestContextGetter* getter,
114                 const base::Closure& callback) {
115   DCHECK(content::BrowserThread::CurrentlyOn(BrowserThread::IO));
116   net::HttpCache* cache(
117       getter->GetURLRequestContext()->http_transaction_factory()->GetCache());
118   DCHECK(cache);
119   scoped_ptr<disk_cache::Backend*> backend(new disk_cache::Backend*);
120   *backend = NULL;
121   disk_cache::Backend** backend_ptr = backend.get();
122
123   net::CompletionCallback backend_callback(
124       base::Bind(&BackendClearCache, base::Passed(backend.Pass()), callback));
125
126   // backend_ptr is valid until all copies of backend_callback go out
127   // of scope.
128   if (net::OK == cache->GetBackend(backend_ptr, backend_callback)) {
129     // The call completed synchronously, so GetBackend didn't run the callback.
130     backend_callback.Run(net::OK);
131   }
132 }
133
134 }  // namespace
135
136 class RenderViewBrowserTest : public ContentBrowserTest {
137  public:
138   RenderViewBrowserTest() {}
139
140   void SetUpCommandLine(CommandLine* command_line) override {
141     // This method is needed to allow interaction with in-process renderer
142     // and use of a test ContentRendererClient.
143     command_line->AppendSwitch(switches::kSingleProcess);
144   }
145
146   void SetUpOnMainThread() override {
147     // Override setting of renderer client.
148     renderer_client_ = new TestShellContentRendererClient();
149     // Explicitly leaks ownership; this object will remain alive
150     // until process death.  We don't deleted the returned value,
151     // since some contexts set the pointer to a non-heap address.
152     SetRendererClientForTesting(renderer_client_);
153   }
154
155   // Navigates to the given URL and waits for |num_navigations| to occur, and
156   // the title to change to |expected_title|.
157   void NavigateToURLAndWaitForTitle(const GURL& url,
158                                     const std::string& expected_title,
159                                     int num_navigations) {
160     content::TitleWatcher title_watcher(
161         shell()->web_contents(), base::ASCIIToUTF16(expected_title));
162
163     content::NavigateToURLBlockUntilNavigationsComplete(
164         shell(), url, num_navigations);
165
166     EXPECT_EQ(base::ASCIIToUTF16(expected_title),
167               title_watcher.WaitAndGetTitle());
168   }
169
170   // Returns true if there is a valid error stored; in this case
171   // |*error_code| and |*stale_cache_entry_present| will be updated
172   // appropriately.
173   // Must be called after the renderer thread is created.
174   bool GetLatestErrorFromRendererClient(
175       int* error_code, bool* stale_cache_entry_present) {
176     bool result = false;
177
178     PostTaskToInProcessRendererAndWait(
179         base::Bind(&RenderViewBrowserTest::GetLatestErrorFromRendererClient0,
180                    renderer_client_, &result, error_code,
181                    stale_cache_entry_present));
182     return result;
183   }
184
185  private:
186   // Must be run on renderer thread.
187   static void GetLatestErrorFromRendererClient0(
188       TestShellContentRendererClient* renderer_client,
189       bool* result, int* error_code, bool* stale_cache_entry_present) {
190     *result = renderer_client->GetLatestError(
191         error_code, stale_cache_entry_present);
192   }
193
194   TestShellContentRendererClient* renderer_client_;
195 };
196
197 IN_PROC_BROWSER_TEST_F(RenderViewBrowserTest, ConfirmCacheInformationPlumbed) {
198   ASSERT_TRUE(test_server()->Start());
199
200   // Load URL with "nocache" set, to create stale cache.
201   GURL test_url(test_server()->GetURL("files/nocache.html"));
202   NavigateToURLAndWaitForTitle(test_url, "Nocache Test Page", 1);
203
204   // Reload same URL after forcing an error from the the network layer;
205   // confirm that the error page is told the cached copy exists.
206   int renderer_id =
207       shell()->web_contents()->GetMainFrame()->GetProcess()->GetID();
208   scoped_refptr<net::URLRequestContextGetter> url_request_context_getter =
209       ShellContentBrowserClient::Get()->browser_context()->
210           GetRequestContextForRenderProcess(renderer_id);
211   BrowserThread::PostTask(
212       BrowserThread::IO, FROM_HERE,
213       base::Bind(&InterceptNetworkTransactions, url_request_context_getter,
214                  net::ERR_FAILED));
215
216   // An error results in one completed navigation.
217   NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1);
218   int error_code = net::OK;
219   bool stale_cache_entry_present = false;
220   ASSERT_TRUE(GetLatestErrorFromRendererClient(
221       &error_code, &stale_cache_entry_present));
222   EXPECT_EQ(net::ERR_FAILED, error_code);
223   EXPECT_TRUE(stale_cache_entry_present);
224
225   // Clear the cache and repeat; confirm lack of entry in cache reported.
226   scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner;
227   BrowserThread::PostTask(
228       BrowserThread::IO, FROM_HERE,
229       base::Bind(&ClearCache, url_request_context_getter,
230                  runner->QuitClosure()));
231   runner->Run();
232
233   content::NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1);
234
235   error_code = net::OK;
236   stale_cache_entry_present = true;
237   ASSERT_TRUE(GetLatestErrorFromRendererClient(
238       &error_code, &stale_cache_entry_present));
239   EXPECT_EQ(net::ERR_FAILED, error_code);
240   EXPECT_FALSE(stale_cache_entry_present);
241 }
242
243 }  // namespace content