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"
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
) {
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
));
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
,
81 return PdfResult(mozilla::WindowsError::FromHResult(hr
));
83 registeredApp
= mozilla::UniquePtr
<wchar_t, mozilla::CoTaskMemFreeDeleter
>{
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,
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
);
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
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
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
;
141 return resolvedHandler
;
144 DefaultPdfResult
GetDefaultPdfInfo() {
145 DefaultPdfInfo pdfInfo
;
146 MOZ_TRY_VAR(pdfInfo
.currentDefaultPdf
, GetDefaultPdf());
151 } // namespace mozilla::default_agent