• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2019 The Chromium Embedded Framework Authors. All rights
2 // reserved. Use of this source code is governed by a BSD-style license that can
3 // be found in the LICENSE file.
4 
5 #include "libcef/browser/net_service/login_delegate.h"
6 
7 #include "libcef/browser/browser_host_base.h"
8 #include "libcef/browser/net_service/browser_urlrequest_impl.h"
9 #include "libcef/browser/thread_util.h"
10 
11 #include "base/memory/scoped_refptr.h"
12 #include "base/threading/sequenced_task_runner_handle.h"
13 #include "content/public/browser/global_request_id.h"
14 #include "content/public/browser/web_contents.h"
15 
16 namespace net_service {
17 
18 namespace {
19 
20 class AuthCallbackImpl : public CefAuthCallback {
21  public:
AuthCallbackImpl(base::WeakPtr<LoginDelegate> delegate)22   explicit AuthCallbackImpl(base::WeakPtr<LoginDelegate> delegate)
23       : delegate_(delegate),
24         task_runner_(base::SequencedTaskRunnerHandle::Get()) {}
25 
26   AuthCallbackImpl(const AuthCallbackImpl&) = delete;
27   AuthCallbackImpl& operator=(const AuthCallbackImpl&) = delete;
28 
~AuthCallbackImpl()29   ~AuthCallbackImpl() override {
30     if (delegate_.MaybeValid()) {
31       // If |delegate_| isn't valid this will be a no-op.
32       task_runner_->PostTask(FROM_HERE,
33                              base::BindOnce(&LoginDelegate::Cancel, delegate_));
34     }
35   }
36 
Continue(const CefString & username,const CefString & password)37   void Continue(const CefString& username, const CefString& password) override {
38     if (!task_runner_->RunsTasksInCurrentSequence()) {
39       task_runner_->PostTask(
40           FROM_HERE, base::BindOnce(&AuthCallbackImpl::Continue, this, username,
41                                     password));
42       return;
43     }
44 
45     if (delegate_) {
46       delegate_->Continue(username, password);
47       delegate_ = nullptr;
48     }
49   }
50 
Cancel()51   void Cancel() override {
52     if (!task_runner_->RunsTasksInCurrentSequence()) {
53       task_runner_->PostTask(FROM_HERE,
54                              base::BindOnce(&AuthCallbackImpl::Cancel, this));
55       return;
56     }
57 
58     if (delegate_) {
59       delegate_->Cancel();
60       delegate_ = nullptr;
61     }
62   }
63 
64  private:
65   base::WeakPtr<LoginDelegate> delegate_;
66   scoped_refptr<base::SequencedTaskRunner> task_runner_;
67 
68   IMPLEMENT_REFCOUNTING(AuthCallbackImpl);
69 };
70 
RunCallbackOnIOThread(CefRefPtr<CefBrowserHostBase> browser,absl::optional<CefBrowserURLRequest::RequestInfo> url_request_info,const net::AuthChallengeInfo & auth_info,const GURL & origin_url,CefRefPtr<AuthCallbackImpl> callback_impl)71 void RunCallbackOnIOThread(
72     CefRefPtr<CefBrowserHostBase> browser,
73     absl::optional<CefBrowserURLRequest::RequestInfo> url_request_info,
74     const net::AuthChallengeInfo& auth_info,
75     const GURL& origin_url,
76     CefRefPtr<AuthCallbackImpl> callback_impl) {
77   CEF_REQUIRE_IOT();
78 
79   // TODO(network): After the old network code path is deleted move this
80   // callback to the BrowserURLRequest's context thread.
81   if (url_request_info) {
82     bool handled = url_request_info->second->GetAuthCredentials(
83         auth_info.is_proxy, auth_info.challenger.host(),
84         auth_info.challenger.port(), auth_info.realm, auth_info.scheme,
85         callback_impl.get());
86     if (handled) {
87       // The user will execute the callback, or the request will be canceled on
88       // AuthCallbackImpl destruction.
89       return;
90     }
91   }
92 
93   if (browser) {
94     CefRefPtr<CefClient> client = browser->GetClient();
95     if (client) {
96       CefRefPtr<CefRequestHandler> handler = client->GetRequestHandler();
97       if (handler) {
98         bool handled = handler->GetAuthCredentials(
99             browser.get(), origin_url.spec(), auth_info.is_proxy,
100             auth_info.challenger.host(), auth_info.challenger.port(),
101             auth_info.realm, auth_info.scheme, callback_impl.get());
102         if (handled) {
103           // The user will execute the callback, or the request will be canceled
104           // on AuthCallbackImpl destruction.
105           return;
106         }
107       }
108     }
109   }
110 
111   callback_impl->Cancel();
112 }
113 }  // namespace
114 
LoginDelegate(const net::AuthChallengeInfo & auth_info,content::WebContents * web_contents,const content::GlobalRequestID & request_id,const GURL & origin_url,LoginAuthRequiredCallback callback)115 LoginDelegate::LoginDelegate(const net::AuthChallengeInfo& auth_info,
116                              content::WebContents* web_contents,
117                              const content::GlobalRequestID& request_id,
118                              const GURL& origin_url,
119                              LoginAuthRequiredCallback callback)
120     : callback_(std::move(callback)), weak_ptr_factory_(this) {
121   CEF_REQUIRE_UIT();
122 
123   // May be nullptr for requests originating from CefURLRequest.
124   CefRefPtr<CefBrowserHostBase> browser;
125   if (web_contents) {
126     browser = CefBrowserHostBase::GetBrowserForContents(web_contents);
127   }
128 
129   // |callback| needs to be executed asynchronously.
130   CEF_POST_TASK(CEF_UIT, base::BindOnce(&LoginDelegate::Start,
131                                         weak_ptr_factory_.GetWeakPtr(), browser,
132                                         auth_info, request_id, origin_url));
133 }
134 
Continue(const CefString & username,const CefString & password)135 void LoginDelegate::Continue(const CefString& username,
136                              const CefString& password) {
137   CEF_REQUIRE_UIT();
138   if (!callback_.is_null()) {
139     std::move(callback_).Run(
140         net::AuthCredentials(username.ToString16(), password.ToString16()));
141   }
142 }
143 
Cancel()144 void LoginDelegate::Cancel() {
145   CEF_REQUIRE_UIT();
146   if (!callback_.is_null()) {
147     std::move(callback_).Run(absl::nullopt);
148   }
149 }
150 
Start(CefRefPtr<CefBrowserHostBase> browser,const net::AuthChallengeInfo & auth_info,const content::GlobalRequestID & request_id,const GURL & origin_url)151 void LoginDelegate::Start(CefRefPtr<CefBrowserHostBase> browser,
152                           const net::AuthChallengeInfo& auth_info,
153                           const content::GlobalRequestID& request_id,
154                           const GURL& origin_url) {
155   CEF_REQUIRE_UIT();
156 
157   auto url_request_info = CefBrowserURLRequest::FromRequestID(request_id);
158 
159   if (browser || url_request_info) {
160     // AuthCallbackImpl is bound to the current thread.
161     CefRefPtr<AuthCallbackImpl> callbackImpl =
162         new AuthCallbackImpl(weak_ptr_factory_.GetWeakPtr());
163 
164     // Execute callbacks on the IO thread to maintain the "old"
165     // network_delegate callback behaviour.
166     CEF_POST_TASK(CEF_IOT, base::BindOnce(&RunCallbackOnIOThread, browser,
167                                           url_request_info, auth_info,
168                                           origin_url, callbackImpl));
169   } else {
170     Cancel();
171   }
172 }
173 
174 }  // namespace net_service