Bug 1603309 - Make sure the Screenshots WebExtension is enabled during performance...
[gecko.git] / toolkit / xre / UntrustedModulesData.h
blobba48f7ed1a5c517c70b21760b5591f5fe7a02375
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 #ifndef mozilla_UntrustedModulesData_h
8 #define mozilla_UntrustedModulesData_h
10 #if defined(XP_WIN)
12 # include "ipc/IPCMessageUtils.h"
13 # include "mozilla/CombinedStacks.h"
14 # include "mozilla/DebugOnly.h"
15 # include "mozilla/Maybe.h"
16 # include "mozilla/RefPtr.h"
17 # include "mozilla/TypedEnumBits.h"
18 # include "mozilla/Unused.h"
19 # include "mozilla/Variant.h"
20 # include "mozilla/Vector.h"
21 # include "mozilla/WinHeaderOnlyUtils.h"
22 # include "nsCOMPtr.h"
23 # include "nsHashKeys.h"
24 # include "nsIFile.h"
25 # include "nsISupportsImpl.h"
26 # include "nsRefPtrHashtable.h"
27 # include "nsString.h"
28 # include "nsXULAppAPI.h"
30 namespace mozilla {
31 namespace glue {
32 struct EnhancedModuleLoadInfo;
33 } // namespace glue
35 enum class ModuleTrustFlags : uint32_t {
36 None = 0,
37 MozillaSignature = 1,
38 MicrosoftWindowsSignature = 2,
39 MicrosoftVersion = 4,
40 FirefoxDirectory = 8,
41 FirefoxDirectoryAndVersion = 0x10,
42 SystemDirectory = 0x20,
43 KeyboardLayout = 0x40,
44 JitPI = 0x80,
45 WinSxSDirectory = 0x100,
48 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(ModuleTrustFlags);
50 class VendorInfo final {
51 public:
52 enum class Source : uint32_t {
53 None,
54 Signature,
55 VersionInfo,
58 VendorInfo() : mSource(Source::None) {}
59 VendorInfo(const Source aSource, const nsAString& aVendor)
60 : mSource(aSource), mVendor(aVendor) {
61 MOZ_ASSERT(aSource != Source::None && !aVendor.IsEmpty());
64 Source mSource;
65 nsString mVendor;
68 class ModulesMap;
70 class ModuleRecord final {
71 public:
72 explicit ModuleRecord(const nsAString& aResolvedNtPath);
74 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ModuleRecord)
76 nsString mResolvedNtName;
77 nsCOMPtr<nsIFile> mResolvedDosName;
78 nsString mSanitizedDllName;
79 Maybe<ModuleVersion> mVersion;
80 Maybe<VendorInfo> mVendorInfo;
81 ModuleTrustFlags mTrustFlags;
83 explicit operator bool() const { return !mSanitizedDllName.IsEmpty(); }
84 bool IsXUL() const;
85 bool IsTrusted() const;
87 ModuleRecord(const ModuleRecord&) = delete;
88 ModuleRecord(ModuleRecord&&) = delete;
90 ModuleRecord& operator=(const ModuleRecord&) = delete;
91 ModuleRecord& operator=(ModuleRecord&&) = delete;
93 private:
94 ModuleRecord();
95 ~ModuleRecord() = default;
96 void GetVersionAndVendorInfo(const nsAString& aPath);
97 int32_t GetScoreThreshold() const;
99 friend struct ::IPC::ParamTraits<ModulesMap>;
103 * This type holds module path data using one of two internal representations.
104 * It may be created from either a nsTHashtable or a Vector, and may be
105 * serialized from either representation into a common format over the wire.
106 * Deserialization always uses the Vector representation.
108 struct ModulePaths final {
109 using SetType = nsTHashtable<nsStringCaseInsensitiveHashKey>;
110 using VecType = Vector<nsString>;
112 Variant<SetType, VecType> mModuleNtPaths;
114 template <typename T>
115 explicit ModulePaths(T&& aPaths)
116 : mModuleNtPaths(AsVariant(std::forward<T>(aPaths))) {}
118 ModulePaths() : mModuleNtPaths(VecType()) {}
120 ModulePaths(const ModulePaths& aOther) = delete;
121 ModulePaths(ModulePaths&& aOther) = default;
122 ModulePaths& operator=(const ModulePaths&) = delete;
123 ModulePaths& operator=(ModulePaths&&) = default;
126 class ProcessedModuleLoadEvent final {
127 public:
128 ProcessedModuleLoadEvent();
129 ProcessedModuleLoadEvent(glue::EnhancedModuleLoadInfo&& aModLoadInfo,
130 RefPtr<ModuleRecord>&& aModuleRecord);
132 explicit operator bool() const { return mModule && *mModule; }
133 bool IsXULLoad() const;
134 bool IsTrusted() const;
136 uint64_t mProcessUptimeMS;
137 Maybe<double> mLoadDurationMS;
138 DWORD mThreadId;
139 nsCString mThreadName;
140 nsString mRequestedDllName;
141 // We intentionally store mBaseAddress as part of the event and not the
142 // module, as relocation may cause it to change between loads. If so, we want
143 // to know about it.
144 uintptr_t mBaseAddress;
145 RefPtr<ModuleRecord> mModule;
147 ProcessedModuleLoadEvent(const ProcessedModuleLoadEvent&) = delete;
148 ProcessedModuleLoadEvent& operator=(const ProcessedModuleLoadEvent&) = delete;
150 ProcessedModuleLoadEvent(ProcessedModuleLoadEvent&&) = default;
151 ProcessedModuleLoadEvent& operator=(ProcessedModuleLoadEvent&&) = default;
153 private:
154 static Maybe<LONGLONG> ComputeQPCTimeStampForProcessCreation();
155 static uint64_t QPCTimeStampToProcessUptimeMilliseconds(
156 const LARGE_INTEGER& aTimeStamp);
159 // Declaring ModulesMap this way makes it much easier to forward declare than
160 // if we had used |using| or |typedef|.
161 class ModulesMap final
162 : public nsRefPtrHashtable<nsStringCaseInsensitiveHashKey, ModuleRecord> {
163 public:
164 ModulesMap()
165 : nsRefPtrHashtable<nsStringCaseInsensitiveHashKey, ModuleRecord>() {}
168 class UntrustedModulesData final {
169 public:
170 UntrustedModulesData()
171 : mProcessType(XRE_GetProcessType()),
172 mPid(::GetCurrentProcessId()),
173 mSanitizationFailures(0),
174 mTrustTestFailures(0) {}
176 UntrustedModulesData(UntrustedModulesData&&) = default;
177 UntrustedModulesData& operator=(UntrustedModulesData&&) = default;
179 UntrustedModulesData(const UntrustedModulesData&) = delete;
180 UntrustedModulesData& operator=(const UntrustedModulesData&) = delete;
182 explicit operator bool() const {
183 return !mEvents.empty() || mSanitizationFailures || mTrustTestFailures ||
184 mXULLoadDurationMS.isSome();
187 void AddNewLoads(const ModulesMap& aModulesMap,
188 Vector<ProcessedModuleLoadEvent>&& aEvents,
189 Vector<Telemetry::ProcessedStack>&& aStacks);
191 void Swap(UntrustedModulesData& aOther);
193 GeckoProcessType mProcessType;
194 DWORD mPid;
195 TimeDuration mElapsed;
196 ModulesMap mModules;
197 Vector<ProcessedModuleLoadEvent> mEvents;
198 Telemetry::CombinedStacks mStacks;
199 Maybe<double> mXULLoadDurationMS;
200 uint32_t mSanitizationFailures;
201 uint32_t mTrustTestFailures;
204 class ModulesMapResult final {
205 public:
206 ModulesMapResult() : mTrustTestFailures(0) {}
208 ModulesMapResult(const ModulesMapResult& aOther) = delete;
209 ModulesMapResult(ModulesMapResult&& aOther) = default;
210 ModulesMapResult& operator=(const ModulesMapResult& aOther) = delete;
211 ModulesMapResult& operator=(ModulesMapResult&& aOther) = default;
213 ModulesMap mModules;
214 uint32_t mTrustTestFailures;
217 } // namespace mozilla
219 namespace IPC {
221 template <>
222 struct ParamTraits<mozilla::ModuleVersion> {
223 typedef mozilla::ModuleVersion paramType;
225 static void Write(Message* aMsg, const paramType& aParam) {
226 aMsg->WriteUInt64(aParam.AsInteger());
229 static bool Read(const Message* aMsg, PickleIterator* aIter,
230 paramType* aResult) {
231 uint64_t ver;
232 if (!aMsg->ReadUInt64(aIter, &ver)) {
233 return false;
236 *aResult = ver;
237 return true;
241 template <>
242 struct ParamTraits<mozilla::VendorInfo> {
243 typedef mozilla::VendorInfo paramType;
245 static void Write(Message* aMsg, const paramType& aParam) {
246 aMsg->WriteUInt32(static_cast<uint32_t>(aParam.mSource));
247 WriteParam(aMsg, aParam.mVendor);
250 static bool Read(const Message* aMsg, PickleIterator* aIter,
251 paramType* aResult) {
252 uint32_t source;
253 if (!aMsg->ReadUInt32(aIter, &source)) {
254 return false;
257 aResult->mSource = static_cast<mozilla::VendorInfo::Source>(source);
259 if (!ReadParam(aMsg, aIter, &aResult->mVendor)) {
260 return false;
263 return true;
267 template <>
268 struct ParamTraits<mozilla::ModuleRecord> {
269 typedef mozilla::ModuleRecord paramType;
271 static void Write(Message* aMsg, const paramType& aParam) {
272 WriteParam(aMsg, aParam.mResolvedNtName);
274 nsAutoString resolvedDosName;
275 if (aParam.mResolvedDosName) {
276 mozilla::DebugOnly<nsresult> rv =
277 aParam.mResolvedDosName->GetPath(resolvedDosName);
278 MOZ_ASSERT(NS_SUCCEEDED(rv));
281 WriteParam(aMsg, resolvedDosName);
282 WriteParam(aMsg, aParam.mSanitizedDllName);
283 WriteParam(aMsg, aParam.mVersion);
284 WriteParam(aMsg, aParam.mVendorInfo);
285 aMsg->WriteUInt32(static_cast<uint32_t>(aParam.mTrustFlags));
288 static bool Read(const Message* aMsg, PickleIterator* aIter,
289 paramType* aResult) {
290 if (!ReadParam(aMsg, aIter, &aResult->mResolvedNtName)) {
291 return false;
294 nsAutoString resolvedDosName;
295 if (!ReadParam(aMsg, aIter, &resolvedDosName)) {
296 return false;
299 if (resolvedDosName.IsEmpty()) {
300 aResult->mResolvedDosName = nullptr;
301 } else if (NS_FAILED(NS_NewLocalFile(
302 resolvedDosName, false,
303 getter_AddRefs(aResult->mResolvedDosName)))) {
304 return false;
307 if (!ReadParam(aMsg, aIter, &aResult->mSanitizedDllName)) {
308 return false;
311 if (!ReadParam(aMsg, aIter, &aResult->mVersion)) {
312 return false;
315 if (!ReadParam(aMsg, aIter, &aResult->mVendorInfo)) {
316 return false;
319 uint32_t trustFlags;
320 if (!aMsg->ReadUInt32(aIter, &trustFlags)) {
321 return false;
324 aResult->mTrustFlags = static_cast<mozilla::ModuleTrustFlags>(trustFlags);
325 return true;
329 template <>
330 struct ParamTraits<mozilla::ModulesMap> {
331 typedef mozilla::ModulesMap paramType;
333 static void Write(Message* aMsg, const paramType& aParam) {
334 aMsg->WriteUInt32(aParam.Count());
336 for (auto iter = aParam.ConstIter(); !iter.Done(); iter.Next()) {
337 MOZ_RELEASE_ASSERT(iter.Data());
338 WriteParam(aMsg, iter.Key());
339 WriteParam(aMsg, *(iter.Data()));
343 static bool Read(const Message* aMsg, PickleIterator* aIter,
344 paramType* aResult) {
345 uint32_t count;
346 if (!ReadParam(aMsg, aIter, &count)) {
347 return false;
350 for (uint32_t current = 0; current < count; ++current) {
351 nsAutoString key;
352 if (!ReadParam(aMsg, aIter, &key) || key.IsEmpty()) {
353 return false;
356 RefPtr<mozilla::ModuleRecord> rec(new mozilla::ModuleRecord());
357 if (!ReadParam(aMsg, aIter, rec.get())) {
358 return false;
361 aResult->Put(key, rec.forget());
364 return true;
368 template <>
369 struct ParamTraits<mozilla::ModulePaths> {
370 typedef mozilla::ModulePaths paramType;
372 static void Write(Message* aMsg, const paramType& aParam) {
373 aParam.mModuleNtPaths.match(
374 [aMsg](const paramType::SetType& aSet) { WriteSet(aMsg, aSet); },
375 [aMsg](const paramType::VecType& aVec) { WriteVector(aMsg, aVec); });
378 static bool Read(const Message* aMsg, PickleIterator* aIter,
379 paramType* aResult) {
380 uint32_t len;
381 if (!aMsg->ReadUInt32(aIter, &len)) {
382 return false;
385 // As noted in the comments for ModulePaths, we only deserialize using the
386 // Vector representation.
387 auto& vec = aResult->mModuleNtPaths.as<paramType::VecType>();
388 if (!vec.reserve(len)) {
389 return false;
392 for (uint32_t idx = 0; idx < len; ++idx) {
393 nsString str;
394 if (!ReadParam(aMsg, aIter, &str)) {
395 return false;
398 if (!vec.emplaceBack(std::move(str))) {
399 return false;
403 return true;
406 private:
407 // NB: This function must write out the set in the same format as WriteVector
408 static void WriteSet(Message* aMsg, const paramType::SetType& aSet) {
409 aMsg->WriteUInt32(aSet.Count());
410 for (auto iter = aSet.ConstIter(); !iter.Done(); iter.Next()) {
411 WriteParam(aMsg, iter.Get()->GetKey());
415 // NB: This function must write out the vector in the same format as WriteSet
416 static void WriteVector(Message* aMsg, const paramType::VecType& aVec) {
417 aMsg->WriteUInt32(aVec.length());
418 for (auto const& item : aVec) {
419 WriteParam(aMsg, item);
424 template <>
425 struct ParamTraits<mozilla::UntrustedModulesData> {
426 typedef mozilla::UntrustedModulesData paramType;
428 static void Write(Message* aMsg, const paramType& aParam) {
429 aMsg->WriteUInt32(aParam.mProcessType);
430 aMsg->WriteULong(aParam.mPid);
431 WriteParam(aMsg, aParam.mElapsed);
432 WriteParam(aMsg, aParam.mModules);
434 aMsg->WriteUInt32(aParam.mEvents.length());
435 for (auto& evt : aParam.mEvents) {
436 WriteEvent(aMsg, evt);
439 WriteParam(aMsg, aParam.mStacks);
440 WriteParam(aMsg, aParam.mXULLoadDurationMS);
441 aMsg->WriteUInt32(aParam.mSanitizationFailures);
442 aMsg->WriteUInt32(aParam.mTrustTestFailures);
445 static bool Read(const Message* aMsg, PickleIterator* aIter,
446 paramType* aResult) {
447 uint32_t processType;
448 if (!aMsg->ReadUInt32(aIter, &processType)) {
449 return false;
452 aResult->mProcessType = static_cast<GeckoProcessType>(processType);
454 if (!aMsg->ReadULong(aIter, &aResult->mPid)) {
455 return false;
458 if (!ReadParam(aMsg, aIter, &aResult->mElapsed)) {
459 return false;
462 if (!ReadParam(aMsg, aIter, &aResult->mModules)) {
463 return false;
466 // We read mEvents manually so that we can use ReadEvent defined below.
467 uint32_t eventsLen;
468 if (!ReadParam(aMsg, aIter, &eventsLen)) {
469 return false;
472 if (!aResult->mEvents.resize(eventsLen)) {
473 return false;
476 for (uint32_t curEventIdx = 0; curEventIdx < eventsLen; ++curEventIdx) {
477 if (!ReadEvent(aMsg, aIter, &(aResult->mEvents[curEventIdx]),
478 aResult->mModules)) {
479 return false;
483 if (!ReadParam(aMsg, aIter, &aResult->mStacks)) {
484 return false;
487 if (!ReadParam(aMsg, aIter, &aResult->mXULLoadDurationMS)) {
488 return false;
491 if (!aMsg->ReadUInt32(aIter, &aResult->mSanitizationFailures)) {
492 return false;
495 if (!aMsg->ReadUInt32(aIter, &aResult->mTrustTestFailures)) {
496 return false;
499 return true;
502 private:
503 // Because ProcessedModuleLoadEvent depends on a hash table from
504 // UntrustedModulesData, we do its serialization as part of this
505 // specialization.
506 static void WriteEvent(Message* aMsg,
507 const mozilla::ProcessedModuleLoadEvent& aParam) {
508 aMsg->WriteUInt64(aParam.mProcessUptimeMS);
509 WriteParam(aMsg, aParam.mLoadDurationMS);
510 aMsg->WriteULong(aParam.mThreadId);
511 WriteParam(aMsg, aParam.mThreadName);
512 WriteParam(aMsg, aParam.mRequestedDllName);
513 WriteParam(aMsg, aParam.mBaseAddress);
515 // We don't write the ModuleRecord directly; we write its key into the
516 // UntrustedModulesData::mModules hash table.
517 MOZ_ASSERT(aParam.mModule && !aParam.mModule->mResolvedNtName.IsEmpty());
518 WriteParam(aMsg, aParam.mModule->mResolvedNtName);
521 // Because ProcessedModuleLoadEvent depends on a hash table from
522 // UntrustedModulesData, we do its deserialization as part of this
523 // specialization.
524 static bool ReadEvent(const Message* aMsg, PickleIterator* aIter,
525 mozilla::ProcessedModuleLoadEvent* aResult,
526 const mozilla::ModulesMap& aModulesMap) {
527 if (!aMsg->ReadUInt64(aIter, &aResult->mProcessUptimeMS)) {
528 return false;
531 if (!ReadParam(aMsg, aIter, &aResult->mLoadDurationMS)) {
532 return false;
535 if (!aMsg->ReadULong(aIter, &aResult->mThreadId)) {
536 return false;
539 if (!ReadParam(aMsg, aIter, &aResult->mThreadName)) {
540 return false;
543 if (!ReadParam(aMsg, aIter, &aResult->mRequestedDllName)) {
544 return false;
547 if (!ReadParam(aMsg, aIter, &aResult->mBaseAddress)) {
548 return false;
551 nsAutoString resolvedNtName;
552 if (!ReadParam(aMsg, aIter, &resolvedNtName)) {
553 return false;
556 aResult->mModule = aModulesMap.Get(resolvedNtName);
557 if (!aResult->mModule) {
558 return false;
561 return true;
565 template <>
566 struct ParamTraits<mozilla::ModulesMapResult> {
567 typedef mozilla::ModulesMapResult paramType;
569 static void Write(Message* aMsg, const paramType& aParam) {
570 WriteParam(aMsg, aParam.mModules);
571 aMsg->WriteUInt32(aParam.mTrustTestFailures);
574 static bool Read(const Message* aMsg, PickleIterator* aIter,
575 paramType* aResult) {
576 if (!ReadParam(aMsg, aIter, &aResult->mModules)) {
577 return false;
580 if (!aMsg->ReadUInt32(aIter, &aResult->mTrustTestFailures)) {
581 return false;
584 return true;
588 } // namespace IPC
590 #else // defined(XP_WIN)
592 namespace mozilla {
594 // For compiling IPDL on non-Windows platforms
595 using UntrustedModulesData = uint32_t;
596 using ModulePaths = uint32_t;
597 using ModulesMapResult = uint32_t;
599 } // namespace mozilla
601 #endif // defined(XP_WIN)
603 #endif // mozilla_UntrustedModulesData_h