no bug - Import translations from android-l10n r=release a=l10n CLOSED TREE
[gecko.git] / toolkit / xre / dllservices / DynamicBlocklistWriter.cpp
blob38a9972e94d71d065bca5c1bb287bb56f78172fa
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"
13 namespace mozilla {
14 #if ENABLE_TESTS
15 nsDependentString testEntryString(DynamicBlockList::kTestDll,
16 DynamicBlockList::kTestDllBytes /
17 sizeof(DynamicBlockList::kTestDll[0]));
18 #endif
20 bool ShouldWriteEntry(const nsAString& name) {
21 #if ENABLE_TESTS
22 return name != testEntryString;
23 #else
24 return true;
25 #endif
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()) {
38 return;
40 } else {
41 hasTestEntry = true;
45 uint32_t entriesToWrite = aBlocklist.Count();
46 if (hasTestEntry) {
47 entriesToWrite -= 1;
50 mStringBufferSize = payloadSize.value();
51 mArraySize = (entriesToWrite + 1) * sizeof(DllBlockInfo);
53 payloadSize += mArraySize;
54 if (!payloadSize.isValid()) {
55 return;
58 mStringBuffer = MakeUnique<uint8_t[]>(mStringBufferSize);
59 Unused << mArray.resize(entriesToWrite + 1); // aBlockEntries + sentinel
61 size_t currentStringOffset = 0;
62 size_t i = 0;
63 for (const nsAString& name : aBlocklist) {
64 if (!ShouldWriteEntry(name)) {
65 continue;
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
73 // in mName.Buffer
74 memcpy(mStringBuffer.get() + currentStringOffset, name.BeginReading(),
75 nameSize);
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;
82 ++i;
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));
100 nsresult rv;
101 nsCOMPtr<nsISafeOutputStream> safeStream = do_QueryInterface(stream, &rv);
102 if (NS_FAILED(rv)) {
103 return 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);
126 } else {
127 promise->MaybeReject(rv);
129 }));
132 void DynamicBlocklistWriter::Cancel() {
133 MOZ_ASSERT(NS_IsMainThread());
134 if (mPromise) {
135 mPromise->MaybeReject(NS_ERROR_ABORT);
139 } // namespace mozilla