Line data Source code
1 : /* This Source Code Form is subject to the terms of the Mozilla Public
2 : * License, v. 2.0. If a copy of the MPL was not distributed with this
3 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 :
5 : #include "PSMRunnable.h"
6 : #include "mozilla/Assertions.h"
7 : #include "mozilla/DebugOnly.h"
8 : #include "mozilla/RefPtr.h"
9 : #include "nsCOMPtr.h"
10 : #include "GeckoProfiler.h"
11 : #include "nsPKCS11Slot.h"
12 : #include "nsProtectedAuthThread.h"
13 : #include "nsReadableUtils.h"
14 : #include "nsString.h"
15 : #include "nsThreadUtils.h"
16 : #include "pk11func.h"
17 :
18 : using namespace mozilla;
19 : using namespace mozilla::psm;
20 :
21 0 : NS_IMPL_ISUPPORTS(nsProtectedAuthThread, nsIProtectedAuthThread)
22 :
23 0 : static void nsProtectedAuthThreadRunner(void *arg)
24 : {
25 0 : AutoProfilerRegisterThread registerThread("Protected Auth");
26 0 : NS_SetCurrentThreadName("Protected Auth");
27 :
28 0 : nsProtectedAuthThread *self = static_cast<nsProtectedAuthThread *>(arg);
29 0 : self->Run();
30 0 : }
31 :
32 0 : nsProtectedAuthThread::nsProtectedAuthThread()
33 : : mMutex("nsProtectedAuthThread.mMutex")
34 : , mIAmRunning(false)
35 : , mLoginReady(false)
36 : , mThreadHandle(nullptr)
37 : , mSlot(0)
38 0 : , mLoginResult(SECFailure)
39 : {
40 0 : }
41 :
42 0 : nsProtectedAuthThread::~nsProtectedAuthThread()
43 : {
44 0 : }
45 :
46 0 : NS_IMETHODIMP nsProtectedAuthThread::Login(nsIObserver *aObserver)
47 : {
48 0 : NS_ENSURE_ARG(aObserver);
49 :
50 0 : if (!mSlot)
51 : // We need pointer to the slot
52 0 : return NS_ERROR_FAILURE;
53 :
54 0 : MutexAutoLock lock(mMutex);
55 :
56 0 : if (mIAmRunning || mLoginReady) {
57 0 : return NS_OK;
58 : }
59 :
60 0 : if (aObserver) {
61 : // We must AddRef aObserver here on the main thread, because it probably
62 : // does not implement a thread-safe AddRef.
63 : mNotifyObserver = new NotifyObserverRunnable(aObserver,
64 0 : "operation-completed");
65 : }
66 :
67 0 : mIAmRunning = true;
68 :
69 0 : mThreadHandle = PR_CreateThread(PR_USER_THREAD, nsProtectedAuthThreadRunner, static_cast<void*>(this),
70 : PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
71 :
72 : // bool thread_started_ok = (threadHandle != nullptr);
73 : // we might want to return "thread started ok" to caller in the future
74 0 : MOZ_ASSERT(mThreadHandle,
75 : "Could not create nsProtectedAuthThreadRunner thread");
76 0 : return NS_OK;
77 : }
78 :
79 0 : NS_IMETHODIMP nsProtectedAuthThread::GetTokenName(nsAString &_retval)
80 : {
81 0 : MutexAutoLock lock(mMutex);
82 :
83 : // Get token name
84 0 : CopyUTF8toUTF16(nsDependentCString(PK11_GetTokenName(mSlot)), _retval);
85 :
86 0 : return NS_OK;
87 : }
88 :
89 0 : NS_IMETHODIMP nsProtectedAuthThread::GetSlot(nsIPKCS11Slot **_retval)
90 : {
91 0 : RefPtr<nsPKCS11Slot> slot;
92 : {
93 0 : MutexAutoLock lock(mMutex);
94 0 : slot = new nsPKCS11Slot(mSlot);
95 : }
96 :
97 0 : slot.forget(_retval);
98 0 : return NS_OK;
99 : }
100 :
101 0 : void nsProtectedAuthThread::SetParams(PK11SlotInfo* aSlot)
102 : {
103 0 : MutexAutoLock lock(mMutex);
104 :
105 0 : mSlot = (aSlot) ? PK11_ReferenceSlot(aSlot) : 0;
106 0 : }
107 :
108 0 : SECStatus nsProtectedAuthThread::GetResult()
109 : {
110 0 : return mLoginResult;
111 : }
112 :
113 0 : void nsProtectedAuthThread::Run(void)
114 : {
115 : // Login with null password. This call will also do C_Logout() but
116 : // it is harmless here
117 0 : mLoginResult = PK11_CheckUserPassword(mSlot, 0);
118 :
119 0 : nsCOMPtr<nsIRunnable> notifyObserver;
120 : {
121 0 : MutexAutoLock lock(mMutex);
122 :
123 0 : mLoginReady = true;
124 0 : mIAmRunning = false;
125 :
126 : // Forget the slot
127 0 : if (mSlot)
128 : {
129 0 : PK11_FreeSlot(mSlot);
130 0 : mSlot = 0;
131 : }
132 :
133 0 : notifyObserver.swap(mNotifyObserver);
134 : }
135 :
136 0 : if (notifyObserver) {
137 0 : DebugOnly<nsresult> rv = NS_DispatchToMainThread(notifyObserver);
138 0 : MOZ_ASSERT(NS_SUCCEEDED(rv),
139 : "Failed to dispatch protected auth observer to main thread");
140 : }
141 0 : }
142 :
143 0 : void nsProtectedAuthThread::Join()
144 : {
145 0 : if (!mThreadHandle)
146 0 : return;
147 :
148 0 : PR_JoinThread(mThreadHandle);
149 0 : mThreadHandle = nullptr;
150 : }
|