Index: content/renderer/browser_render_view_browsertest.cc |
diff --git a/content/renderer/browser_render_view_browsertest.cc b/content/renderer/browser_render_view_browsertest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..57bb7a8a06c12c7460e68f856ccde623cd39a73f |
--- /dev/null |
+++ b/content/renderer/browser_render_view_browsertest.cc |
@@ -0,0 +1,254 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+// Browser tests targeted at the RenderView that run in browser context. |
+// Note that these tests rely on single-process mode, and hence may be |
+// disabled in some configurations (check gyp files). |
+ |
+#include "base/basictypes.h" |
+#include "base/bind.h" |
+#include "base/callback.h" |
+#include "base/command_line.h" |
+#include "base/strings/utf_string_conversions.h" |
+#include "content/public/browser/browser_context.h" |
+#include "content/public/browser/browser_thread.h" |
+#include "content/public/browser/render_frame_host.h" |
+#include "content/public/browser/render_process_host.h" |
+#include "content/public/browser/web_contents.h" |
+#include "content/public/common/content_switches.h" |
+#include "content/public/renderer/render_view.h" |
+#include "content/public/test/browser_test_utils.h" |
+#include "content/public/test/test_utils.h" |
+#include "content/shell/browser/shell.h" |
+#include "content/shell/browser/shell_browser_context.h" |
+#include "content/shell/browser/shell_content_browser_client.h" |
+#include "content/shell/common/shell_content_client.h" |
+#include "content/shell/renderer/shell_content_renderer_client.h" |
+#include "content/test/content_browser_test.h" |
+#include "content/test/content_browser_test_utils.h" |
+#include "net/base/net_errors.h" |
+#include "net/disk_cache/disk_cache.h" |
+#include "net/http/failing_http_transaction_factory.h" |
+#include "net/http/http_cache.h" |
+#include "net/url_request/url_request_context.h" |
+#include "net/url_request/url_request_context_getter.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+#include "third_party/WebKit/public/platform/WebURLError.h" |
+#include "third_party/WebKit/public/platform/WebURLRequest.h" |
+#include "third_party/WebKit/public/web/WebFrame.h" |
+ |
+namespace content { |
+ |
+namespace { |
+ |
+class TestShellContentRendererClient : public ShellContentRendererClient { |
+ public: |
+ TestShellContentRendererClient() |
+ : latest_error_valid_(false), |
+ latest_error_reason_(0), |
+ latest_error_stale_copy_in_cache_(false) {} |
+ |
+ virtual void GetNavigationErrorStrings( |
+ content::RenderView* render_view, |
+ blink::WebFrame* frame, |
+ const blink::WebURLRequest& failed_request, |
+ const blink::WebURLError& error, |
+ std::string* error_html, |
+ base::string16* error_description) OVERRIDE { |
+ if (error_html) |
+ *error_html = "A suffusion of yellow."; |
+ latest_error_valid_ = true; |
+ latest_error_reason_ = error.reason; |
+ latest_error_stale_copy_in_cache_ = error.staleCopyInCache; |
+ } |
+ |
+ bool GetLatestError(int* error_code, bool* stale_cache_entry_present) { |
+ if (latest_error_valid_) { |
+ *error_code = latest_error_reason_; |
+ *stale_cache_entry_present = latest_error_stale_copy_in_cache_; |
+ } |
+ return latest_error_valid_; |
+ } |
+ |
+ private: |
+ bool latest_error_valid_; |
+ int latest_error_reason_; |
+ bool latest_error_stale_copy_in_cache_; |
+}; |
+ |
+// Must be called on IO thread. |
+void InterceptNetworkTransactions(net::URLRequestContextGetter* getter, |
+ net::Error error) { |
+ DCHECK(content::BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ net::HttpCache* cache( |
+ getter->GetURLRequestContext()->http_transaction_factory()->GetCache()); |
+ DCHECK(cache); |
+ scoped_ptr<net::FailingHttpTransactionFactory> factory( |
+ new net::FailingHttpTransactionFactory(cache->GetSession(), error)); |
+ // Throw away old version; since this is a browser test, there is no |
+ // need to restore the old state. |
+ cache->SetHttpNetworkTransactionFactoryForTesting( |
+ factory.PassAs<net::HttpTransactionFactory>()); |
+} |
+ |
+void CallOnUIThreadValidatingReturn(const base::Closure& callback, |
+ int rv) { |
+ DCHECK_EQ(net::OK, rv); |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, FROM_HERE, callback); |
+} |
+ |
+// Must be called on IO thread. The callback will be called on |
+// completion of cache clearing on the UI thread. |
+void BackendClearCache(scoped_ptr<disk_cache::Backend*> backend, |
+ const base::Closure& callback, |
+ int rv) { |
+ DCHECK(*backend); |
+ DCHECK_EQ(net::OK, rv); |
+ (*backend)->DoomAllEntries( |
+ base::Bind(&CallOnUIThreadValidatingReturn, callback)); |
+} |
+ |
+// Must be called on IO thread. The callback will be called on |
+// completion of cache clearing on the UI thread. |
+void ClearCache(net::URLRequestContextGetter* getter, |
+ const base::Closure& callback) { |
+ DCHECK(content::BrowserThread::CurrentlyOn(BrowserThread::IO)); |
+ net::HttpCache* cache( |
+ getter->GetURLRequestContext()->http_transaction_factory()->GetCache()); |
+ DCHECK(cache); |
+ scoped_ptr<disk_cache::Backend*> backend(new disk_cache::Backend*); |
+ *backend = NULL; |
+ disk_cache::Backend** backend_ptr = backend.get(); |
+ |
+ net::CompletionCallback backend_callback( |
+ base::Bind(&BackendClearCache, base::Passed(backend.Pass()), callback)); |
+ |
+ // backend_ptr is valid until all copies of backend_callback go out |
+ // of scope. |
+ if (net::OK == cache->GetBackend(backend_ptr, backend_callback)) { |
+ // The call completed synchronously, so GetBackend didn't run the callback. |
+ backend_callback.Run(net::OK); |
+ } |
+} |
+ |
+} // namespace |
+ |
+class RenderViewBrowserTest : public ContentBrowserTest { |
+ public: |
+ RenderViewBrowserTest() : renderer_client_(NULL) {} |
+ |
+ virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { |
+ // This method is needed to allow interaction with in-process renderer |
+ // and use of a test ContentRendererClient. |
+ command_line->AppendSwitch(switches::kSingleProcess); |
+ } |
+ |
+ virtual void SetUp() OVERRIDE { |
+ // Override setting of renderer client. |
+ renderer_client_ = new TestShellContentRendererClient(); |
+ SetContentRendererClient( |
+ scoped_ptr<ContentRendererClient>(renderer_client_).Pass()); |
+ |
+ ContentBrowserTest::SetUp(); |
+ } |
+ |
+ // Navigates to the given URL and waits for |num_navigations| to occur, and |
+ // the title to change to |expected_title|. |
+ void NavigateToURLAndWaitForTitle(const GURL& url, |
+ const std::string& expected_title, |
+ int num_navigations) { |
+ content::TitleWatcher title_watcher( |
+ shell()->web_contents(), base::ASCIIToUTF16(expected_title)); |
+ |
+ content::NavigateToURLBlockUntilNavigationsComplete( |
+ shell(), url, num_navigations); |
+ |
+ EXPECT_EQ(base::ASCIIToUTF16(expected_title), |
+ title_watcher.WaitAndGetTitle()); |
+ } |
+ |
+ // Returns true if there is a valid error stored; in this case |
+ // |*error_code| and |*stale_cache_entry_present| will be updated |
+ // appropriately. |
+ // Must be called after the renderer thread is created. |
+ bool GetLatestErrorFromRendererClient( |
+ int* error_code, bool* stale_cache_entry_present) { |
+ bool result = false; |
+ |
+ PostTaskToInProcessRendererAndWait( |
+ base::Bind(&RenderViewBrowserTest::GetLatestErrorFromRendererClient0, |
+ renderer_client_, &result, error_code, |
+ stale_cache_entry_present)); |
+ return result; |
+ } |
+ |
+ private: |
+ // Must be run on renderer thread. |
+ static void GetLatestErrorFromRendererClient0( |
+ TestShellContentRendererClient* renderer_client, |
+ bool* result, int* error_code, bool* stale_cache_entry_present) { |
+ *result = renderer_client->GetLatestError( |
+ error_code, stale_cache_entry_present); |
+ } |
+ |
+ // Actually owned by the superclass, so safe to keep a bare pointer. |
+ TestShellContentRendererClient* renderer_client_; |
+}; |
+ |
+#if defined(OS_ANDROID) |
+// Flaky https://crbug.com/341745 |
+#define MAYBE_ConfirmCacheInformationPlumbed DISABLED_ConfirmCacheInformationPlumbed |
+#else |
+#define MAYBE_ConfirmCacheInformationPlumbed ConfirmCacheInformationPlumbed |
+#endif |
+ |
+IN_PROC_BROWSER_TEST_F(RenderViewBrowserTest, |
+ MAYBE_ConfirmCacheInformationPlumbed) { |
+ ASSERT_TRUE(test_server()->Start()); |
+ |
+ // Load URL with "nocache" set, to create stale cache. |
+ GURL test_url(test_server()->GetURL("files/nocache.html")); |
+ NavigateToURLAndWaitForTitle(test_url, "Nocache Test Page", 1); |
+ |
+ // Reload same URL after forcing an error from the the network layer; |
+ // confirm that the error page is told the cached copy exists. |
+ int renderer_id = |
+ shell()->web_contents()->GetMainFrame()->GetProcess()->GetID(); |
+ scoped_refptr<net::URLRequestContextGetter> url_request_context_getter = |
+ ShellContentBrowserClient::Get()->browser_context()-> |
+ GetRequestContextForRenderProcess(renderer_id); |
+ BrowserThread::PostTask( |
+ BrowserThread::IO, FROM_HERE, |
+ base::Bind(&InterceptNetworkTransactions, url_request_context_getter, |
+ net::ERR_FAILED)); |
+ |
+ // An error results in one completed navigation. |
+ NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1); |
+ int error_code = net::OK; |
+ bool stale_cache_entry_present = false; |
+ ASSERT_TRUE(GetLatestErrorFromRendererClient( |
+ &error_code, &stale_cache_entry_present)); |
+ EXPECT_EQ(net::ERR_FAILED, error_code); |
+ EXPECT_TRUE(stale_cache_entry_present); |
+ |
+ // Clear the cache and repeat; confirm lack of entry in cache reported. |
+ scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner; |
+ BrowserThread::PostTask( |
+ BrowserThread::IO, FROM_HERE, |
+ base::Bind(&ClearCache, url_request_context_getter, |
+ runner->QuitClosure())); |
+ runner->Run(); |
+ |
+ content::NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1); |
+ |
+ error_code = net::OK; |
+ stale_cache_entry_present = true; |
+ ASSERT_TRUE(GetLatestErrorFromRendererClient( |
+ &error_code, &stale_cache_entry_present)); |
+ EXPECT_EQ(net::ERR_FAILED, error_code); |
+ EXPECT_FALSE(stale_cache_entry_present); |
+} |
+ |
+} // namespace content |