Bug 1867190 - Add prefs for PHC probablities r=glandium
[gecko.git] / toolkit / mozapps / defaultagent / DefaultPDF.cpp
blobe0a9f2e85a80a1e1e7eed9e9f7307378adf863e9
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/. */
7 #include "DefaultPDF.h"
9 #include <string>
11 #include <shlobj.h>
12 #include <winerror.h>
14 #include "EventLog.h"
16 #include "mozilla/Buffer.h"
17 #include "mozilla/RefPtr.h"
18 #include "mozilla/WinHeaderOnlyUtils.h"
19 #include "mozilla/Try.h"
21 namespace mozilla::default_agent {
23 constexpr std::string_view kUnknownPdfString = "";
25 constexpr std::pair<std::string_view, PDFHandler> kStringPdfHandlerMap[]{
26 {"error", PDFHandler::Error},
27 {kUnknownPdfString, PDFHandler::Unknown},
28 {"Firefox", PDFHandler::Firefox},
29 {"Microsoft Edge", PDFHandler::MicrosoftEdge},
30 {"Google Chrome", PDFHandler::GoogleChrome},
31 {"Adobe Acrobat", PDFHandler::AdobeAcrobat},
32 {"WPS", PDFHandler::WPS},
33 {"Nitro", PDFHandler::Nitro},
34 {"Foxit", PDFHandler::Foxit},
35 {"PDF-XChange", PDFHandler::PDFXChange},
36 {"Avast", PDFHandler::AvastSecureBrowser},
37 {"Sumatra", PDFHandler::SumatraPDF},
40 static_assert(mozilla::ArrayLength(kStringPdfHandlerMap) == kPDFHandlerCount);
42 std::string GetStringForPDFHandler(PDFHandler handler) {
43 for (const auto& [mapString, mapPdf] : kStringPdfHandlerMap) {
44 if (handler == mapPdf) {
45 return std::string{mapString};
49 return std::string(kUnknownPdfString);
52 PDFHandler GetPDFHandlerFromString(const std::string& pdfHandlerString) {
53 for (const auto& [mapString, mapPdfHandler] : kStringPdfHandlerMap) {
54 if (pdfHandlerString == mapString) {
55 return mapPdfHandler;
59 return PDFHandler::Unknown;
62 using PdfResult = mozilla::WindowsErrorResult<PDFHandler>;
64 static PdfResult GetDefaultPdf() {
65 RefPtr<IApplicationAssociationRegistration> pAAR;
66 HRESULT hr = CoCreateInstance(
67 CLSID_ApplicationAssociationRegistration, nullptr, CLSCTX_INPROC,
68 IID_IApplicationAssociationRegistration, getter_AddRefs(pAAR));
69 if (FAILED(hr)) {
70 LOG_ERROR(hr);
71 return PdfResult(mozilla::WindowsError::FromHResult(hr));
74 mozilla::UniquePtr<wchar_t, mozilla::CoTaskMemFreeDeleter> registeredApp;
76 wchar_t* rawRegisteredApp;
77 hr = pAAR->QueryCurrentDefault(L".pdf", AT_FILEEXTENSION, AL_EFFECTIVE,
78 &rawRegisteredApp);
79 if (FAILED(hr)) {
80 LOG_ERROR(hr);
81 return PdfResult(mozilla::WindowsError::FromHResult(hr));
83 registeredApp = mozilla::UniquePtr<wchar_t, mozilla::CoTaskMemFreeDeleter>{
84 rawRegisteredApp};
87 // Get the application Friendly Name associated to the found ProgID. This is
88 // sized to be larger than any observed or expected friendly names. Long
89 // friendly names tend to be in the form `[Company] [Viewer] [Variant]`
90 DWORD friendlyNameLen = 0;
91 hr = AssocQueryStringW(ASSOCF_NONE, ASSOCSTR_FRIENDLYAPPNAME,
92 registeredApp.get(), nullptr, nullptr,
93 &friendlyNameLen);
94 if (FAILED(hr)) {
95 LOG_ERROR(hr);
96 return PdfResult(mozilla::WindowsError::FromHResult(hr));
99 mozilla::Buffer<wchar_t> friendlyNameBuffer(friendlyNameLen);
100 hr = AssocQueryStringW(ASSOCF_NONE, ASSOCSTR_FRIENDLYAPPNAME,
101 registeredApp.get(), nullptr,
102 friendlyNameBuffer.Elements(), &friendlyNameLen);
103 if (FAILED(hr)) {
104 LOG_ERROR(hr);
105 return PdfResult(mozilla::WindowsError::FromHResult(hr));
108 constexpr std::pair<std::wstring_view, PDFHandler> kFriendlyNamePrefixes[] = {
109 {L"Firefox", PDFHandler::Firefox},
110 {L"Microsoft Edge", PDFHandler::MicrosoftEdge},
111 {L"Google Chrome", PDFHandler::GoogleChrome},
112 {L"Adobe", PDFHandler::AdobeAcrobat},
113 {L"Acrobat", PDFHandler::AdobeAcrobat},
114 {L"WPS", PDFHandler::WPS},
115 {L"Nitro", PDFHandler::Nitro},
116 {L"Foxit", PDFHandler::Foxit},
117 {L"PDF-XChange", PDFHandler::PDFXChange},
118 {L"Avast", PDFHandler::AvastSecureBrowser},
119 {L"Sumatra", PDFHandler::SumatraPDF},
122 // We should have one prefix for every PDF handler we track, with exceptions
123 // listed below.
124 // Error - removed; not a real pdf handler.
125 // Unknown - removed; not a real pdf handler.
126 // AdobeAcrobat - duplicate; `Adobe` and `Acrobat` prefixes are both seen in
127 // telemetry.
128 static_assert(mozilla::ArrayLength(kFriendlyNamePrefixes) ==
129 kPDFHandlerCount - 2 + 1);
131 PDFHandler resolvedHandler = PDFHandler::Unknown;
132 for (const auto& [knownHandlerSubstring, handlerEnum] :
133 kFriendlyNamePrefixes) {
134 if (!wcsnicmp(friendlyNameBuffer.Elements(), knownHandlerSubstring.data(),
135 knownHandlerSubstring.length())) {
136 resolvedHandler = handlerEnum;
137 break;
141 return resolvedHandler;
144 DefaultPdfResult GetDefaultPdfInfo() {
145 DefaultPdfInfo pdfInfo;
146 MOZ_TRY_VAR(pdfInfo.currentDefaultPdf, GetDefaultPdf());
148 return pdfInfo;
151 } // namespace mozilla::default_agent