blob: 380f95f33b4eca014cd881541b5e0c9cab2c419e [file] [log] [blame]
[email protected]c81b2b72014-02-13 04:04:081// 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
dcheng07945f632015-12-26 07:59:329#include <utility>
10
[email protected]c81b2b72014-02-13 04:04:0811#include "base/bind.h"
12#include "base/callback.h"
13#include "base/command_line.h"
14#include "base/strings/utf_string_conversions.h"
15#include "content/public/browser/browser_context.h"
16#include "content/public/browser/browser_thread.h"
17#include "content/public/browser/render_frame_host.h"
18#include "content/public/browser/render_process_host.h"
19#include "content/public/browser/web_contents.h"
20#include "content/public/common/content_switches.h"
21#include "content/public/renderer/render_view.h"
22#include "content/public/test/browser_test_utils.h"
[email protected]6e9def12014-03-27 20:23:2823#include "content/public/test/content_browser_test.h"
24#include "content/public/test/content_browser_test_utils.h"
[email protected]c81b2b72014-02-13 04:04:0825#include "content/public/test/test_utils.h"
26#include "content/shell/browser/shell.h"
27#include "content/shell/browser/shell_browser_context.h"
28#include "content/shell/browser/shell_content_browser_client.h"
29#include "content/shell/common/shell_content_client.h"
30#include "content/shell/renderer/shell_content_renderer_client.h"
[email protected]c81b2b72014-02-13 04:04:0831#include "net/base/net_errors.h"
32#include "net/disk_cache/disk_cache.h"
33#include "net/http/failing_http_transaction_factory.h"
34#include "net/http/http_cache.h"
35#include "net/url_request/url_request_context.h"
36#include "net/url_request/url_request_context_getter.h"
37#include "testing/gtest/include/gtest/gtest.h"
38#include "third_party/WebKit/public/platform/WebURLError.h"
39#include "third_party/WebKit/public/platform/WebURLRequest.h"
40#include "third_party/WebKit/public/web/WebFrame.h"
41
42namespace content {
43
44namespace {
45
46class TestShellContentRendererClient : public ShellContentRendererClient {
47 public:
48 TestShellContentRendererClient()
49 : latest_error_valid_(false),
50 latest_error_reason_(0),
51 latest_error_stale_copy_in_cache_(false) {}
52
mmenkef1c777e2015-10-27 21:06:4453 void GetNavigationErrorStrings(content::RenderFrame* render_frame,
dcheng6d18e402014-10-21 12:32:5254 const blink::WebURLRequest& failed_request,
55 const blink::WebURLError& error,
56 std::string* error_html,
57 base::string16* error_description) override {
[email protected]c81b2b72014-02-13 04:04:0858 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.
80void InterceptNetworkTransactions(net::URLRequestContextGetter* getter,
81 net::Error error) {
thestig475bf9102015-09-08 23:50:2382 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]c81b2b72014-02-13 04:04:0883 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.
dcheng07945f632015-12-26 07:59:3290 cache->SetHttpNetworkTransactionFactoryForTesting(std::move(factory));
[email protected]c81b2b72014-02-13 04:04:0891}
92
93void 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.
102void 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.
113void ClearCache(net::URLRequestContextGetter* getter,
114 const base::Closure& callback) {
thestig475bf9102015-09-08 23:50:23115 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]c81b2b72014-02-13 04:04:08116 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
dcheng07945f632015-12-26 07:59:32123 net::CompletionCallback backend_callback(base::Bind(
124 &BackendClearCache, base::Passed(std::move(backend)), callback));
[email protected]c81b2b72014-02-13 04:04:08125
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
136class RenderViewBrowserTest : public ContentBrowserTest {
137 public:
[email protected]a88f6362014-03-18 04:25:35138 RenderViewBrowserTest() {}
[email protected]c81b2b72014-02-13 04:04:08139
avi83883c82014-12-23 00:08:49140 void SetUpCommandLine(base::CommandLine* command_line) override {
[email protected]c81b2b72014-02-13 04:04:08141 // 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
dcheng6d18e402014-10-21 12:32:52146 void SetUpOnMainThread() override {
[email protected]c81b2b72014-02-13 04:04:08147 // Override setting of renderer client.
[email protected]cf03eb42014-03-20 00:35:55148 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_);
[email protected]c81b2b72014-02-13 04:04:08153 }
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,
[email protected]cf03eb42014-03-20 00:35:55180 renderer_client_, &result, error_code,
[email protected]c81b2b72014-02-13 04:04:08181 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
[email protected]cf03eb42014-03-20 00:35:55194 TestShellContentRendererClient* renderer_client_;
[email protected]c81b2b72014-02-13 04:04:08195};
196
[email protected]cf03eb42014-03-20 00:35:55197IN_PROC_BROWSER_TEST_F(RenderViewBrowserTest, ConfirmCacheInformationPlumbed) {
svaldezc3a9a172015-11-03 22:01:33198 ASSERT_TRUE(embedded_test_server()->Start());
[email protected]c81b2b72014-02-13 04:04:08199
200 // Load URL with "nocache" set, to create stale cache.
svaldezc3a9a172015-11-03 22:01:33201 GURL test_url(embedded_test_server()->GetURL("/nocache.html"));
[email protected]c81b2b72014-02-13 04:04:08202 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