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