Home | History | Annotate | Download | only in browser
      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.
      4 
      5 #include "android_webview/browser/aw_login_delegate.h"
      6 
      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 "content/public/browser/browser_thread.h"
     12 #include "content/public/browser/render_frame_host.h"
     13 #include "content/public/browser/resource_dispatcher_host.h"
     14 #include "content/public/browser/resource_request_info.h"
     15 #include "content/public/browser/web_contents.h"
     16 #include "net/base/auth.h"
     17 #include "net/url_request/url_request.h"
     18 
     19 using namespace base::android;
     20 
     21 using content::BrowserThread;
     22 using content::RenderFrameHost;
     23 using content::ResourceDispatcherHost;
     24 using content::ResourceRequestInfo;
     25 using content::WebContents;
     26 
     27 namespace {
     28 const char* kAuthAttemptsKey = "android_webview_auth_attempts";
     29 
     30 class UrlRequestAuthAttemptsData : public base::SupportsUserData::Data {
     31  public:
     32   UrlRequestAuthAttemptsData() : auth_attempts_(0) { }
     33   int auth_attempts_;
     34 };
     35 
     36 }  // namespace
     37 
     38 namespace android_webview {
     39 
     40 AwLoginDelegate::AwLoginDelegate(net::AuthChallengeInfo* auth_info,
     41                                  net::URLRequest* request)
     42     : auth_info_(auth_info),
     43       request_(request),
     44       render_process_id_(0),
     45       render_frame_id_(0) {
     46     ResourceRequestInfo::GetRenderFrameForRequest(
     47         request, &render_process_id_, &render_frame_id_);
     48 
     49     UrlRequestAuthAttemptsData* count =
     50         static_cast<UrlRequestAuthAttemptsData*>(
     51             request->GetUserData(kAuthAttemptsKey));
     52 
     53     if (count == NULL) {
     54       count = new UrlRequestAuthAttemptsData();
     55       request->SetUserData(kAuthAttemptsKey, count);
     56     }
     57 
     58     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
     59         base::Bind(&AwLoginDelegate::HandleHttpAuthRequestOnUIThread,
     60                    this, (count->auth_attempts_ == 0)));
     61     count->auth_attempts_++;
     62 }
     63 
     64 AwLoginDelegate::~AwLoginDelegate() {
     65   // The Auth handler holds a ref count back on |this| object, so it should be
     66   // impossible to reach here while this object still owns an auth handler.
     67   DCHECK(!aw_http_auth_handler_);
     68 }
     69 
     70 void AwLoginDelegate::Proceed(const base::string16& user,
     71                               const base::string16& password) {
     72   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     73   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
     74       base::Bind(&AwLoginDelegate::ProceedOnIOThread,
     75                  this, user, password));
     76 }
     77 
     78 void AwLoginDelegate::Cancel() {
     79   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     80   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
     81       base::Bind(&AwLoginDelegate::CancelOnIOThread, this));
     82 }
     83 
     84 void AwLoginDelegate::HandleHttpAuthRequestOnUIThread(
     85     bool first_auth_attempt) {
     86   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     87 
     88   aw_http_auth_handler_.reset(AwHttpAuthHandlerBase::Create(
     89       this, auth_info_.get(), first_auth_attempt));
     90 
     91   RenderFrameHost* render_frame_host = RenderFrameHost::FromID(
     92       render_process_id_, render_frame_id_);
     93   WebContents* web_contents = WebContents::FromRenderFrameHost(
     94       render_frame_host);
     95   if (!aw_http_auth_handler_->HandleOnUIThread(web_contents)) {
     96     Cancel();
     97     return;
     98   }
     99 }
    100 
    101 void AwLoginDelegate::CancelOnIOThread() {
    102   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    103   if (request_) {
    104     request_->CancelAuth();
    105     ResourceDispatcherHost::Get()->ClearLoginDelegateForRequest(request_);
    106     request_ = NULL;
    107   }
    108   DeleteAuthHandlerSoon();
    109 }
    110 
    111 void AwLoginDelegate::ProceedOnIOThread(const base::string16& user,
    112                                         const base::string16& password) {
    113   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    114   if (request_) {
    115     request_->SetAuth(net::AuthCredentials(user, password));
    116     ResourceDispatcherHost::Get()->ClearLoginDelegateForRequest(request_);
    117     request_ = NULL;
    118   }
    119   DeleteAuthHandlerSoon();
    120 }
    121 
    122 void AwLoginDelegate::OnRequestCancelled() {
    123   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    124   request_ = NULL;
    125   DeleteAuthHandlerSoon();
    126 }
    127 
    128 void AwLoginDelegate::DeleteAuthHandlerSoon() {
    129   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
    130     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
    131         base::Bind(&AwLoginDelegate::DeleteAuthHandlerSoon, this));
    132     return;
    133   }
    134   aw_http_auth_handler_.reset();
    135 }
    136 
    137 }  // namespace android_webview
    138