1 // Copyright 2015 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.
5 #include "chrome/browser/ui/search/new_tab_page_interceptor_service.h"
7 #include "base/location.h"
8 #include "base/logging.h"
9 #include "base/metrics/histogram.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/search/search.h"
12 #include "chrome/browser/search_engines/template_url_service_factory.h"
13 #include "chrome/common/url_constants.h"
14 #include "components/search_engines/template_url_service.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "net/base/net_errors.h"
17 #include "net/http/http_status_code.h"
18 #include "net/url_request/url_request.h"
19 #include "net/url_request/url_request_interceptor.h"
20 #include "net/url_request/url_request_job.h"
21 #include "net/url_request/url_request_redirect_job.h"
24 // Implementation of the URLRequestInterceptor for the New Tab Page. Will look
25 // at incoming response from the server and possibly divert to the local NTP.
26 class NewTabPageInterceptor
: public net::URLRequestInterceptor
{
28 explicit NewTabPageInterceptor(const GURL
& new_tab_url
)
29 : new_tab_url_(new_tab_url
), weak_factory_(this) {
30 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
33 ~NewTabPageInterceptor() override
{
34 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
37 base::WeakPtr
<NewTabPageInterceptor
> GetWeakPtr() {
38 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
39 return weak_factory_
.GetWeakPtr();
42 void SetNewTabPageURL(const GURL
& new_tab_page_url
) {
43 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
44 new_tab_url_
= new_tab_page_url
;
48 // Overrides from net::URLRequestInterceptor:
49 net::URLRequestJob
* MaybeInterceptRequest(
50 net::URLRequest
* request
,
51 net::NetworkDelegate
* network_delegate
) const override
{
52 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
56 net::URLRequestJob
* MaybeInterceptResponse(
57 net::URLRequest
* request
,
58 net::NetworkDelegate
* network_delegate
) const override
{
59 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
60 if ((request
->url() != new_tab_url_
) ||
61 (new_tab_url_
== GURL(chrome::kChromeSearchLocalNtpUrl
))) {
64 // User has canceled this navigation so it shouldn't be redirected.
65 if (request
->status().status() == net::URLRequestStatus::CANCELED
||
66 (request
->status().status() == net::URLRequestStatus::FAILED
&&
67 request
->status().error() == net::ERR_ABORTED
)) {
71 // Request to NTP was successful.
72 if (request
->status().is_success() &&
73 request
->GetResponseCode() != net::HTTP_NO_CONTENT
&&
74 request
->GetResponseCode() < 400) {
78 // Failure to load the NTP correctly; redirect to Local NTP.
79 UMA_HISTOGRAM_ENUMERATION("InstantExtended.CacheableNTPLoad",
80 search::CACHEABLE_NTP_LOAD_FAILED
,
81 search::CACHEABLE_NTP_LOAD_MAX
);
82 return new net::URLRequestRedirectJob(
83 request
, network_delegate
, GURL(chrome::kChromeSearchLocalNtpUrl
),
84 net::URLRequestRedirectJob::REDIRECT_307_TEMPORARY_REDIRECT
,
85 "NTP Request Interceptor");
89 base::WeakPtrFactory
<NewTabPageInterceptor
> weak_factory_
;
91 DISALLOW_COPY_AND_ASSIGN(NewTabPageInterceptor
);
94 NewTabPageInterceptorService::NewTabPageInterceptorService(Profile
* profile
)
96 template_url_service_(TemplateURLServiceFactory::GetForProfile(profile
)) {
98 if (template_url_service_
)
99 template_url_service_
->AddObserver(this);
102 NewTabPageInterceptorService::~NewTabPageInterceptorService() {
103 if (template_url_service_
)
104 template_url_service_
->RemoveObserver(this);
107 void NewTabPageInterceptorService::OnTemplateURLServiceChanged() {
108 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
109 GURL
new_tab_page_url(search::GetNewTabPageURL(profile_
));
110 content::BrowserThread::PostTask(
111 content::BrowserThread::IO
, FROM_HERE
,
112 base::Bind(&NewTabPageInterceptor::SetNewTabPageURL
, interceptor_
,
116 scoped_ptr
<net::URLRequestInterceptor
>
117 NewTabPageInterceptorService::CreateInterceptor() {
118 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
119 scoped_ptr
<NewTabPageInterceptor
> interceptor(
120 new NewTabPageInterceptor(search::GetNewTabPageURL(profile_
)));
121 interceptor_
= interceptor
->GetWeakPtr();
122 return interceptor
.Pass();