michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "pk11func.h" michael@0: #include "mozilla/DebugOnly.h" michael@0: #include "mozilla/RefPtr.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "PSMRunnable.h" michael@0: #include "nsString.h" michael@0: #include "nsReadableUtils.h" michael@0: #include "nsPKCS11Slot.h" michael@0: #include "nsProtectedAuthThread.h" michael@0: michael@0: using namespace mozilla; michael@0: using namespace mozilla::psm; michael@0: michael@0: NS_IMPL_ISUPPORTS(nsProtectedAuthThread, nsIProtectedAuthThread) michael@0: michael@0: static void nsProtectedAuthThreadRunner(void *arg) michael@0: { michael@0: PR_SetCurrentThreadName("Protected Auth"); michael@0: michael@0: nsProtectedAuthThread *self = static_cast(arg); michael@0: self->Run(); michael@0: } michael@0: michael@0: nsProtectedAuthThread::nsProtectedAuthThread() michael@0: : mMutex("nsProtectedAuthThread.mMutex") michael@0: , mIAmRunning(false) michael@0: , mLoginReady(false) michael@0: , mThreadHandle(nullptr) michael@0: , mSlot(0) michael@0: , mLoginResult(SECFailure) michael@0: { michael@0: NS_INIT_ISUPPORTS(); michael@0: } michael@0: michael@0: nsProtectedAuthThread::~nsProtectedAuthThread() michael@0: { michael@0: } michael@0: michael@0: NS_IMETHODIMP nsProtectedAuthThread::Login(nsIObserver *aObserver) michael@0: { michael@0: NS_ENSURE_ARG(aObserver); michael@0: michael@0: if (!mSlot) michael@0: // We need pointer to the slot michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: MutexAutoLock lock(mMutex); michael@0: michael@0: if (mIAmRunning || mLoginReady) { michael@0: return NS_OK; michael@0: } michael@0: michael@0: if (aObserver) { michael@0: // We must AddRef aObserver here on the main thread, because it probably michael@0: // does not implement a thread-safe AddRef. michael@0: mNotifyObserver = new NotifyObserverRunnable(aObserver, michael@0: "operation-completed"); michael@0: } michael@0: michael@0: mIAmRunning = true; michael@0: michael@0: mThreadHandle = PR_CreateThread(PR_USER_THREAD, nsProtectedAuthThreadRunner, static_cast(this), michael@0: PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); michael@0: michael@0: // bool thread_started_ok = (threadHandle != nullptr); michael@0: // we might want to return "thread started ok" to caller in the future michael@0: NS_ASSERTION(mThreadHandle, "Could not create nsProtectedAuthThreadRunner thread\n"); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP nsProtectedAuthThread::GetTokenName(nsAString &_retval) michael@0: { michael@0: MutexAutoLock lock(mMutex); michael@0: michael@0: // Get token name michael@0: CopyUTF8toUTF16(nsDependentCString(PK11_GetTokenName(mSlot)), _retval); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP nsProtectedAuthThread::GetSlot(nsIPKCS11Slot **_retval) michael@0: { michael@0: RefPtr slot; michael@0: { michael@0: MutexAutoLock lock(mMutex); michael@0: slot = new nsPKCS11Slot(mSlot); michael@0: } michael@0: michael@0: return CallQueryInterface (slot.get(), _retval); michael@0: } michael@0: michael@0: void nsProtectedAuthThread::SetParams(PK11SlotInfo* aSlot) michael@0: { michael@0: MutexAutoLock lock(mMutex); michael@0: michael@0: mSlot = (aSlot) ? PK11_ReferenceSlot(aSlot) : 0; michael@0: } michael@0: michael@0: SECStatus nsProtectedAuthThread::GetResult() michael@0: { michael@0: return mLoginResult; michael@0: } michael@0: michael@0: void nsProtectedAuthThread::Run(void) michael@0: { michael@0: // Login with null password. This call will also do C_Logout() but michael@0: // it is harmless here michael@0: mLoginResult = PK11_CheckUserPassword(mSlot, 0); michael@0: michael@0: nsCOMPtr notifyObserver; michael@0: { michael@0: MutexAutoLock lock(mMutex); michael@0: michael@0: mLoginReady = true; michael@0: mIAmRunning = false; michael@0: michael@0: // Forget the slot michael@0: if (mSlot) michael@0: { michael@0: PK11_FreeSlot(mSlot); michael@0: mSlot = 0; michael@0: } michael@0: michael@0: notifyObserver.swap(mNotifyObserver); michael@0: } michael@0: michael@0: if (notifyObserver) { michael@0: DebugOnly rv = NS_DispatchToMainThread(notifyObserver); michael@0: NS_ASSERTION(NS_SUCCEEDED(rv), michael@0: "failed to dispatch protected auth observer to main thread"); michael@0: } michael@0: } michael@0: michael@0: void nsProtectedAuthThread::Join() michael@0: { michael@0: if (!mThreadHandle) michael@0: return; michael@0: michael@0: PR_JoinThread(mThreadHandle); michael@0: mThreadHandle = nullptr; michael@0: }