| Index: chrome/browser/errorpage_browsertest.cc
|
| diff --git a/chrome/browser/errorpage_browsertest.cc b/chrome/browser/errorpage_browsertest.cc
|
| index 9a60d1cb37fc87f61839ca9abbea7b98803cbbb5..4613e197e4aae530dd98a9dded7da3d093c83a42 100644
|
| --- a/chrome/browser/errorpage_browsertest.cc
|
| +++ b/chrome/browser/errorpage_browsertest.cc
|
| @@ -3,7 +3,10 @@
|
| // found in the LICENSE file.
|
|
|
| #include "base/bind.h"
|
| +#include "base/command_line.h"
|
| #include "base/compiler_specific.h"
|
| +#include "base/logging.h"
|
| +#include "base/memory/scoped_ptr.h"
|
| #include "base/path_service.h"
|
| #include "base/prefs/pref_service.h"
|
| #include "base/strings/stringprintf.h"
|
| @@ -17,9 +20,11 @@
|
| #include "chrome/browser/ui/browser_commands.h"
|
| #include "chrome/browser/ui/tabs/tab_strip_model.h"
|
| #include "chrome/common/chrome_paths.h"
|
| +#include "chrome/common/chrome_switches.h"
|
| #include "chrome/common/pref_names.h"
|
| #include "chrome/test/base/in_process_browser_test.h"
|
| #include "chrome/test/base/ui_test_utils.h"
|
| +#include "content/public/browser/browser_thread.h"
|
| #include "content/public/browser/notification_service.h"
|
| #include "content/public/browser/render_frame_host.h"
|
| #include "content/public/browser/render_view_host.h"
|
| @@ -37,11 +42,16 @@
|
| #include "net/url_request/url_request_context.h"
|
| #include "net/url_request/url_request_context_getter.h"
|
| #include "net/url_request/url_request_filter.h"
|
| +#include "net/url_request/url_request_job.h"
|
| #include "net/url_request/url_request_job_factory.h"
|
| +#include "net/url_request/url_request_test_job.h"
|
| +#include "net/url_request/url_request_test_util.h"
|
|
|
| using content::BrowserThread;
|
| using content::NavigationController;
|
| using content::URLRequestFailedJob;
|
| +using net::URLRequestJobFactory;
|
| +using net::URLRequestTestJob;
|
|
|
| namespace {
|
|
|
| @@ -126,6 +136,62 @@ void ExpectDisplayingNavigationCorrections(Browser* browser,
|
| EXPECT_TRUE(search_box_populated);
|
| }
|
|
|
| +// A protocol handler that fails a configurable number of requests, then
|
| +// succeeds all requests after that, keeping count of failures and successes.
|
| +class FailFirstNRequestsProtocolHandler
|
| + : public URLRequestJobFactory::ProtocolHandler {
|
| + public:
|
| + FailFirstNRequestsProtocolHandler(const GURL& url, int requests_to_fail)
|
| + : url_(url), requests_(0), failures_(0),
|
| + requests_to_fail_(requests_to_fail) {}
|
| + virtual ~FailFirstNRequestsProtocolHandler() {}
|
| +
|
| + // This method deliberately violates pointer ownership rules:
|
| + // AddUrlProtocolHandler() takes a scoped_ptr, taking ownership of the
|
| + // supplied ProtocolHandler (i.e., |this|), but also having the caller retain
|
| + // a pointer to |this| so the caller can use the requests() and failures()
|
| + // accessors.
|
| + void AddUrlHandler() {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + scoped_ptr<URLRequestJobFactory::ProtocolHandler> scoped_handler(this);
|
| + net::URLRequestFilter::GetInstance()->AddUrlProtocolHandler(
|
| + url_,
|
| + scoped_handler.Pass());
|
| + }
|
| +
|
| + // net::URLRequestJobFactory::ProtocolHandler implementation
|
| + virtual net::URLRequestJob* MaybeCreateJob(
|
| + net::URLRequest* request,
|
| + net::NetworkDelegate* network_delegate) const OVERRIDE {
|
| + DCHECK_EQ(url_, request->url());
|
| + requests_++;
|
| + if (failures_ < requests_to_fail_) {
|
| + failures_++;
|
| + // Note: net::ERR_CONNECTION_RESET does not summon the Link Doctor; see
|
| + // NetErrorHelperCore::GetErrorPageURL.
|
| + return new URLRequestFailedJob(request,
|
| + network_delegate,
|
| + net::ERR_CONNECTION_RESET);
|
| + } else {
|
| + return new URLRequestTestJob(request, network_delegate,
|
| + URLRequestTestJob::test_headers(),
|
| + URLRequestTestJob::test_data_1(),
|
| + true);
|
| + }
|
| + }
|
| +
|
| + int requests() const { return requests_; }
|
| + int failures() const { return failures_; }
|
| +
|
| + private:
|
| + const GURL url_;
|
| + // These are mutable because MaybeCreateJob is const but we want this state
|
| + // for testing.
|
| + mutable int requests_;
|
| + mutable int failures_;
|
| + int requests_to_fail_;
|
| +};
|
| +
|
| class ErrorPageTest : public InProcessBrowserTest {
|
| public:
|
| enum HistoryNavigationDirection {
|
| @@ -607,6 +673,69 @@ IN_PROC_BROWSER_TEST_F(ErrorPageTest, StaleCacheStatus) {
|
| EXPECT_TRUE(ProbeStaleCopyValue(false));
|
| }
|
|
|
| +class ErrorPageAutoReloadTest : public InProcessBrowserTest {
|
| + public:
|
| + virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
|
| + command_line->AppendSwitch(switches::kEnableOfflineAutoReload);
|
| + }
|
| +
|
| + void InstallProtocolHandler(const GURL& url, int requests_to_fail) {
|
| + protocol_handler_ = new FailFirstNRequestsProtocolHandler(
|
| + url,
|
| + requests_to_fail);
|
| + // Tests don't need to wait for this task to complete before using the
|
| + // filter; any requests that might be affected by it will end up in the IO
|
| + // thread's message loop after this posted task anyway.
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO, FROM_HERE,
|
| + base::Bind(&ErrorPageAutoReloadTest::AddFilters,
|
| + base::Unretained(this)));
|
| + }
|
| +
|
| + void NavigateToURLAndWaitForTitle(const GURL& url,
|
| + const std::string& expected_title,
|
| + int num_navigations) {
|
| + content::TitleWatcher title_watcher(
|
| + browser()->tab_strip_model()->GetActiveWebContents(),
|
| + base::ASCIIToUTF16(expected_title));
|
| +
|
| + ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
|
| + browser(), url, num_navigations);
|
| +
|
| + EXPECT_EQ(base::ASCIIToUTF16(expected_title),
|
| + title_watcher.WaitAndGetTitle());
|
| + }
|
| +
|
| + FailFirstNRequestsProtocolHandler* protocol_handler() {
|
| + return protocol_handler_;
|
| + }
|
| +
|
| + private:
|
| + void AddFilters() {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + // Note: in theory, AddUrlHandler gives ownership of |protocol_handler_| to
|
| + // URLRequestFilter. As soon as anything calls
|
| + // URLRequestFilter::ClearHandlers(), |protocol_handler_| can become
|
| + // invalid.
|
| + protocol_handler_->AddUrlHandler();
|
| + }
|
| +
|
| + FailFirstNRequestsProtocolHandler* protocol_handler_;
|
| +};
|
| +
|
| +IN_PROC_BROWSER_TEST_F(ErrorPageAutoReloadTest, AutoReload) {
|
| + GURL test_url("http://error.page.auto.reload");
|
| + const int kRequestsToFail = 2;
|
| + InstallProtocolHandler(test_url, kRequestsToFail);
|
| + NavigateToURLAndWaitForTitle(test_url, "Test One", kRequestsToFail + 1);
|
| + // Note that the protocol handler updates these variables on the IO thread,
|
| + // but this function reads them on the main thread. The requests have to be
|
| + // created (on the IO thread) before NavigateToURLAndWaitForTitle returns or
|
| + // this becomes racey.
|
| + EXPECT_EQ(kRequestsToFail, protocol_handler()->failures());
|
| + EXPECT_EQ(kRequestsToFail + 1, protocol_handler()->requests());
|
| +}
|
| +
|
| // Protocol handler that fails all requests with net::ERR_ADDRESS_UNREACHABLE.
|
| class AddressUnreachableProtocolHandler
|
| : public net::URLRequestJobFactory::ProtocolHandler {
|
|
|