Add login event for "app" module
authorCheng Zhao <zcbenz@gmail.com>
Wed, 28 Oct 2015 11:34:01 +0000 (19:34 +0800)
committerCheng Zhao <zcbenz@gmail.com>
Wed, 28 Oct 2015 11:54:59 +0000 (19:54 +0800)
atom/browser/api/atom_api_app.cc
atom/browser/api/atom_api_app.h
atom/browser/browser.cc
atom/browser/browser.h
atom/browser/browser_observer.h
atom/browser/login_handler.cc
atom/browser/login_handler.h

index c79dea9f7c5cd62c7682f4213d32b27c3fd6c730..436d76fb90225bf308db176027b5aaea7414f7ba 100644 (file)
 
 #include "atom/browser/api/atom_api_menu.h"
 #include "atom/browser/api/atom_api_session.h"
+#include "atom/browser/api/atom_api_web_contents.h"
 #include "atom/browser/atom_browser_context.h"
 #include "atom/browser/atom_browser_main_parts.h"
 #include "atom/browser/browser.h"
-#include "atom/browser/api/atom_api_web_contents.h"
+#include "atom/browser/login_handler.h"
 #include "atom/common/native_mate_converters/callback.h"
 #include "atom/common/native_mate_converters/file_path_converter.h"
 #include "atom/common/node_includes.h"
@@ -132,8 +133,6 @@ void OnClientCertificateSelected(
     v8::Isolate* isolate,
     std::shared_ptr<content::ClientCertificateDelegate> delegate,
     mate::Arguments* args) {
-  v8::Locker locker(isolate);
-  v8::HandleScope handle_scope(isolate);
   mate::Dictionary cert_data;
   if (!(args->Length() == 1 && args->GetNext(&cert_data))) {
     args->ThrowError();
@@ -147,10 +146,18 @@ void OnClientCertificateSelected(
       net::X509Certificate::CreateCertificateListFromBytes(
           encoded_data.data(), encoded_data.size(),
           net::X509Certificate::FORMAT_AUTO);
-
   delegate->ContinueWithCertificate(certs[0].get());
 }
 
+void PassLoginInformation(scoped_refptr<LoginHandler> login_handler,
+                          mate::Arguments* args) {
+  base::string16 username, password;
+  if (args->GetNext(&username) && args->GetNext(&password))
+    login_handler->Login(username, password);
+  else
+    login_handler->CancelAuth();
+}
+
 }  // namespace
 
 App::App() {
@@ -233,6 +240,16 @@ void App::OnSelectCertificate(
         cert_request_info->client_certs[0].get());
 }
 
+void App::OnLogin(LoginHandler* login_handler) {
+  bool prevent_default =
+      Emit("login", base::Bind(&PassLoginInformation,
+                               make_scoped_refptr(login_handler)));
+
+  // Default behavior is to alwasy cancel the auth.
+  if (!prevent_default)
+    login_handler->CancelAuth();
+}
+
 void App::OnGpuProcessCrashed(base::TerminationStatus exit_code) {
   Emit("gpu-process-crashed");
 }
index 94cd9bbc68f9982f6063d5f757568f77d17a90bf..63cda4447e322d50f4cbfc29305a0dd80ad687f9 100644 (file)
@@ -50,6 +50,7 @@ class App : public mate::EventEmitter,
       content::WebContents* web_contents,
       net::SSLCertRequestInfo* cert_request_info,
       scoped_ptr<content::ClientCertificateDelegate> delegate) override;
+  void OnLogin(LoginHandler* login_handler) override;
 
   // content::GpuDataManagerObserver:
   void OnGpuProcessCrashed(base::TerminationStatus exit_code) override;
index 79ebe91a87e65d3514add4dd2484e2473b0ce795..739921fda90f5b86b2ddc974e17179c46cd3b829 100644 (file)
@@ -134,6 +134,10 @@ void Browser::ClientCertificateSelector(
                                         delegate.Pass()));
 }
 
+void Browser::RequestLogin(LoginHandler* login_handler) {
+  FOR_EACH_OBSERVER(BrowserObserver, observers_, OnLogin(login_handler));
+}
+
 void Browser::NotifyAndShutdown() {
   if (is_shutdown_)
     return;
index bae281d4d370cde87327dfcbde7898c22ca36394..8719e18f3140779fea38193116e34d1e1e43a7d8 100644 (file)
@@ -29,6 +29,8 @@ class MenuModel;
 
 namespace atom {
 
+class LoginHandler;
+
 // This class is used for control application-wide operations.
 class Browser : public WindowListObserver {
  public:
@@ -122,6 +124,9 @@ class Browser : public WindowListObserver {
       net::SSLCertRequestInfo* cert_request_info,
       scoped_ptr<content::ClientCertificateDelegate> delegate);
 
+  // Request basic auth login.
+  void RequestLogin(LoginHandler* login_handler);
+
   void AddObserver(BrowserObserver* obs) {
     observers_.AddObserver(obs);
   }
index 45e86e620f847cf0f7e723026e155740b6c26b5a..7dccbfbac3c54fca83ca9f8ec4aee7269e3b85ac 100644 (file)
@@ -20,6 +20,8 @@ class SSLCertRequestInfo;
 
 namespace atom {
 
+class LoginHandler;
+
 class BrowserObserver {
  public:
   // The browser is about to close all windows.
@@ -57,6 +59,9 @@ class BrowserObserver {
       net::SSLCertRequestInfo* cert_request_info,
       scoped_ptr<content::ClientCertificateDelegate> delegate) {}
 
+  // The browser requests HTTP login.
+  virtual void OnLogin(LoginHandler* login_handler) {}
+
  protected:
   virtual ~BrowserObserver() {}
 };
index 1980cc133abcbe9ee8b25b499c64b59c5243b538..ededcd0c85138de293549ff2f8960e6325534b9b 100644 (file)
@@ -4,19 +4,76 @@
 
 #include "atom/browser/login_handler.h"
 
+#include "atom/browser/browser.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/resource_dispatcher_host.h"
 #include "net/base/auth.h"
+#include "net/url_request/url_request.h"
+
+using content::BrowserThread;
 
 namespace atom {
 
+namespace {
+
+// Helper to remove the ref from an net::URLRequest to the LoginHandler.
+// Should only be called from the IO thread, since it accesses an
+// net::URLRequest.
+void ResetLoginHandlerForRequest(net::URLRequest* request) {
+  content::ResourceDispatcherHost::Get()->ClearLoginDelegateForRequest(request);
+}
+
+}  // namespace
+
 LoginHandler::LoginHandler(net::AuthChallengeInfo* auth_info,
                            net::URLRequest* request)
-    : auth_info_(auth_info), request_(request), weak_factory_(this) {
+    : auth_info_(auth_info), request_(request) {
+  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+                          base::Bind(&Browser::RequestLogin,
+                                     base::Unretained(Browser::Get()),
+                                     make_scoped_refptr(this)));
 }
 
 LoginHandler::~LoginHandler() {
 }
 
+void LoginHandler::Login(const base::string16& username,
+                         const base::string16& password) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  BrowserThread::PostTask(
+      BrowserThread::IO, FROM_HERE,
+      base::Bind(&LoginHandler::DoLogin, this, username, password));
+}
+
+void LoginHandler::CancelAuth() {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+                          base::Bind(&LoginHandler::DoCancelAuth, this));
+}
+
 void LoginHandler::OnRequestCancelled() {
+  request_ = nullptr;
+}
+
+void LoginHandler::DoCancelAuth() {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  if (request_) {
+    request_->CancelAuth();
+    // Verify that CancelAuth doesn't destroy the request via our delegate.
+    DCHECK(request_ != nullptr);
+    ResetLoginHandlerForRequest(request_);
+  }
+}
+
+void LoginHandler::DoLogin(const base::string16& username,
+                           const base::string16& password) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  if (request_) {
+    request_->SetAuth(net::AuthCredentials(username, password));
+    ResetLoginHandlerForRequest(request_);
+  }
 }
 
 }  // namespace atom
index 421e2e43837dbb32d027a2515f1a34e2c2a23c06..077e4b6cf9509955fec29f938d8a724599117c7d 100644 (file)
@@ -5,7 +5,7 @@
 #ifndef ATOM_BROWSER_LOGIN_HANDLER_H_
 #define ATOM_BROWSER_LOGIN_HANDLER_H_
 
-#include "base/memory/weak_ptr.h"
+#include "base/strings/string16.h"
 #include "content/public/browser/resource_dispatcher_host_login_delegate.h"
 
 namespace net {
@@ -15,10 +15,17 @@ class URLRequest;
 
 namespace atom {
 
+// Handles the HTTP basic auth, must be created on IO thread.
 class LoginHandler : public content::ResourceDispatcherHostLoginDelegate {
  public:
   LoginHandler(net::AuthChallengeInfo* auth_info, net::URLRequest* request);
 
+  // The auth is cancelled, must be called on UI thread.
+  void CancelAuth();
+
+  // Login with |username| and |password|, must be called on UI thread.
+  void Login(const base::string16& username, const base::string16& password);
+
  protected:
   ~LoginHandler() override;
 
@@ -26,6 +33,10 @@ class LoginHandler : public content::ResourceDispatcherHostLoginDelegate {
   void OnRequestCancelled() override;
 
  private:
+  // Must be called on IO thread.
+  void DoCancelAuth();
+  void DoLogin(const base::string16& username, const base::string16& password);
+
   // Who/where/what asked for the authentication.
   scoped_refptr<net::AuthChallengeInfo> auth_info_;
 
@@ -33,8 +44,6 @@ class LoginHandler : public content::ResourceDispatcherHostLoginDelegate {
   // This should only be accessed on the IO loop.
   net::URLRequest* request_;
 
-  base::WeakPtrFactory<LoginHandler> weak_factory_;
-
   DISALLOW_COPY_AND_ASSIGN(LoginHandler);
 };