Bug 409280, nsIProtectedAuthThread is not embedding friendly Patch contributed by Christian Persch (GNOME) r=kengert, blocking1.9=mtschrep
authorkaie@kuix.de
Tue, 15 Jan 2008 14:41:52 -0800
changeset 10302 23678c787ef24774e34ee66e0db74dcd948c1d52
parent 10301 0b9eaef75a19ca77f7b5004655234652ccc1e657
child 10303 85e634b38dcd5e2f23be21096e1fd17c69ed6a60
push idunknown
push userunknown
push dateunknown
reviewerskengert
bugs409280
milestone1.9b3pre
Bug 409280, nsIProtectedAuthThread is not embedding friendly Patch contributed by Christian Persch (GNOME) r=kengert, blocking1.9=mtschrep
security/manager/pki/resources/content/protectedAuth.js
security/manager/ssl/public/nsIProtectedAuthThread.idl
security/manager/ssl/src/nsProtectedAuthThread.cpp
security/manager/ssl/src/nsProtectedAuthThread.h
--- a/security/manager/pki/resources/content/protectedAuth.js
+++ b/security/manager/pki/resources/content/protectedAuth.js
@@ -48,17 +48,24 @@ function onLoad()
     {
         var tokenName = protectedAuthThread.getTokenName();
 
         var tag = document.getElementById("tokenName");
         tag.setAttribute("value",tokenName);
 
         setCursor("wait");
   
-        protectedAuthThread.login(window);
+        var obs = {
+          observe : function protectedAuthListenerObserve(subject, topic, data) {
+            if (topic == "operation-completed")
+              window.close();
+          }
+        };
+        
+        protectedAuthThread.login(obs);
 
     } catch (exception)
     {
         window.close();
         return;
     }
 }
 
--- a/security/manager/ssl/public/nsIProtectedAuthThread.idl
+++ b/security/manager/ssl/public/nsIProtectedAuthThread.idl
@@ -30,39 +30,49 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.idl"
-#include "nsIDOMWindowInternal.idl"
+#include "nsIObserver.idl"
+#include "nsIPKCS11Slot.idl"
 
 /**
  * nsIProtectedAuthThread
  *  This is used to communicate with the thread login on to 
  *  a token with CKF_PROTECTED_AUTHENTICATION_PATH set.
  */
-[scriptable, uuid(45334489-3d30-47c6-920b-0a55a313aebf)]
+[scriptable, uuid(4bb27cb7-8984-4cee-8ce7-9b014c3d091b)]
 interface nsIProtectedAuthThread : nsISupports
 {
   /**
    * login - run the thread
    *   A user interface implementing this interface needs to
    *   call this method as soon as the message to the user is
    *   displayed. This will trigger login operation. No user 
    *   cancellation is possible during login operation.
+   *
+   *   When the login is done, the observe method of @observer will
+   *   be called on the UI thread with a topic of "login-finished"
+   *   and null data and subject.
    */
-  void login(in nsIDOMWindowInternal dialog);
+  void login(in nsIObserver observer);
+
+  /**
+   * The PKCS11 slot
+   */
+  readonly attribute nsIPKCS11Slot slot;
 
   /**
    * Gets token to be logged in name.
    */
-  wstring getTokenName();
+  AString getTokenName();
 };
 
 %{ C++
 // {45334489-3D30-47c6-920B-0A55A313AEBF}
 #define NS_PROTECTEDAUTHTHREAD_CID \
 { 0x45334489, 0x3d30, 0x47c6, { 0x92, 0x0b, 0x0a, 0x55, 0xa3, 0x13, 0xae, 0xbf } }
 #define NS_PROTECTEDAUTHTHREAD_CONTRACTID "@mozilla.org/security/protectedauththread;1"
 %}
--- a/security/manager/ssl/src/nsProtectedAuthThread.cpp
+++ b/security/manager/ssl/src/nsProtectedAuthThread.cpp
@@ -31,110 +31,117 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "pk11func.h"
 #include "nsCOMPtr.h"
+#include "nsAutoPtr.h"
 #include "nsProxiedService.h"
 #include "nsString.h"
 #include "nsReadableUtils.h"
+#include "nsPKCS11Slot.h"
 #include "nsProtectedAuthThread.h"
 
 NS_IMPL_THREADSAFE_ISUPPORTS1(nsProtectedAuthThread, nsIProtectedAuthThread)
 
 static void PR_CALLBACK nsProtectedAuthThreadRunner(void *arg)
 {
     nsProtectedAuthThread *self = static_cast<nsProtectedAuthThread *>(arg);
     self->Run();
 }
 
 nsProtectedAuthThread::nsProtectedAuthThread()
 : mMutex(nsnull)
-, mStatusDialogPtr(nsnull)
 , mIAmRunning(PR_FALSE)
-, mStatusDialogClosed(PR_FALSE)
+, mStatusObserverNotified(PR_FALSE)
 , mLoginReady(PR_FALSE)
 , mThreadHandle(nsnull)
 , mSlot(0)
 , mLoginResult(SECFailure)
 {
     NS_INIT_ISUPPORTS();
     mMutex = PR_NewLock();
 }
 
 nsProtectedAuthThread::~nsProtectedAuthThread()
 {
     if (mMutex)
         PR_DestroyLock(mMutex);
-
-    if (mStatusDialogPtr)
-    {
-        NS_RELEASE(mStatusDialogPtr);
-    }
 }
 
-NS_IMETHODIMP nsProtectedAuthThread::Login(nsIDOMWindowInternal *statusDialog)
+NS_IMETHODIMP nsProtectedAuthThread::Login(nsIObserver *aObserver)
 {
+    NS_ENSURE_ARG(aObserver);
+
     if (!mMutex)
         return NS_ERROR_FAILURE;
     
-    if (!statusDialog )
-        return NS_ERROR_FAILURE;
-
     if (!mSlot)
         // We need pointer to the slot
         return NS_ERROR_FAILURE;
-    
-    nsCOMPtr<nsIDOMWindowInternal> wi;
-    NS_GetProxyForObject( NS_PROXY_TO_MAIN_THREAD,
-                          nsIDOMWindowInternal::GetIID(),
-                          statusDialog,
-                          NS_PROXY_SYNC | NS_PROXY_ALWAYS,
-                          getter_AddRefs(wi));
+
+    nsCOMPtr<nsIObserver> observerProxy;
+    nsresult rv = NS_GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
+                                       NS_GET_IID(nsIObserver),
+                                       aObserver,
+                                       NS_PROXY_SYNC | NS_PROXY_ALWAYS,
+                                       getter_AddRefs(observerProxy));
+    if (NS_FAILED(rv))
+        return rv;
 
     PR_Lock(mMutex);
     
     if (mIAmRunning || mLoginReady) {
         PR_Unlock(mMutex);
         return NS_OK;
     }
 
-    mStatusDialogPtr = wi;
-    NS_ADDREF(mStatusDialogPtr);
-    wi = 0;
-    
+    observerProxy.swap(mStatusObserver);
     mIAmRunning = PR_TRUE;
     
     mThreadHandle = PR_CreateThread(PR_USER_THREAD, nsProtectedAuthThreadRunner, static_cast<void*>(this), 
         PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
     
     // bool thread_started_ok = (threadHandle != nsnull);
     // we might want to return "thread started ok" to caller in the future
     NS_ASSERTION(mThreadHandle, "Could not create nsProtectedAuthThreadRunner thread\n");
     
     PR_Unlock(mMutex);
     
     return NS_OK;
 }
 
-NS_IMETHODIMP nsProtectedAuthThread::GetTokenName(PRUnichar **_retval)
+NS_IMETHODIMP nsProtectedAuthThread::GetTokenName(nsAString &_retval)
 {
     PR_Lock(mMutex);
 
     // Get token name
-    *_retval = UTF8ToNewUnicode(nsDependentCString(PK11_GetTokenName(mSlot)));
+    CopyUTF8toUTF16(nsDependentCString(PK11_GetTokenName(mSlot)), _retval);
 
     PR_Unlock(mMutex);
 
     return NS_OK;
 }
 
+NS_IMETHODIMP nsProtectedAuthThread::GetSlot(nsIPKCS11Slot **_retval)
+{
+    PR_Lock(mMutex);
+
+    nsRefPtr<nsPKCS11Slot> slot = new nsPKCS11Slot(mSlot);
+
+    PR_Unlock(mMutex);
+
+    if (!slot)
+      return NS_ERROR_OUT_OF_MEMORY;
+
+    return CallQueryInterface (slot.get(), _retval);
+}
 
 void nsProtectedAuthThread::SetParams(PK11SlotInfo* aSlot)
 {
     PR_Lock(mMutex);
 
     mSlot = (aSlot) ? PK11_ReferenceSlot(aSlot) : 0;
     
     PR_Unlock(mMutex);
@@ -145,43 +152,43 @@ SECStatus nsProtectedAuthThread::GetResu
     return mLoginResult;
 }
 
 void nsProtectedAuthThread::Run(void)
 {
     // Login with null password. This call will also do C_Logout() but 
     // it is harmless here
     mLoginResult = PK11_CheckUserPassword(mSlot, 0);
-    
-    nsIDOMWindowInternal *windowToClose = 0;
+
+    nsIObserver *observer = nsnull;
     
     PR_Lock(mMutex);
     
     mLoginReady = PR_TRUE;
     mIAmRunning = PR_FALSE;
 
     // Forget the slot
     if (mSlot)
     {
         PK11_FreeSlot(mSlot);
         mSlot = 0;
     }
     
-    if (!mStatusDialogClosed)
+    if (!mStatusObserverNotified)
     {
-        windowToClose = mStatusDialogPtr;
+        observer = mStatusObserver;
     }
-        
-    mStatusDialogPtr = 0;
-    mStatusDialogClosed = PR_TRUE;
+
+    mStatusObserver = nsnull;
+    mStatusObserverNotified = PR_TRUE;
     
     PR_Unlock(mMutex);
     
-    if (windowToClose)
-        windowToClose->Close();
+    if (observer)
+        observer->Observe(nsnull, "operation-completed", nsnull);
 }
 
 void nsProtectedAuthThread::Join()
 {
     if (!mThreadHandle)
         return;
     
     PR_JoinThread(mThreadHandle);
--- a/security/manager/ssl/src/nsProtectedAuthThread.h
+++ b/security/manager/ssl/src/nsProtectedAuthThread.h
@@ -32,30 +32,31 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef NSPROTECTEDAUTHTHREAD_H_
 #define NSPROTECTEDAUTHTHREAD_H_
 
+#include <nsCOMPtr.h>
 #include "keyhi.h"
 #include "nspr.h"
 
 #include "nsIProtectedAuthThread.h"
 
 class nsProtectedAuthThread : public nsIProtectedAuthThread
 {
 private:
     PRLock      *mMutex;
 
-    nsIDOMWindowInternal*   mStatusDialogPtr;
+    nsCOMPtr<nsIObserver> mStatusObserver;
 
     PRBool      mIAmRunning;
-    PRBool      mStatusDialogClosed;
+    PRBool      mStatusObserverNotified;
     PRBool      mLoginReady;
 
     PRThread    *mThreadHandle;
 
     // Slot to do authentication on
     PK11SlotInfo*   mSlot;
 
     // Result of the authentication