1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
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 https://mozilla.org/MPL/2.0/. */
7 #include "mozilla/DynamicBlocklist.h"
8 #include "mozilla/LauncherRegistryInfo.h"
10 #include "nsISafeOutputStream.h"
11 #include "nsNetUtil.h"
15 nsDependentString
testEntryString(DynamicBlockList::kTestDll
,
16 DynamicBlockList::kTestDllBytes
/
17 sizeof(DynamicBlockList::kTestDll
[0]));
20 bool ShouldWriteEntry(const nsAString
& name
) {
22 return name
!= testEntryString
;
28 DynamicBlocklistWriter::DynamicBlocklistWriter(
29 RefPtr
<dom::Promise
> aPromise
,
30 const nsTHashSet
<nsStringCaseInsensitiveHashKey
>& aBlocklist
)
31 : mPromise(aPromise
), mArraySize(0), mStringBufferSize(0) {
32 CheckedUint32 payloadSize
;
33 bool hasTestEntry
= false;
34 for (const nsAString
& name
: aBlocklist
) {
35 if (ShouldWriteEntry(name
)) {
36 payloadSize
+= name
.Length() * sizeof(char16_t
);
37 if (!payloadSize
.isValid()) {
45 uint32_t entriesToWrite
= aBlocklist
.Count();
50 mStringBufferSize
= payloadSize
.value();
51 mArraySize
= (entriesToWrite
+ 1) * sizeof(DllBlockInfo
);
53 payloadSize
+= mArraySize
;
54 if (!payloadSize
.isValid()) {
58 mStringBuffer
= MakeUnique
<uint8_t[]>(mStringBufferSize
);
59 Unused
<< mArray
.resize(entriesToWrite
+ 1); // aBlockEntries + sentinel
61 size_t currentStringOffset
= 0;
63 for (const nsAString
& name
: aBlocklist
) {
64 if (!ShouldWriteEntry(name
)) {
67 const uint32_t nameSize
= name
.Length() * sizeof(char16_t
);
69 mArray
[i
].mMaxVersion
= DllBlockInfo::ALL_VERSIONS
;
70 mArray
[i
].mFlags
= DllBlockInfoFlags::FLAGS_DEFAULT
;
72 // Copy the module's name to the string buffer and store its offset
74 memcpy(mStringBuffer
.get() + currentStringOffset
, name
.BeginReading(),
76 mArray
[i
].mName
.Buffer
=
77 reinterpret_cast<wchar_t*>(mArraySize
+ currentStringOffset
);
78 // Only keep mName.Length and leave mName.MaximumLength to be zero
79 mArray
[i
].mName
.Length
= nameSize
;
81 currentStringOffset
+= nameSize
;
86 nsresult
DynamicBlocklistWriter::WriteToFile(const nsAString
& aName
) const {
87 nsCOMPtr
<nsIFile
> file
;
88 MOZ_TRY(NS_NewLocalFile(aName
, true, getter_AddRefs(file
)));
90 nsCOMPtr
<nsIOutputStream
> stream
;
91 MOZ_TRY(NS_NewSafeLocalFileOutputStream(getter_AddRefs(stream
), file
));
93 MOZ_TRY(WriteValue(stream
, kSignature
));
94 MOZ_TRY(WriteValue(stream
, kCurrentVersion
));
95 MOZ_TRY(WriteValue(stream
,
96 static_cast<uint32_t>(mArraySize
+ mStringBufferSize
)));
97 MOZ_TRY(WriteBuffer(stream
, mArray
.begin(), mArraySize
));
98 MOZ_TRY(WriteBuffer(stream
, mStringBuffer
.get(), mStringBufferSize
));
101 nsCOMPtr
<nsISafeOutputStream
> safeStream
= do_QueryInterface(stream
, &rv
);
106 return safeStream
->Finish();
109 void DynamicBlocklistWriter::Run() {
110 MOZ_ASSERT(!NS_IsMainThread());
112 nsresult rv
= NS_ERROR_ABORT
;
114 LauncherRegistryInfo regInfo
;
115 LauncherResult
<std::wstring
> blocklistFile
= regInfo
.GetBlocklistFileName();
116 if (blocklistFile
.isOk()) {
117 const wchar_t* rawBuffer
= blocklistFile
.inspect().c_str();
118 rv
= WriteToFile(nsDependentString(rawBuffer
));
121 NS_DispatchToMainThread(
122 // Don't capture mPromise by copy because we're not in the main thread
123 NS_NewRunnableFunction(__func__
, [promise
= std::move(mPromise
), rv
]() {
124 if (NS_SUCCEEDED(rv
)) {
125 promise
->MaybeResolve(JS::NullHandleValue
);
127 promise
->MaybeReject(rv
);
132 void DynamicBlocklistWriter::Cancel() {
133 MOZ_ASSERT(NS_IsMainThread());
135 mPromise
->MaybeReject(NS_ERROR_ABORT
);
139 } // namespace mozilla