Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "mozilla/dom/WebCryptoThreadPool.h"
8 :
9 : #include "mozilla/Services.h"
10 : #include "mozilla/StaticPtr.h"
11 : #include "nsComponentManagerUtils.h"
12 : #include "nsXPCOMCIDInternal.h"
13 : #include "nsXPCOMPrivate.h"
14 : #include "nsIObserverService.h"
15 : #include "nsIThreadPool.h"
16 :
17 : namespace mozilla {
18 : namespace dom {
19 :
20 3 : StaticRefPtr<WebCryptoThreadPool> gInstance;
21 :
22 6 : NS_IMPL_ISUPPORTS(WebCryptoThreadPool, nsIObserver)
23 :
24 : /* static */ void
25 3 : WebCryptoThreadPool::Initialize()
26 : {
27 3 : MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
28 3 : MOZ_ASSERT(!gInstance, "More than one instance!");
29 :
30 3 : gInstance = new WebCryptoThreadPool();
31 3 : NS_WARNING_ASSERTION(gInstance, "Failed create thread pool!");
32 :
33 3 : if (gInstance && NS_FAILED(gInstance->Init())) {
34 0 : NS_WARNING("Failed to initialize thread pool!");
35 0 : gInstance = nullptr;
36 : }
37 3 : }
38 :
39 : /* static */ nsresult
40 0 : WebCryptoThreadPool::Dispatch(nsIRunnable* aRunnable)
41 : {
42 0 : if (gInstance) {
43 0 : return gInstance->DispatchInternal(aRunnable);
44 : }
45 :
46 : // Fail if called on shutdown.
47 0 : return NS_ERROR_FAILURE;
48 : }
49 :
50 : nsresult
51 3 : WebCryptoThreadPool::Init()
52 : {
53 3 : MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
54 :
55 6 : nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
56 3 : NS_ENSURE_TRUE(obs, NS_ERROR_FAILURE);
57 :
58 : // Need this observer to know when to shut down the thread pool.
59 3 : return obs->AddObserver(this, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, false);
60 : }
61 :
62 : nsresult
63 0 : WebCryptoThreadPool::DispatchInternal(nsIRunnable* aRunnable)
64 : {
65 0 : MutexAutoLock lock(mMutex);
66 :
67 0 : if (!mPool) {
68 0 : NS_ENSURE_TRUE(EnsureNSSInitializedChromeOrContent(), NS_ERROR_FAILURE);
69 :
70 0 : nsCOMPtr<nsIThreadPool> pool(do_CreateInstance(NS_THREADPOOL_CONTRACTID));
71 0 : NS_ENSURE_TRUE(pool, NS_ERROR_FAILURE);
72 :
73 0 : nsresult rv = pool->SetName(NS_LITERAL_CSTRING("SubtleCrypto"));
74 0 : NS_ENSURE_SUCCESS(rv, rv);
75 :
76 0 : pool.swap(mPool);
77 : }
78 :
79 0 : return mPool->Dispatch(aRunnable, NS_DISPATCH_NORMAL);
80 : }
81 :
82 : void
83 0 : WebCryptoThreadPool::Shutdown()
84 : {
85 0 : MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
86 0 : MutexAutoLock lock(mMutex);
87 :
88 0 : if (mPool) {
89 0 : mPool->Shutdown();
90 : }
91 :
92 0 : nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
93 0 : NS_WARNING_ASSERTION(obs, "Failed to retrieve observer service!");
94 :
95 0 : if (obs) {
96 0 : if (NS_FAILED(obs->RemoveObserver(this,
97 : NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID))) {
98 0 : NS_WARNING("Failed to remove shutdown observer!");
99 : }
100 : }
101 0 : }
102 :
103 : NS_IMETHODIMP
104 0 : WebCryptoThreadPool::Observe(nsISupports* aSubject,
105 : const char* aTopic,
106 : const char16_t* aData)
107 : {
108 0 : MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
109 :
110 0 : if (gInstance) {
111 0 : gInstance->Shutdown();
112 0 : gInstance = nullptr;
113 : }
114 :
115 0 : return NS_OK;
116 : }
117 :
118 : } // namespace dom
119 9 : } // namespace mozilla
|