1 // Copyright (c) 2012 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 "android_webview/browser/aw_login_delegate.h"
7 #include "android_webview/browser/aw_browser_context.h"
8 #include "base/android/jni_android.h"
9 #include "base/logging.h"
10 #include "base/supports_user_data.h"
11 #include "components/data_reduction_proxy/browser/data_reduction_proxy_auth_request_handler.h"
12 #include "components/data_reduction_proxy/browser/data_reduction_proxy_settings.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "content/public/browser/render_frame_host.h"
15 #include "content/public/browser/resource_dispatcher_host.h"
16 #include "content/public/browser/resource_request_info.h"
17 #include "content/public/browser/web_contents.h"
18 #include "net/base/auth.h"
19 #include "net/url_request/url_request.h"
21 using namespace base::android
;
23 using content::BrowserThread
;
24 using content::RenderFrameHost
;
25 using content::ResourceDispatcherHost
;
26 using content::ResourceRequestInfo
;
27 using content::WebContents
;
28 using data_reduction_proxy::DataReductionProxyAuthRequestHandler
;
29 using data_reduction_proxy::DataReductionProxySettings
;
32 const char* kAuthAttemptsKey
= "android_webview_auth_attempts";
34 class UrlRequestAuthAttemptsData
: public base::SupportsUserData::Data
{
36 UrlRequestAuthAttemptsData() : auth_attempts_(0) { }
42 namespace android_webview
{
44 AwLoginDelegate::AwLoginDelegate(net::AuthChallengeInfo
* auth_info
,
45 net::URLRequest
* request
)
46 : auth_info_(auth_info
),
48 render_process_id_(0),
50 ResourceRequestInfo::GetRenderFrameForRequest(
51 request
, &render_process_id_
, &render_frame_id_
);
53 UrlRequestAuthAttemptsData
* count
=
54 static_cast<UrlRequestAuthAttemptsData
*>(
55 request
->GetUserData(kAuthAttemptsKey
));
58 count
= new UrlRequestAuthAttemptsData();
59 request
->SetUserData(kAuthAttemptsKey
, count
);
62 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
63 base::Bind(&AwLoginDelegate::HandleHttpAuthRequestOnUIThread
,
64 this, (count
->auth_attempts_
== 0)));
65 count
->auth_attempts_
++;
68 AwLoginDelegate::~AwLoginDelegate() {
69 // The Auth handler holds a ref count back on |this| object, so it should be
70 // impossible to reach here while this object still owns an auth handler.
71 DCHECK(aw_http_auth_handler_
== NULL
);
74 void AwLoginDelegate::Proceed(const base::string16
& user
,
75 const base::string16
& password
) {
76 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
77 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
78 base::Bind(&AwLoginDelegate::ProceedOnIOThread
,
79 this, user
, password
));
82 void AwLoginDelegate::Cancel() {
83 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
84 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
85 base::Bind(&AwLoginDelegate::CancelOnIOThread
, this));
88 void AwLoginDelegate::HandleHttpAuthRequestOnUIThread(
89 bool first_auth_attempt
) {
90 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
92 aw_http_auth_handler_
.reset(AwHttpAuthHandlerBase::Create(
93 this, auth_info_
.get(), first_auth_attempt
));
95 RenderFrameHost
* render_frame_host
= RenderFrameHost::FromID(
96 render_process_id_
, render_frame_id_
);
97 WebContents
* web_contents
= WebContents::FromRenderFrameHost(
99 AwBrowserContext
* browser_context
=
100 AwBrowserContext::FromWebContents(web_contents
);
101 DataReductionProxySettings
* drp_settings
=
102 browser_context
->GetDataReductionProxySettings();
103 if (drp_settings
&& drp_settings
->IsDataReductionProxyEnabled()) {
104 // The data reduction proxy auth handler should only be reset on the first
105 // auth attempt, because it maintains internal state to cancel if there have
106 // been too many attempts.
107 if (!drp_auth_handler_
.get()) {
108 drp_auth_handler_
.reset(new DataReductionProxyAuthRequestHandler(
111 DCHECK(drp_auth_handler_
.get());
112 base::string16 user
, password
;
113 DataReductionProxyAuthRequestHandler::TryHandleResult drp_result
=
114 drp_auth_handler_
->TryHandleAuthentication(
115 auth_info_
.get(), &user
, &password
);
117 DataReductionProxyAuthRequestHandler::TRY_HANDLE_RESULT_PROCEED
) {
118 Proceed(user
, password
);
122 DataReductionProxyAuthRequestHandler::TRY_HANDLE_RESULT_CANCEL
) {
126 // Fall through if |drp_result| is IGNORE
129 if (!aw_http_auth_handler_
->HandleOnUIThread(web_contents
)) {
135 void AwLoginDelegate::CancelOnIOThread() {
136 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
138 request_
->CancelAuth();
139 ResourceDispatcherHost::Get()->ClearLoginDelegateForRequest(request_
);
142 DeleteAuthHandlerSoon();
145 void AwLoginDelegate::ProceedOnIOThread(const base::string16
& user
,
146 const base::string16
& password
) {
147 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
149 request_
->SetAuth(net::AuthCredentials(user
, password
));
150 ResourceDispatcherHost::Get()->ClearLoginDelegateForRequest(request_
);
153 DeleteAuthHandlerSoon();
156 void AwLoginDelegate::OnRequestCancelled() {
157 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
159 DeleteAuthHandlerSoon();
162 void AwLoginDelegate::DeleteAuthHandlerSoon() {
163 if (!BrowserThread::CurrentlyOn(BrowserThread::UI
)) {
164 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
165 base::Bind(&AwLoginDelegate::DeleteAuthHandlerSoon
, this));
168 aw_http_auth_handler_
.reset();
171 } // namespace android_webview