summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorrdsmith@chromium.org <rdsmith@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-06 23:08:37 +0000
committerrdsmith@chromium.org <rdsmith@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-06 23:08:37 +0000
commitdcbe3df77892fded9f0afa3fe01112f242b6fff7 (patch)
treecc4a01616ff566c53df7b4d1c1b821850abcfcdf /content
parent097782be0628a771d04d49dbb06360b6232cb340 (diff)
downloadchromium_src-dcbe3df77892fded9f0afa3fe01112f242b6fff7.zip
chromium_src-dcbe3df77892fded9f0afa3fe01112f242b6fff7.tar.gz
chromium_src-dcbe3df77892fded9f0afa3fe01112f242b6fff7.tar.bz2
Plumb network stack information about existence of cached copy
through to error page. Specifically, add a "stale_copy_in_cache" argument to all of (ordered from Browser->Renderer): * ResourceMsg_RequestComplete IPC message. * ResourceDispatcher::OnRequestComplete * ResourceLoaderBridge::Peer::OnCompletedRequest. * All subclasses of RLB::P::OnCompleted Request, including WebURLLoaderImpl::context::OnCompletedRequest. * Blink WebURLError and ResourceError classes (https://codereview.chromium.org/138493002). * LocalizedError::GetStrings. This is a paired commit with the blink CL https://codereview.chromium.org/138493002. That CL must be landed before this one. BUG=329620 Review URL: https://codereview.chromium.org/138513002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@249527 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r--content/browser/loader/async_resource_handler.cc14
-rw-r--r--content/browser/loader/resource_dispatcher_host_impl.cc13
-rw-r--r--content/child/npapi/plugin_url_fetcher.cc1
-rw-r--r--content/child/npapi/plugin_url_fetcher.h1
-rw-r--r--content/child/resource_dispatcher.cc15
-rw-r--r--content/child/resource_dispatcher.h7
-rw-r--r--content/child/resource_dispatcher_unittest.cc3
-rw-r--r--content/common/resource_messages.h25
-rw-r--r--content/renderer/render_view_browsertest.cc225
-rw-r--r--content/test/content_browser_test.cc23
-rw-r--r--content/test/content_browser_test.h4
-rw-r--r--content/test/data/nocache.html4
-rw-r--r--content/test/data/nocache.html.mock-http-headers2
13 files changed, 302 insertions, 35 deletions
diff --git a/content/browser/loader/async_resource_handler.cc b/content/browser/loader/async_resource_handler.cc
index 52c1d8f..2a35c4d 100644
--- a/content/browser/loader/async_resource_handler.cc
+++ b/content/browser/loader/async_resource_handler.cc
@@ -335,8 +335,6 @@ void AsyncResourceHandler::OnResponseCompleted(
CHECK(status.status() != net::URLRequestStatus::SUCCESS ||
sent_received_response_msg_);
- TimeTicks completion_time = TimeTicks::Now();
-
int error_code = status.error();
bool was_ignored_by_handler = info->WasIgnoredByHandler();
@@ -356,12 +354,14 @@ void AsyncResourceHandler::OnResponseCompleted(
error_code = net::ERR_FAILED;
}
+ ResourceMsg_RequestCompleteData request_complete_data;
+ request_complete_data.error_code = error_code;
+ request_complete_data.was_ignored_by_handler = was_ignored_by_handler;
+ request_complete_data.exists_in_cache = request()->response_info().was_cached;
+ request_complete_data.security_info = security_info;
+ request_complete_data.completion_time = TimeTicks::Now();
info->filter()->Send(
- new ResourceMsg_RequestComplete(request_id,
- error_code,
- was_ignored_by_handler,
- security_info,
- completion_time));
+ new ResourceMsg_RequestComplete(request_id, request_complete_data));
}
bool AsyncResourceHandler::EnsureResourceBufferIsInitialized() {
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc
index b8bfaef..173202e 100644
--- a/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -158,12 +158,15 @@ void AbortRequestBeforeItStarts(ResourceMessageFilter* filter,
filter->Send(sync_result);
} else {
// Tell the renderer that this request was disallowed.
+ ResourceMsg_RequestCompleteData request_complete_data;
+ request_complete_data.error_code = net::ERR_ABORTED;
+ request_complete_data.was_ignored_by_handler = false;
+ request_complete_data.exists_in_cache = false;
+ // No security info needed, connection not established.
+ request_complete_data.completion_time = base::TimeTicks();
+
filter->Send(new ResourceMsg_RequestComplete(
- request_id,
- net::ERR_ABORTED,
- false,
- std::string(), // No security info needed, connection not established.
- base::TimeTicks()));
+ request_id, request_complete_data));
}
}
diff --git a/content/child/npapi/plugin_url_fetcher.cc b/content/child/npapi/plugin_url_fetcher.cc
index efc5b13..fa85dd6 100644
--- a/content/child/npapi/plugin_url_fetcher.cc
+++ b/content/child/npapi/plugin_url_fetcher.cc
@@ -341,6 +341,7 @@ void PluginURLFetcher::OnReceivedData(const char* data,
void PluginURLFetcher::OnCompletedRequest(
int error_code,
bool was_ignored_by_handler,
+ bool stale_copy_in_cache,
const std::string& security_info,
const base::TimeTicks& completion_time) {
if (multipart_delegate_) {
diff --git a/content/child/npapi/plugin_url_fetcher.h b/content/child/npapi/plugin_url_fetcher.h
index 2a0a10d..cf58813 100644
--- a/content/child/npapi/plugin_url_fetcher.h
+++ b/content/child/npapi/plugin_url_fetcher.h
@@ -62,6 +62,7 @@ class PluginURLFetcher : public webkit_glue::ResourceLoaderBridge::Peer {
virtual void OnCompletedRequest(
int error_code,
bool was_ignored_by_handler,
+ bool stale_copy_in_cache,
const std::string& security_info,
const base::TimeTicks& completion_time) OVERRIDE;
diff --git a/content/child/resource_dispatcher.cc b/content/child/resource_dispatcher.cc
index 6e4f438..d6affbb 100644
--- a/content/child/resource_dispatcher.cc
+++ b/content/child/resource_dispatcher.cc
@@ -521,10 +521,7 @@ void ResourceDispatcher::FollowPendingRedirect(
void ResourceDispatcher::OnRequestComplete(
int request_id,
- int error_code,
- bool was_ignored_by_handler,
- const std::string& security_info,
- const base::TimeTicks& browser_completion_time) {
+ const ResourceMsg_RequestCompleteData& request_complete_data) {
TRACE_EVENT0("loader", "ResourceDispatcher::OnRequestComplete");
SiteIsolationPolicy::OnRequestComplete(request_id);
@@ -540,17 +537,21 @@ void ResourceDispatcher::OnRequestComplete(
if (delegate_) {
ResourceLoaderBridge::Peer* new_peer =
delegate_->OnRequestComplete(
- request_info->peer, request_info->resource_type, error_code);
+ request_info->peer, request_info->resource_type,
+ request_complete_data.error_code);
if (new_peer)
request_info->peer = new_peer;
}
base::TimeTicks renderer_completion_time = ToRendererCompletionTime(
- *request_info, browser_completion_time);
+ *request_info, request_complete_data.completion_time);
// The request ID will be removed from our pending list in the destructor.
// Normally, dispatching this message causes the reference-counted request to
// die immediately.
- peer->OnCompletedRequest(error_code, was_ignored_by_handler, security_info,
+ peer->OnCompletedRequest(request_complete_data.error_code,
+ request_complete_data.was_ignored_by_handler,
+ request_complete_data.exists_in_cache,
+ request_complete_data.security_info,
renderer_completion_time);
}
diff --git a/content/child/resource_dispatcher.h b/content/child/resource_dispatcher.h
index d85087d..4943765 100644
--- a/content/child/resource_dispatcher.h
+++ b/content/child/resource_dispatcher.h
@@ -20,6 +20,8 @@
#include "ipc/ipc_sender.h"
#include "webkit/child/resource_loader_bridge.h"
+struct ResourceMsg_RequestCompleteData;
+
namespace content {
class ResourceDispatcherDelegate;
struct ResourceResponseHead;
@@ -150,10 +152,7 @@ class CONTENT_EXPORT ResourceDispatcher : public IPC::Listener {
int encoded_data_length);
void OnRequestComplete(
int request_id,
- int error_code,
- bool was_ignored_by_handler,
- const std::string& security_info,
- const base::TimeTicks& completion_time);
+ const ResourceMsg_RequestCompleteData &request_complete_data);
// Dispatch the message to one of the message response handlers.
void DispatchMessage(const IPC::Message& message);
diff --git a/content/child/resource_dispatcher_unittest.cc b/content/child/resource_dispatcher_unittest.cc
index 46869d5..7ff9ac3 100644
--- a/content/child/resource_dispatcher_unittest.cc
+++ b/content/child/resource_dispatcher_unittest.cc
@@ -70,6 +70,7 @@ class TestRequestCallback : public ResourceLoaderBridge::Peer {
virtual void OnCompletedRequest(
int error_code,
bool was_ignored_by_handler,
+ bool stale_copy_in_cache,
const std::string& security_info,
const base::TimeTicks& completion_time) OVERRIDE {
EXPECT_FALSE(complete_);
@@ -295,6 +296,7 @@ class DeferredResourceLoadingTest : public ResourceDispatcherTest,
virtual void OnCompletedRequest(
int error_code,
bool was_ignored_by_handler,
+ bool stale_copy_in_cache,
const std::string& security_info,
const base::TimeTicks& completion_time) OVERRIDE {
}
@@ -382,6 +384,7 @@ class TimeConversionTest : public ResourceDispatcherTest,
virtual void OnCompletedRequest(
int error_code,
bool was_ignored_by_handler,
+ bool stale_copy_in_cache,
const std::string& security_info,
const base::TimeTicks& completion_time) OVERRIDE {
}
diff --git a/content/common/resource_messages.h b/content/common/resource_messages.h
index 8b346dd..100f75c 100644
--- a/content/common/resource_messages.h
+++ b/content/common/resource_messages.h
@@ -213,6 +213,24 @@ IPC_STRUCT_BEGIN(ResourceHostMsg_Request)
IPC_STRUCT_MEMBER(bool, allow_download)
IPC_STRUCT_END()
+// Parameters for a ResourceMsg_RequestComplete
+IPC_STRUCT_BEGIN(ResourceMsg_RequestCompleteData)
+ // The error code.
+ IPC_STRUCT_MEMBER(int, error_code)
+
+ // Was ignored by the request handler.
+ IPC_STRUCT_MEMBER(bool, was_ignored_by_handler)
+
+ // A copy of the data requested exists in the cache.
+ IPC_STRUCT_MEMBER(bool, exists_in_cache)
+
+ // Serialized security info; see content/common/ssl_status_serialization.h.
+ IPC_STRUCT_MEMBER(std::string, security_info)
+
+ // Time the request completed.
+ IPC_STRUCT_MEMBER(base::TimeTicks, completion_time)
+IPC_STRUCT_END()
+
// Resource messages sent from the browser to the renderer.
// Sent when the headers are available for a resource request.
@@ -274,12 +292,9 @@ IPC_MESSAGE_CONTROL3(ResourceMsg_DataDownloaded,
int /* encoded_data_length */)
// Sent when the request has been completed.
-IPC_MESSAGE_CONTROL5(ResourceMsg_RequestComplete,
+IPC_MESSAGE_CONTROL2(ResourceMsg_RequestComplete,
int /* request_id */,
- int /* error_code */,
- bool /* was_ignored_by_handler */,
- std::string /* security info */,
- base::TimeTicks /* completion_time */)
+ ResourceMsg_RequestCompleteData)
// Resource messages sent from the renderer to the browser.
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index 3a38ff2..a562d37 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -4,6 +4,8 @@
#include "base/basictypes.h"
+#include "base/bind.h"
+#include "base/callback.h"
#include "base/memory/shared_memory.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -11,22 +13,40 @@
#include "content/common/frame_messages.h"
#include "content/common/ssl_status_serialization.h"
#include "content/common/view_messages.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/browser/native_web_keyboard_event.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/browser/web_ui_controller_factory.h"
#include "content/public/common/bindings_policy.h"
+#include "content/public/common/content_switches.h"
#include "content/public/common/page_zoom.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
#include "content/public/renderer/document_state.h"
#include "content/public/renderer/history_item_serialization.h"
#include "content/public/renderer/navigation_state.h"
+#include "content/public/test/browser_test_utils.h"
#include "content/public/test/render_view_test.h"
+#include "content/public/test/test_utils.h"
#include "content/renderer/render_view_impl.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 "content/test/mock_keyboard.h"
#include "net/base/net_errors.h"
#include "net/cert/cert_status_flags.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/WebData.h"
#include "third_party/WebKit/public/platform/WebHTTPBody.h"
@@ -118,8 +138,6 @@ class WebUITestWebUIControllerFactory : public WebUIControllerFactory {
}
};
-} // namespace
-
class RenderViewImplTest : public RenderViewTest {
public:
RenderViewImplTest() {
@@ -305,6 +323,99 @@ class RenderViewImplTest : public RenderViewTest {
scoped_ptr<MockKeyboard> mock_keyboard_;
};
+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
+
// Test that we get form state change notifications when input fields change.
TEST_F(RenderViewImplTest, DISABLED_OnNavStateChanged) {
// Don't want any delay for form state sync changes. This will still post a
@@ -2243,4 +2354,114 @@ TEST_F(RenderViewImplTest, FocusElementCallsFocusedNodeChanged) {
render_thread_->sink().ClearMessages();
}
+// For actual, browser side tests targetting code in RenderView
+// or RenderViewImpl.
+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_;
+};
+
+IN_PROC_BROWSER_TEST_F(RenderViewBrowserTest, 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.
+ content::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
diff --git a/content/test/content_browser_test.cc b/content/test/content_browser_test.cc
index a164450..3881613 100644
--- a/content/test/content_browser_test.cc
+++ b/content/test/content_browser_test.cc
@@ -55,8 +55,6 @@ ContentBrowserTest::~ContentBrowserTest() {
}
void ContentBrowserTest::SetUp() {
- setup_called_ = true;
-
shell_main_delegate_.reset(new ShellMainDelegate);
shell_main_delegate_->PreSandboxStartup();
@@ -65,11 +63,16 @@ void ContentBrowserTest::SetUp() {
SetUpCommandLine(command_line);
- // Single-process mode is not set in BrowserMain, so process it explicitly,
- // and set up renderer.
+ // Single-process mode is not set in BrowserMain, so if a subclass hasn't
+ // modified it yet, process it explicitly, and set up renderer.
if (command_line->HasSwitch(switches::kSingleProcess)) {
- single_process_renderer_client_.reset(new ShellContentRendererClient);
+ if (!single_process_renderer_client_)
+ single_process_renderer_client_.reset(new ShellContentRendererClient());
SetRendererClientForTesting(single_process_renderer_client_.get());
+ } else {
+ // Confirm no test has called SetContentRendererClient() without
+ // setting up single process mode.
+ DCHECK(!single_process_renderer_client_);
}
#if defined(OS_MACOSX)
@@ -89,6 +92,8 @@ void ContentBrowserTest::SetUp() {
ui::InitializeInputMethodForTesting();
#endif
+ setup_called_ = true;
+
BrowserTestBase::SetUp();
}
@@ -144,6 +149,14 @@ void ContentBrowserTest::RunTestOnMainThreadLoop() {
Shell::CloseAllWindows();
}
+void ContentBrowserTest::SetContentRendererClient(
+ scoped_ptr<ContentRendererClient> renderer_client) {
+ // This routine must be called before SetUp().
+ DCHECK(!setup_called_);
+ DCHECK(!single_process_renderer_client_);
+ single_process_renderer_client_ = renderer_client.Pass();
+}
+
Shell* ContentBrowserTest::CreateBrowser() {
return Shell::CreateNewWindow(
ShellContentBrowserClient::Get()->browser_context(),
diff --git a/content/test/content_browser_test.h b/content/test/content_browser_test.h
index 5a76bb6..0647d4a 100644
--- a/content/test/content_browser_test.h
+++ b/content/test/content_browser_test.h
@@ -28,6 +28,10 @@ class ContentBrowserTest : public BrowserTestBase {
// BrowserTestBase:
virtual void RunTestOnMainThreadLoop() OVERRIDE;
+ // Must be called before or during setup.
+ void SetContentRendererClient(
+ scoped_ptr<ContentRendererClient> renderer_client);
+
protected:
// Creates a new window and loads about:blank.
Shell* CreateBrowser();
diff --git a/content/test/data/nocache.html b/content/test/data/nocache.html
new file mode 100644
index 0000000..9ef8195
--- /dev/null
+++ b/content/test/data/nocache.html
@@ -0,0 +1,4 @@
+<html>
+<head><title>Nocache Test Page</title></head>
+<body>Nocache test body</body>
+</html>
diff --git a/content/test/data/nocache.html.mock-http-headers b/content/test/data/nocache.html.mock-http-headers
new file mode 100644
index 0000000..a52ff3d
--- /dev/null
+++ b/content/test/data/nocache.html.mock-http-headers
@@ -0,0 +1,2 @@
+HTTP/1.1 200 OK
+Cache-Control: nocache