Commit 6f2b1673 authored by mathp's avatar mathp Committed by Commit bot

[New Tab Page] Change the mechanism to intercept online NTP errors

No longer rely on DidFailProvisionalLoad, solving other issues.

Includes a rename of URLRequestMockHTTPJob::AddUrlHandler

BUG=373455
TEST=NewTabPageInterceptorTest

Review URL: https://codereview.chromium.org/845973005

Cr-Commit-Position: refs/heads/master@{#314004}
parent a55e33a2
...@@ -29,8 +29,8 @@ using content::BrowserThread; ...@@ -29,8 +29,8 @@ using content::BrowserThread;
namespace { namespace {
void SetUrlRequestMock(const base::FilePath& path) { void SetUrlRequestMock(const base::FilePath& path) {
net::URLRequestMockHTTPJob::AddUrlHandler(path, net::URLRequestMockHTTPJob::AddUrlHandlers(path,
BrowserThread::GetBlockingPool()); BrowserThread::GetBlockingPool());
} }
} }
......
...@@ -37,8 +37,8 @@ void SetUrlRequestMocksEnabled(bool enabled) { ...@@ -37,8 +37,8 @@ void SetUrlRequestMocksEnabled(bool enabled) {
base::FilePath root_http; base::FilePath root_http;
PathService::Get(chrome::DIR_TEST_DATA, &root_http); PathService::Get(chrome::DIR_TEST_DATA, &root_http);
net::URLRequestMockHTTPJob::AddUrlHandler(root_http, net::URLRequestMockHTTPJob::AddUrlHandlers(
BrowserThread::GetBlockingPool()); root_http, BrowserThread::GetBlockingPool());
} else { } else {
// Revert to the default handlers. // Revert to the default handlers.
net::URLRequestFilter::GetInstance()->ClearHandlers(); net::URLRequestFilter::GetInstance()->ClearHandlers();
......
...@@ -634,10 +634,8 @@ class PolicyTest : public InProcessBrowserTest { ...@@ -634,10 +634,8 @@ class PolicyTest : public InProcessBrowserTest {
base::FilePath root_http; base::FilePath root_http;
PathService::Get(content::DIR_TEST_DATA, &root_http); PathService::Get(content::DIR_TEST_DATA, &root_http);
BrowserThread::PostTaskAndReply( BrowserThread::PostTaskAndReply(
BrowserThread::IO, BrowserThread::IO, FROM_HERE,
FROM_HERE, base::Bind(URLRequestMockHTTPJob::AddUrlHandlers, root_http,
base::Bind(URLRequestMockHTTPJob::AddUrlHandler,
root_http,
make_scoped_refptr(BrowserThread::GetBlockingPool())), make_scoped_refptr(BrowserThread::GetBlockingPool())),
base::MessageLoop::current()->QuitWhenIdleClosure()); base::MessageLoop::current()->QuitWhenIdleClosure());
content::RunMessageLoop(); content::RunMessageLoop();
......
...@@ -585,6 +585,7 @@ void ProfileImplIOData::InitializeInternal( ...@@ -585,6 +585,7 @@ void ProfileImplIOData::InitializeInternal(
scoped_ptr<net::URLRequestJobFactoryImpl> main_job_factory( scoped_ptr<net::URLRequestJobFactoryImpl> main_job_factory(
new net::URLRequestJobFactoryImpl()); new net::URLRequestJobFactoryImpl());
InstallProtocolHandlers(main_job_factory.get(), protocol_handlers); InstallProtocolHandlers(main_job_factory.get(), protocol_handlers);
// The data reduction proxy interceptor should be as close to the network // The data reduction proxy interceptor should be as close to the network
// as possible. // as possible.
request_interceptors.insert( request_interceptors.insert(
......
...@@ -48,6 +48,8 @@ ...@@ -48,6 +48,8 @@
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/signin/signin_names_io_thread.h" #include "chrome/browser/signin/signin_names_io_thread.h"
#include "chrome/browser/ui/search/new_tab_page_interceptor_service.h"
#include "chrome/browser/ui/search/new_tab_page_interceptor_service_factory.h"
#include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h" #include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h" #include "chrome/common/pref_names.h"
...@@ -398,6 +400,13 @@ void ProfileIOData::InitializeOnUIThread(Profile* profile) { ...@@ -398,6 +400,13 @@ void ProfileIOData::InitializeOnUIThread(Profile* profile) {
params->protocol_handler_interceptor = params->protocol_handler_interceptor =
protocol_handler_registry->CreateJobInterceptorFactory(); protocol_handler_registry->CreateJobInterceptorFactory();
NewTabPageInterceptorService* new_tab_interceptor_service =
NewTabPageInterceptorServiceFactory::GetForProfile(profile);
if (new_tab_interceptor_service) {
params->new_tab_page_interceptor =
new_tab_interceptor_service->CreateInterceptor();
}
params->proxy_config_service params->proxy_config_service
.reset(ProxyServiceFactory::CreateProxyConfigService( .reset(ProxyServiceFactory::CreateProxyConfigService(
profile->GetProxyConfigTracker())); profile->GetProxyConfigTracker()));
...@@ -1129,6 +1138,12 @@ void ProfileIOData::Init( ...@@ -1129,6 +1138,12 @@ void ProfileIOData::Init(
tracked_objects::ScopedTracker tracking_profile5( tracked_objects::ScopedTracker tracking_profile5(
FROM_HERE_WITH_EXPLICIT_FUNCTION("436671 ProfileIOData::Init5")); FROM_HERE_WITH_EXPLICIT_FUNCTION("436671 ProfileIOData::Init5"));
// Install the New Tab Page Interceptor.
if (profile_params_->new_tab_page_interceptor.get()) {
request_interceptors.push_back(
profile_params_->new_tab_page_interceptor.release());
}
InitializeInternal( InitializeInternal(
network_delegate.Pass(), profile_params_.get(), network_delegate.Pass(), profile_params_.get(),
protocol_handlers, request_interceptors.Pass()); protocol_handlers, request_interceptors.Pass());
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "net/http/http_cache.h" #include "net/http/http_cache.h"
#include "net/http/http_network_session.h" #include "net/http/http_network_session.h"
#include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_interceptor.h"
#include "net/url_request/url_request_job_factory.h" #include "net/url_request/url_request_job_factory.h"
class ChromeHttpUserAgentSettings; class ChromeHttpUserAgentSettings;
...@@ -316,6 +317,10 @@ class ProfileIOData { ...@@ -316,6 +317,10 @@ class ProfileIOData {
scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory> scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
protocol_handler_interceptor; protocol_handler_interceptor;
// Holds the URLRequestInterceptor pointer that is created on the UI thread
// and then passed to the list of request_interceptors on the IO thread.
scoped_ptr<net::URLRequestInterceptor> new_tab_page_interceptor;
// We need to initialize the ProxyConfigService from the UI thread // We need to initialize the ProxyConfigService from the UI thread
// because on linux it relies on initializing things through gconf, // because on linux it relies on initializing things through gconf,
// and needs to be on the main thread. // and needs to be on the main thread.
......
...@@ -30,6 +30,13 @@ class PrefRegistrySyncable; ...@@ -30,6 +30,13 @@ class PrefRegistrySyncable;
namespace chrome { namespace chrome {
// For reporting Cacheable NTP navigations.
enum CacheableNTPLoad {
CACHEABLE_NTP_LOAD_FAILED = 0,
CACHEABLE_NTP_LOAD_SUCCEEDED = 1,
CACHEABLE_NTP_LOAD_MAX = 2
};
enum OptInState { enum OptInState {
// The user has not manually opted in/out of InstantExtended. // The user has not manually opted in/out of InstantExtended.
INSTANT_EXTENDED_NOT_SET, INSTANT_EXTENDED_NOT_SET,
......
// Copyright 2015 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.
#include "base/files/file_path.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/search/search.h"
#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/browser/search_engines/ui_thread_search_terms_data.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/search_engines/template_url_service.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/web_contents.h"
#include "net/test/url_request/url_request_mock_http_job.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
using content::BrowserThread;
namespace {
void SetUrlRequestMock(const base::FilePath& path) {
net::URLRequestMockHTTPJob::AddUrlHandlers(path,
BrowserThread::GetBlockingPool());
}
} // namespace
class NewTabPageInterceptorTest : public InProcessBrowserTest {
public:
NewTabPageInterceptorTest() {}
void SetUpOnMainThread() override {
path_ = ui_test_utils::GetTestFilePath(base::FilePath(), base::FilePath());
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
base::Bind(&SetUrlRequestMock, path_));
}
const GURL& new_tab_url() const { return new_tab_url_; }
void set_new_tab_url(const GURL& url) { new_tab_url_ = url; }
void ChangeDefaultSearchProvider(const char* new_tab_path) {
TemplateURLService* template_url_service =
TemplateURLServiceFactory::GetForProfile(browser()->profile());
ui_test_utils::WaitForTemplateURLServiceToLoad(template_url_service);
UIThreadSearchTermsData::SetGoogleBaseURL("https://mock.http/");
std::string base_url("{google:baseURL}");
TemplateURLData data;
data.SetKeyword(base::UTF8ToUTF16(base_url));
data.SetURL(base_url + "url?bar={searchTerms}");
data.new_tab_url = base_url + new_tab_path;
TemplateURL* template_url = new TemplateURL(data);
// Takes ownership of |template_url|.
template_url_service->Add(template_url);
template_url_service->SetUserSelectedDefaultSearchProvider(template_url);
}
static GURL GetMockURL(const base::FilePath::StringType& path) {
return net::URLRequestMockHTTPJob::GetMockHttpsUrl(base::FilePath(path));
}
private:
GURL new_tab_url_;
base::FilePath path_;
};
IN_PROC_BROWSER_TEST_F(NewTabPageInterceptorTest, NoInterception) {
set_new_tab_url(GetMockURL(FILE_PATH_LITERAL("instant_extended.html")));
ChangeDefaultSearchProvider("instant_extended.html");
ui_test_utils::NavigateToURL(browser(), new_tab_url());
content::WebContents* contents =
browser()->tab_strip_model()->GetWebContentsAt(0);
content::NavigationController* controller = &contents->GetController();
// A correct, 200-OK file works correctly.
EXPECT_EQ(new_tab_url(), controller->GetLastCommittedEntry()->GetURL());
}
IN_PROC_BROWSER_TEST_F(NewTabPageInterceptorTest, 404Interception) {
set_new_tab_url(GetMockURL(FILE_PATH_LITERAL("page404.html")));
ChangeDefaultSearchProvider("page404.html");
ui_test_utils::NavigateToURL(browser(), new_tab_url());
content::WebContents* contents =
browser()->tab_strip_model()->GetWebContentsAt(0);
content::NavigationController* controller = &contents->GetController();
// 404 makes a redirect to the local NTP.
EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl),
controller->GetLastCommittedEntry()->GetURL());
}
IN_PROC_BROWSER_TEST_F(NewTabPageInterceptorTest, 204Interception) {
set_new_tab_url(GetMockURL(FILE_PATH_LITERAL("page204.html")));
ChangeDefaultSearchProvider("page204.html");
ui_test_utils::NavigateToURL(browser(), new_tab_url());
content::WebContents* contents =
browser()->tab_strip_model()->GetWebContentsAt(0);
content::NavigationController* controller = &contents->GetController();
// 204 makes a redirect to the local NTP.
EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl),
controller->GetLastCommittedEntry()->GetURL());
}
IN_PROC_BROWSER_TEST_F(NewTabPageInterceptorTest, FailedRequestInterception) {
set_new_tab_url(GetMockURL(FILE_PATH_LITERAL("notarealfile.html")));
ChangeDefaultSearchProvider("notarealfile.html");
ui_test_utils::NavigateToURL(browser(), new_tab_url());
content::WebContents* contents =
browser()->tab_strip_model()->GetWebContentsAt(0);
content::NavigationController* controller = &contents->GetController();
// Failed navigation makes a redirect to the local NTP.
EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl),
controller->GetLastCommittedEntry()->GetURL());
}
// Copyright 2015 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.
#include "chrome/browser/ui/search/new_tab_page_interceptor_service.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search/search.h"
#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/common/url_constants.h"
#include "components/search_engines/template_url_service.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/net_errors.h"
#include "net/http/http_status_code.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_interceptor.h"
#include "net/url_request/url_request_job.h"
#include "net/url_request/url_request_redirect_job.h"
#include "url/gurl.h"
// Implementation of the URLRequestInterceptor for the New Tab Page. Will look
// at incoming response from the server and possibly divert to the local NTP.
class NewTabPageInterceptor : public net::URLRequestInterceptor {
public:
explicit NewTabPageInterceptor(const GURL& new_tab_url)
: new_tab_url_(new_tab_url), weak_factory_(this) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
}
~NewTabPageInterceptor() override {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
}
base::WeakPtr<NewTabPageInterceptor> GetWeakPtr() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
return weak_factory_.GetWeakPtr();
}
void SetNewTabPageURL(const GURL& new_tab_page_url) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
new_tab_url_ = new_tab_page_url;
}
private:
// Overrides from net::URLRequestInterceptor:
net::URLRequestJob* MaybeInterceptRequest(
net::URLRequest* request,
net::NetworkDelegate* network_delegate) const override {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
return nullptr;
}
net::URLRequestJob* MaybeInterceptResponse(
net::URLRequest* request,
net::NetworkDelegate* network_delegate) const override {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
if ((request->url() != new_tab_url_) ||
(new_tab_url_ == GURL(chrome::kChromeSearchLocalNtpUrl))) {
return nullptr;
}
// User has canceled this navigation so it shouldn't be redirected.
if (request->status().status() == net::URLRequestStatus::CANCELED ||
(request->status().status() == net::URLRequestStatus::FAILED &&
request->status().error() == net::ERR_ABORTED)) {
return nullptr;
}
// Request to NTP was successful.
if (request->status().is_success() &&
request->GetResponseCode() != net::HTTP_NO_CONTENT &&
request->GetResponseCode() < 400) {
return nullptr;
}
// Failure to load the NTP correctly; redirect to Local NTP.
UMA_HISTOGRAM_ENUMERATION("InstantExtended.CacheableNTPLoad",
chrome::CACHEABLE_NTP_LOAD_FAILED,
chrome::CACHEABLE_NTP_LOAD_MAX);
return new net::URLRequestRedirectJob(
request, network_delegate, GURL(chrome::kChromeSearchLocalNtpUrl),
net::URLRequestRedirectJob::REDIRECT_307_TEMPORARY_REDIRECT,
"NTP Request Interceptor");
}
GURL new_tab_url_;
base::WeakPtrFactory<NewTabPageInterceptor> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(NewTabPageInterceptor);
};
NewTabPageInterceptorService::NewTabPageInterceptorService(Profile* profile)
: profile_(profile),
template_url_service_(TemplateURLServiceFactory::GetForProfile(profile)) {
DCHECK(profile_);
if (template_url_service_)
template_url_service_->AddObserver(this);
}
NewTabPageInterceptorService::~NewTabPageInterceptorService() {
if (template_url_service_)
template_url_service_->RemoveObserver(this);
}
void NewTabPageInterceptorService::OnTemplateURLServiceChanged() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
GURL new_tab_page_url(chrome::GetNewTabPageURL(profile_));
content::BrowserThread::PostTask(
content::BrowserThread::IO, FROM_HERE,
base::Bind(&NewTabPageInterceptor::SetNewTabPageURL, interceptor_,
new_tab_page_url));
}
scoped_ptr<net::URLRequestInterceptor>
NewTabPageInterceptorService::CreateInterceptor() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
scoped_ptr<NewTabPageInterceptor> interceptor(
new NewTabPageInterceptor(chrome::GetNewTabPageURL(profile_)));
interceptor_ = interceptor->GetWeakPtr();
return interceptor.Pass();
}
// Copyright 2015 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.
#ifndef CHROME_BROWSER_UI_SEARCH_NEW_TAB_PAGE_INTERCEPTOR_SERVICE_H_
#define CHROME_BROWSER_UI_SEARCH_NEW_TAB_PAGE_INTERCEPTOR_SERVICE_H_
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/search_engines/template_url_service_observer.h"
class NewTabPageInterceptor;
class Profile;
class TemplateURLService;
namespace net {
class URLRequestInterceptor;
}
// Owns a NewTabPageInterceptor.
class NewTabPageInterceptorService : public KeyedService,
public TemplateURLServiceObserver {
public:
explicit NewTabPageInterceptorService(Profile* profile);
~NewTabPageInterceptorService() override;
// TemplateURLServiceObserver override.
void OnTemplateURLServiceChanged() override;
scoped_ptr<net::URLRequestInterceptor> CreateInterceptor();
private:
Profile* profile_;
base::WeakPtr<NewTabPageInterceptor> interceptor_;
// The TemplateURLService that we are observing. It will outlive this
// NewTabPageInterceptorService due to the dependency declared in
// NewTabPageInterceptorServiceFactory.
TemplateURLService* template_url_service_;
DISALLOW_COPY_AND_ASSIGN(NewTabPageInterceptorService);
};
#endif // CHROME_BROWSER_UI_SEARCH_NEW_TAB_PAGE_INTERCEPTOR_SERVICE_H_
// Copyright 2015 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.
#include "chrome/browser/ui/search/new_tab_page_interceptor_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search/instant_service_factory.h"
#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/browser/ui/search/new_tab_page_interceptor_service.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "content/public/browser/browser_thread.h"
// static
NewTabPageInterceptorServiceFactory*
NewTabPageInterceptorServiceFactory::GetInstance() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
return Singleton<NewTabPageInterceptorServiceFactory>::get();
}
// static
NewTabPageInterceptorService*
NewTabPageInterceptorServiceFactory::GetForProfile(Profile* profile) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (profile->IsOffTheRecord())
return nullptr;
return static_cast<NewTabPageInterceptorService*>(
GetInstance()->GetServiceForBrowserContext(profile, true));
}
NewTabPageInterceptorServiceFactory::NewTabPageInterceptorServiceFactory()
: BrowserContextKeyedServiceFactory(
"NTP Request Interceptor Service Factory",
BrowserContextDependencyManager::GetInstance()) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
DependsOn(TemplateURLServiceFactory::GetInstance());
}
NewTabPageInterceptorServiceFactory::~NewTabPageInterceptorServiceFactory() {
}
KeyedService* NewTabPageInterceptorServiceFactory::BuildServiceInstanceFor(
content::BrowserContext* context) const {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
Profile* profile = Profile::FromBrowserContext(context);
return new NewTabPageInterceptorService(profile);
}
// Copyright 2015 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.
#ifndef CHROME_BROWSER_UI_SEARCH_NEW_TAB_PAGE_INTERCEPTOR_SERVICE_FACTORY_H_
#define CHROME_BROWSER_UI_SEARCH_NEW_TAB_PAGE_INTERCEPTOR_SERVICE_FACTORY_H_
#include "base/memory/singleton.h"
#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
#include "components/keyed_service/core/keyed_service.h"
class NewTabPageInterceptorService;
class Profile;
namespace content {
class BrowserContext;
}
namespace net {
class URLRequestInterceptor;
}
// Owns and creates NewTabPageInterceptorService instances.
class NewTabPageInterceptorServiceFactory
: public BrowserContextKeyedServiceFactory {
public:
static NewTabPageInterceptorService* GetForProfile(Profile* profile);
static NewTabPageInterceptorServiceFactory* GetInstance();
private:
friend struct DefaultSingletonTraits<NewTabPageInterceptorServiceFactory>;
NewTabPageInterceptorServiceFactory();
~NewTabPageInterceptorServiceFactory() override;
// BrowserContextKeyedServiceFactory:
KeyedService* BuildServiceInstanceFor(
content::BrowserContext* context) const override;
DISALLOW_COPY_AND_ASSIGN(NewTabPageInterceptorServiceFactory);
};
#endif // CHROME_BROWSER_UI_SEARCH_NEW_TAB_PAGE_INTERCEPTOR_SERVICE_FACTORY_H_
...@@ -56,20 +56,6 @@ DEFINE_WEB_CONTENTS_USER_DATA_KEY(SearchTabHelper); ...@@ -56,20 +56,6 @@ DEFINE_WEB_CONTENTS_USER_DATA_KEY(SearchTabHelper);
namespace { namespace {
// For reporting Cacheable NTP navigations.
enum CacheableNTPLoad {
CACHEABLE_NTP_LOAD_FAILED = 0,
CACHEABLE_NTP_LOAD_SUCCEEDED = 1,
CACHEABLE_NTP_LOAD_MAX = 2
};
void RecordCacheableNTPLoadHistogram(bool succeeded) {
UMA_HISTOGRAM_ENUMERATION("InstantExtended.CacheableNTPLoad",
succeeded ? CACHEABLE_NTP_LOAD_SUCCEEDED :
CACHEABLE_NTP_LOAD_FAILED,
CACHEABLE_NTP_LOAD_MAX);
}
bool IsCacheableNTP(const content::WebContents* contents) { bool IsCacheableNTP(const content::WebContents* contents) {
const content::NavigationEntry* entry = const content::NavigationEntry* entry =
contents->GetController().GetLastCommittedEntry(); contents->GetController().GetLastCommittedEntry();
...@@ -311,12 +297,9 @@ void SearchTabHelper::DidNavigateMainFrame( ...@@ -311,12 +297,9 @@ void SearchTabHelper::DidNavigateMainFrame(
const content::LoadCommittedDetails& details, const content::LoadCommittedDetails& details,
const content::FrameNavigateParams& params) { const content::FrameNavigateParams& params) {
if (IsCacheableNTP(web_contents_)) { if (IsCacheableNTP(web_contents_)) {
if (details.http_status_code == 204 || details.http_status_code >= 400) { UMA_HISTOGRAM_ENUMERATION("InstantExtended.CacheableNTPLoad",
RedirectToLocalNTP(); chrome::CACHEABLE_NTP_LOAD_SUCCEEDED,
RecordCacheableNTPLoadHistogram(false); chrome::CACHEABLE_NTP_LOAD_MAX);
return;
}
RecordCacheableNTPLoadHistogram(true);
} }
// Always set the title on the new tab page to be the one from our UI // Always set the title on the new tab page to be the one from our UI
...@@ -338,21 +321,6 @@ void SearchTabHelper::DidNavigateMainFrame( ...@@ -338,21 +321,6 @@ void SearchTabHelper::DidNavigateMainFrame(
} }
} }
void SearchTabHelper::DidFailProvisionalLoad(
content::RenderFrameHost* render_frame_host,
const GURL& validated_url,
int error_code,
const base::string16& /* error_description */) {
// If error_code is ERR_ABORTED means that the user has canceled this
// navigation so it shouldn't be redirected.
if (!render_frame_host->GetParent() && error_code != net::ERR_ABORTED &&
validated_url != GURL(chrome::kChromeSearchLocalNtpUrl) &&
chrome::IsNTPURL(validated_url, profile())) {
RedirectToLocalNTP();
RecordCacheableNTPLoadHistogram(false);
}
}
void SearchTabHelper::DidFinishLoad(content::RenderFrameHost* render_frame_host, void SearchTabHelper::DidFinishLoad(content::RenderFrameHost* render_frame_host,
const GURL& /* validated_url */) { const GURL& /* validated_url */) {
if (!render_frame_host->GetParent()) { if (!render_frame_host->GetParent()) {
...@@ -619,17 +587,6 @@ Profile* SearchTabHelper::profile() const { ...@@ -619,17 +587,6 @@ Profile* SearchTabHelper::profile() const {
return Profile::FromBrowserContext(web_contents_->GetBrowserContext()); return Profile::FromBrowserContext(web_contents_->GetBrowserContext());
} }
void SearchTabHelper::RedirectToLocalNTP() {
// Extra parentheses to declare a variable.
content::NavigationController::LoadURLParams load_params(
(GURL(chrome::kChromeSearchLocalNtpUrl)));
load_params.referrer = content::Referrer();
load_params.transition_type = ui::PAGE_TRANSITION_SERVER_REDIRECT;
// Don't push a history entry.
load_params.should_replace_current_entry = true;
web_contents_->GetController().LoadURLWithParams(load_params);
}
bool SearchTabHelper::IsInputInProgress() const { bool SearchTabHelper::IsInputInProgress() const {
OmniboxView* omnibox = GetOmniboxView(); OmniboxView* omnibox = GetOmniboxView();
return !model_.mode().is_ntp() && omnibox && return !model_.mode().is_ntp() && omnibox &&
......
...@@ -156,10 +156,6 @@ class SearchTabHelper : public content::WebContentsObserver, ...@@ -156,10 +156,6 @@ class SearchTabHelper : public content::WebContentsObserver,
void DidNavigateMainFrame( void DidNavigateMainFrame(
const content::LoadCommittedDetails& details, const content::LoadCommittedDetails& details,
const content::FrameNavigateParams& params) override; const content::FrameNavigateParams& params) override;
void DidFailProvisionalLoad(content::RenderFrameHost* render_frame_host,
const GURL& validated_url,
int error_code,
const base::string16& error_description) override;
void DidFinishLoad(content::RenderFrameHost* render_frame_host, void DidFinishLoad(content::RenderFrameHost* render_frame_host,
const GURL& validated_url) override; const GURL& validated_url) override;
void NavigationEntryCommitted( void NavigationEntryCommitted(
...@@ -207,10 +203,6 @@ class SearchTabHelper : public content::WebContentsObserver, ...@@ -207,10 +203,6 @@ class SearchTabHelper : public content::WebContentsObserver,
Profile* profile() const; Profile* profile() const;
// Helper function to navigate the given contents to the local fallback
// Instant URL and trim the history correctly.
void RedirectToLocalNTP();
// Returns whether input is in progress, i.e. if the omnibox has focus and the // Returns whether input is in progress, i.e. if the omnibox has focus and the
// active tab is in mode SEARCH_SUGGESTIONS. // active tab is in mode SEARCH_SUGGESTIONS.
bool IsInputInProgress() const; bool IsInputInProgress() const;
......
...@@ -397,68 +397,6 @@ class SearchTabHelperWindowTest : public BrowserWithTestWindowTest { ...@@ -397,68 +397,6 @@ class SearchTabHelperWindowTest : public BrowserWithTestWindowTest {
} }
}; };
TEST_F(SearchTabHelperWindowTest, OnProvisionalLoadFailRedirectNTPToLocal) {
AddTab(browser(), GURL(chrome::kChromeUINewTabURL));
content::WebContents* contents =
browser()->tab_strip_model()->GetWebContentsAt(0);
content::NavigationController* controller = &contents->GetController();
SearchTabHelper* search_tab_helper =
SearchTabHelper::FromWebContents(contents);
ASSERT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper);
// A failed provisional load of a cacheable NTP should be redirected to local
// NTP.
const GURL cacheableNTPURL = chrome::GetNewTabPageURL(profile());
search_tab_helper->DidFailProvisionalLoad(
contents->GetMainFrame(), cacheableNTPURL, 1, base::string16());
CommitPendingLoad(controller);
EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl),
controller->GetLastCommittedEntry()->GetURL());
}
TEST_F(SearchTabHelperWindowTest, OnProvisionalLoadFailDontRedirectIfAborted) {
AddTab(browser(), GURL("chrome://blank"));
content::WebContents* contents =
browser()->tab_strip_model()->GetWebContentsAt(0);
content::NavigationController* controller = &contents->GetController();
SearchTabHelper* search_tab_helper =
SearchTabHelper::FromWebContents(contents);
ASSERT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper);
// A failed provisional load of a cacheable NTP should be redirected to local
// NTP.
const GURL cacheableNTPURL = chrome::GetNewTabPageURL(profile());
search_tab_helper->DidFailProvisionalLoad(contents->GetMainFrame(),
cacheableNTPURL,
net::ERR_ABORTED,
base::string16());
CommitPendingLoad(controller);
EXPECT_EQ(GURL("chrome://blank"),
controller->GetLastCommittedEntry()->GetURL());
}
TEST_F(SearchTabHelperWindowTest, OnProvisionalLoadFailDontRedirectNonNTP) {
AddTab(browser(), GURL(chrome::kChromeUINewTabURL));
content::WebContents* contents =
browser()->tab_strip_model()->GetWebContentsAt(0);
content::NavigationController* controller = &contents->GetController();
SearchTabHelper* search_tab_helper =
SearchTabHelper::FromWebContents(contents);
ASSERT_NE(static_cast<SearchTabHelper*>(NULL), search_tab_helper);
// Any other web page shouldn't be redirected when provisional load fails.
search_tab_helper->DidFailProvisionalLoad(contents->GetMainFrame(),
GURL("http://www.example.com"),
1,
base::string16());
CommitPendingLoad(controller);
EXPECT_NE(GURL(chrome::kChromeSearchLocalNtpUrl),
controller->GetLastCommittedEntry()->GetURL());
}
class SearchTabHelperPrerenderTest : public InstantUnitTestBase { class SearchTabHelperPrerenderTest : public InstantUnitTestBase {
public: public:
~SearchTabHelperPrerenderTest() override {} ~SearchTabHelperPrerenderTest() override {}
......
...@@ -821,6 +821,10 @@ ...@@ -821,6 +821,10 @@
'browser/ui/search/instant_search_prerenderer.h', 'browser/ui/search/instant_search_prerenderer.h',
'browser/ui/search/instant_tab.cc', 'browser/ui/search/instant_tab.cc',
'browser/ui/search/instant_tab.h', 'browser/ui/search/instant_tab.h',
'browser/ui/search/new_tab_page_interceptor_service_factory.cc',
'browser/ui/search/new_tab_page_interceptor_service_factory.h',
'browser/ui/search/new_tab_page_interceptor_service.cc',
'browser/ui/search/new_tab_page_interceptor_service.h',
'browser/ui/search/search_ipc_router.cc', 'browser/ui/search/search_ipc_router.cc',
'browser/ui/search/search_ipc_router.h', 'browser/ui/search/search_ipc_router.h',
'browser/ui/search/search_ipc_router_policy_impl.cc', 'browser/ui/search/search_ipc_router_policy_impl.cc',
......
...@@ -481,6 +481,7 @@ ...@@ -481,6 +481,7 @@
'browser/ui/passwords/manage_passwords_test.cc', 'browser/ui/passwords/manage_passwords_test.cc',
'browser/ui/pdf/pdf_browsertest.cc', 'browser/ui/pdf/pdf_browsertest.cc',
'browser/ui/prefs/prefs_tab_helper_browsertest.cc', 'browser/ui/prefs/prefs_tab_helper_browsertest.cc',
'browser/ui/search/new_tab_page_interceptor_browsertest.cc',
'browser/ui/settings_window_manager_browsertest.cc', 'browser/ui/settings_window_manager_browsertest.cc',
'browser/ui/startup/startup_browser_creator_browsertest.cc', 'browser/ui/startup/startup_browser_creator_browsertest.cc',
'browser/ui/sync/one_click_signin_bubble_links_delegate_browsertest.cc', 'browser/ui/sync/one_click_signin_bubble_links_delegate_browsertest.cc',
......
<title>This page intentionally left blank</title>
HTTP/1.0 204 No Content
Content-Length: 0
...@@ -19,7 +19,7 @@ namespace cronet { ...@@ -19,7 +19,7 @@ namespace cronet {
void AddUrlInterceptors(JNIEnv* env, jclass jcaller, jstring jtest_files_root) { void AddUrlInterceptors(JNIEnv* env, jclass jcaller, jstring jtest_files_root) {
base::FilePath test_files_root( base::FilePath test_files_root(
base::android::ConvertJavaStringToUTF8(env, jtest_files_root)); base::android::ConvertJavaStringToUTF8(env, jtest_files_root));
net::URLRequestMockHTTPJob::AddUrlHandler( net::URLRequestMockHTTPJob::AddUrlHandlers(
test_files_root, new base::SequencedWorkerPool(1, "Worker")); test_files_root, new base::SequencedWorkerPool(1, "Worker"));
net::URLRequestMockDataJob::AddUrlHandler(); net::URLRequestMockDataJob::AddUrlHandler();
net::URLRequestFailedJob::AddUrlHandler(); net::URLRequestFailedJob::AddUrlHandler();
......
...@@ -586,11 +586,9 @@ class DownloadContentTest : public ContentBrowserTest { ...@@ -586,11 +586,9 @@ class DownloadContentTest : public ContentBrowserTest {
base::Bind(&net::URLRequestSlowDownloadJob::AddUrlHandler)); base::Bind(&net::URLRequestSlowDownloadJob::AddUrlHandler));
base::FilePath mock_base(GetTestFilePath("download", "")); base::FilePath mock_base(GetTestFilePath("download", ""));
BrowserThread::PostTask( BrowserThread::PostTask(
BrowserThread::IO, BrowserThread::IO, FROM_HERE,
FROM_HERE,
base::Bind( base::Bind(
&net::URLRequestMockHTTPJob::AddUrlHandler, &net::URLRequestMockHTTPJob::AddUrlHandlers, mock_base,
mock_base,
make_scoped_refptr(content::BrowserThread::GetBlockingPool()))); make_scoped_refptr(content::BrowserThread::GetBlockingPool())));
} }
......
...@@ -73,11 +73,9 @@ class DragDownloadFileTest : public ContentBrowserTest { ...@@ -73,11 +73,9 @@ class DragDownloadFileTest : public ContentBrowserTest {
void SetUpServer() { void SetUpServer() {
base::FilePath mock_base(GetTestFilePath("download", "")); base::FilePath mock_base(GetTestFilePath("download", ""));
BrowserThread::PostTask( BrowserThread::PostTask(
BrowserThread::IO, BrowserThread::IO, FROM_HERE,
FROM_HERE,
base::Bind( base::Bind(
&net::URLRequestMockHTTPJob::AddUrlHandler, &net::URLRequestMockHTTPJob::AddUrlHandlers, mock_base,
mock_base,
make_scoped_refptr(content::BrowserThread::GetBlockingPool()))); make_scoped_refptr(content::BrowserThread::GetBlockingPool())));
} }
......
...@@ -42,11 +42,9 @@ class ResourceDispatcherHostBrowserTest : public ContentBrowserTest, ...@@ -42,11 +42,9 @@ class ResourceDispatcherHostBrowserTest : public ContentBrowserTest,
void SetUpOnMainThread() override { void SetUpOnMainThread() override {
base::FilePath path = GetTestFilePath("", ""); base::FilePath path = GetTestFilePath("", "");
BrowserThread::PostTask( BrowserThread::PostTask(
BrowserThread::IO, BrowserThread::IO, FROM_HERE,
FROM_HERE,
base::Bind( base::Bind(
&net::URLRequestMockHTTPJob::AddUrlHandler, &net::URLRequestMockHTTPJob::AddUrlHandlers, path,
path,
make_scoped_refptr(content::BrowserThread::GetBlockingPool()))); make_scoped_refptr(content::BrowserThread::GetBlockingPool())));
BrowserThread::PostTask( BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE, BrowserThread::IO, FROM_HERE,
......
...@@ -39,7 +39,7 @@ namespace content { ...@@ -39,7 +39,7 @@ namespace content {
namespace { namespace {
void SetUrlRequestMock(const base::FilePath& path) { void SetUrlRequestMock(const base::FilePath& path) {
net::URLRequestMockHTTPJob::AddUrlHandler( net::URLRequestMockHTTPJob::AddUrlHandlers(
path, content::BrowserThread::GetBlockingPool()); path, content::BrowserThread::GetBlockingPool());
} }
......
...@@ -96,16 +96,29 @@ std::string DoFileIO(const base::FilePath& file_path) { ...@@ -96,16 +96,29 @@ std::string DoFileIO(const base::FilePath& file_path) {
return raw_headers; return raw_headers;
} }
// For a given file |path| and |scheme|, return the URL served by the
// URlRequestMockHTTPJob.
GURL GetMockUrlForScheme(const base::FilePath& path,
const std::string& scheme) {
std::string url = scheme + "://" + kMockHostname + "/";
std::string path_str = path.MaybeAsASCII();
DCHECK(!path_str.empty()); // We only expect ASCII paths in tests.
url.append(path_str);
return GURL(url);
}
} // namespace } // namespace
// static // static
void URLRequestMockHTTPJob::AddUrlHandler( void URLRequestMockHTTPJob::AddUrlHandlers(
const base::FilePath& base_path, const base::FilePath& base_path,
const scoped_refptr<base::SequencedWorkerPool>& worker_pool) { const scoped_refptr<base::SequencedWorkerPool>& worker_pool) {
// Add kMockHostname to net::URLRequestFilter. // Add kMockHostname to net::URLRequestFilter, for both HTTP and HTTPS.
net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance(); net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance();
filter->AddHostnameInterceptor( filter->AddHostnameInterceptor(
"http", kMockHostname, CreateInterceptor(base_path, worker_pool)); "http", kMockHostname, CreateInterceptor(base_path, worker_pool));
filter->AddHostnameInterceptor("https", kMockHostname,
CreateInterceptor(base_path, worker_pool));
} }
// static // static
...@@ -120,13 +133,12 @@ void URLRequestMockHTTPJob::AddHostnameToFileHandler( ...@@ -120,13 +133,12 @@ void URLRequestMockHTTPJob::AddHostnameToFileHandler(
// static // static
GURL URLRequestMockHTTPJob::GetMockUrl(const base::FilePath& path) { GURL URLRequestMockHTTPJob::GetMockUrl(const base::FilePath& path) {
std::string url = "http://"; return GetMockUrlForScheme(path, "http");
url.append(kMockHostname); }
url.append("/");
std::string path_str = path.MaybeAsASCII(); // static
DCHECK(!path_str.empty()); // We only expect ASCII paths in tests. GURL URLRequestMockHTTPJob::GetMockHttpsUrl(const base::FilePath& path) {
url.append(path_str); return GetMockUrlForScheme(path, "https");
return GURL(url);
} }
// static // static
......
...@@ -49,8 +49,8 @@ class URLRequestMockHTTPJob : public URLRequestFileJob { ...@@ -49,8 +49,8 @@ class URLRequestMockHTTPJob : public URLRequestFileJob {
void GetResponseInfo(HttpResponseInfo* info) override; void GetResponseInfo(HttpResponseInfo* info) override;
bool IsRedirectResponse(GURL* location, int* http_status_code) override; bool IsRedirectResponse(GURL* location, int* http_status_code) override;
// Adds the testing URLs to the URLRequestFilter. // Adds the testing URLs to the URLRequestFilter, both under HTTP and HTTPS.
static void AddUrlHandler( static void AddUrlHandlers(
const base::FilePath& base_path, const base::FilePath& base_path,
const scoped_refptr<base::SequencedWorkerPool>& worker_pool); const scoped_refptr<base::SequencedWorkerPool>& worker_pool);
...@@ -64,6 +64,7 @@ class URLRequestMockHTTPJob : public URLRequestFileJob { ...@@ -64,6 +64,7 @@ class URLRequestMockHTTPJob : public URLRequestFileJob {
// Given the path to a file relative to the path passed to AddUrlHandler(), // Given the path to a file relative to the path passed to AddUrlHandler(),
// construct a mock URL. // construct a mock URL.
static GURL GetMockUrl(const base::FilePath& path); static GURL GetMockUrl(const base::FilePath& path);
static GURL GetMockHttpsUrl(const base::FilePath& path);
// Given the path to a file relative to the path passed to AddUrlHandler(), // Given the path to a file relative to the path passed to AddUrlHandler(),
// construct a mock URL that reports |net_error| at given |phase| of the // construct a mock URL that reports |net_error| at given |phase| of the
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment