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 http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/ipc/ProtocolUtils.h"
8 #include "mozilla/Logging.h"
9 #include "HandlerServiceParent.h"
10 #include "nsIHandlerService.h"
11 #include "nsIMIMEInfo.h"
12 #include "nsIMIMEService.h"
13 #include "ContentHandlerService.h"
14 #include "nsIExternalProtocolService.h"
15 #include "nsStringEnumerator.h"
16 #include "nsIMutableArray.h"
17 #include "nsCExternalHandlerService.h"
18 #include "nsComponentManagerUtils.h"
19 #include "nsServiceManagerUtils.h"
21 # include "unix/nsGNOMERegistry.h"
24 using mozilla::dom::ContentHandlerService
;
25 using mozilla::dom::HandlerApp
;
26 using mozilla::dom::HandlerInfo
;
27 using mozilla::dom::RemoteHandlerApp
;
31 class ProxyHandlerInfo final
: public nsIHandlerInfo
{
33 explicit ProxyHandlerInfo(const HandlerInfo
& aHandlerInfo
);
35 NS_DECL_NSIHANDLERINFO
;
37 nsTArray
<nsCString
>& Extensions() { return mHandlerInfo
.extensions(); }
40 ~ProxyHandlerInfo() {}
41 HandlerInfo mHandlerInfo
;
42 nsHandlerInfoAction mPrefAction
;
43 nsCOMPtr
<nsIMutableArray
> mPossibleApps
;
46 NS_IMPL_ISUPPORTS(ProxyHandlerInfo
, nsIHandlerInfo
)
48 ProxyHandlerInfo::ProxyHandlerInfo(const HandlerInfo
& aHandlerInfo
)
49 : mHandlerInfo(aHandlerInfo
),
50 mPrefAction(nsIHandlerInfo::alwaysAsk
),
51 mPossibleApps(do_CreateInstance(NS_ARRAY_CONTRACTID
)) {
52 for (auto& happ
: aHandlerInfo
.possibleApplicationHandlers()) {
53 mPossibleApps
->AppendElement(new RemoteHandlerApp(happ
));
57 /* readonly attribute ACString type; */
58 NS_IMETHODIMP
ProxyHandlerInfo::GetType(nsACString
& aType
) {
59 aType
.Assign(mHandlerInfo
.type());
63 /* attribute AString description; */
64 NS_IMETHODIMP
ProxyHandlerInfo::GetDescription(nsAString
& aDescription
) {
65 return NS_ERROR_NOT_IMPLEMENTED
;
67 NS_IMETHODIMP
ProxyHandlerInfo::SetDescription(const nsAString
& aDescription
) {
68 return NS_ERROR_NOT_IMPLEMENTED
;
71 /* attribute nsIHandlerApp preferredApplicationHandler; */
72 NS_IMETHODIMP
ProxyHandlerInfo::GetPreferredApplicationHandler(
73 nsIHandlerApp
** aPreferredApplicationHandler
) {
74 *aPreferredApplicationHandler
=
75 new RemoteHandlerApp(mHandlerInfo
.preferredApplicationHandler());
76 NS_IF_ADDREF(*aPreferredApplicationHandler
);
80 NS_IMETHODIMP
ProxyHandlerInfo::SetPreferredApplicationHandler(
81 nsIHandlerApp
* aApp
) {
83 nsString detailedDescription
;
86 aApp
->GetDetailedDescription(detailedDescription
);
89 mHandlerInfo
.preferredApplicationHandler() =
90 HandlerApp(name
, detailedDescription
);
94 /* readonly attribute nsIMutableArray possibleApplicationHandlers; */
95 NS_IMETHODIMP
ProxyHandlerInfo::GetPossibleApplicationHandlers(
96 nsIMutableArray
** aPossibleApplicationHandlers
) {
97 *aPossibleApplicationHandlers
= mPossibleApps
;
98 NS_IF_ADDREF(*aPossibleApplicationHandlers
);
102 /* readonly attribute boolean hasDefaultHandler; */
103 NS_IMETHODIMP
ProxyHandlerInfo::GetHasDefaultHandler(bool* aHasDefaultHandler
) {
104 return NS_ERROR_NOT_IMPLEMENTED
;
107 /* readonly attribute AString defaultDescription; */
108 NS_IMETHODIMP
ProxyHandlerInfo::GetDefaultDescription(
109 nsAString
& aDefaultDescription
) {
110 return NS_ERROR_NOT_IMPLEMENTED
;
113 NS_IMETHODIMP
ProxyHandlerInfo::GetDefaultExecutable(nsIFile
** aExecutable
) {
114 return NS_ERROR_NOT_IMPLEMENTED
;
117 /* void launchWithURI (in nsIURI aURI,
118 [optional] in BrowsingContext aBrowsingContext); */
119 NS_IMETHODIMP
ProxyHandlerInfo::LaunchWithURI(
120 nsIURI
* aURI
, mozilla::dom::BrowsingContext
* aBrowsingContext
) {
121 return NS_ERROR_NOT_IMPLEMENTED
;
124 /* attribute ProxyHandlerInfoAction preferredAction; */
125 NS_IMETHODIMP
ProxyHandlerInfo::GetPreferredAction(
126 nsHandlerInfoAction
* aPreferredAction
) {
127 *aPreferredAction
= mPrefAction
;
130 NS_IMETHODIMP
ProxyHandlerInfo::SetPreferredAction(
131 nsHandlerInfoAction aPreferredAction
) {
132 mHandlerInfo
.preferredAction() = aPreferredAction
;
133 mPrefAction
= aPreferredAction
;
137 /* attribute boolean alwaysAskBeforeHandling; */
138 NS_IMETHODIMP
ProxyHandlerInfo::GetAlwaysAskBeforeHandling(
139 bool* aAlwaysAskBeforeHandling
) {
140 *aAlwaysAskBeforeHandling
= mHandlerInfo
.alwaysAskBeforeHandling();
143 NS_IMETHODIMP
ProxyHandlerInfo::SetAlwaysAskBeforeHandling(
144 bool aAlwaysAskBeforeHandling
) {
145 mHandlerInfo
.alwaysAskBeforeHandling() = aAlwaysAskBeforeHandling
;
149 class ProxyMIMEInfo
: public nsIMIMEInfo
{
153 NS_FORWARD_NSIHANDLERINFO(mProxyHandlerInfo
->);
155 explicit ProxyMIMEInfo(const HandlerInfo
& aHandlerInfo
)
156 : mProxyHandlerInfo(new ProxyHandlerInfo(aHandlerInfo
)) {}
159 virtual ~ProxyMIMEInfo() {}
160 RefPtr
<ProxyHandlerInfo
> mProxyHandlerInfo
;
163 /* additional members */
166 NS_IMPL_ISUPPORTS(ProxyMIMEInfo
, nsIMIMEInfo
, nsIHandlerInfo
)
168 /* nsIUTF8StringEnumerator getFileExtensions (); */
169 NS_IMETHODIMP
ProxyMIMEInfo::GetFileExtensions(
170 nsIUTF8StringEnumerator
** _retval
) {
171 return NS_NewUTF8StringEnumerator(_retval
, &mProxyHandlerInfo
->Extensions(),
175 /* void setFileExtensions (in AUTF8String aExtensions); */
176 NS_IMETHODIMP
ProxyMIMEInfo::SetFileExtensions(const nsACString
& aExtensions
) {
177 return NS_ERROR_NOT_IMPLEMENTED
;
180 /* boolean extensionExists (in AUTF8String aExtension); */
181 NS_IMETHODIMP
ProxyMIMEInfo::ExtensionExists(const nsACString
& aExtension
,
183 *_retval
= mProxyHandlerInfo
->Extensions().Contains(
184 aExtension
, nsCaseInsensitiveCStringArrayComparator());
188 /* void appendExtension (in AUTF8String aExtension); */
189 NS_IMETHODIMP
ProxyMIMEInfo::AppendExtension(const nsACString
& aExtension
) {
190 if (!aExtension
.IsEmpty() &&
191 !mProxyHandlerInfo
->Extensions().Contains(
192 aExtension
, nsCaseInsensitiveCStringArrayComparator())) {
193 mProxyHandlerInfo
->Extensions().AppendElement(aExtension
);
198 /* attribute AUTF8String primaryExtension; */
199 NS_IMETHODIMP
ProxyMIMEInfo::GetPrimaryExtension(
200 nsACString
& aPrimaryExtension
) {
201 const auto& extensions
= mProxyHandlerInfo
->Extensions();
202 if (extensions
.IsEmpty()) {
203 aPrimaryExtension
.Truncate();
204 return NS_ERROR_FAILURE
;
206 aPrimaryExtension
= extensions
[0];
210 NS_IMETHODIMP
ProxyMIMEInfo::SetPrimaryExtension(
211 const nsACString
& aPrimaryExtension
) {
212 return NS_ERROR_NOT_IMPLEMENTED
;
215 /* readonly attribute ACString MIMEType; */
216 NS_IMETHODIMP
ProxyMIMEInfo::GetMIMEType(nsACString
& aMIMEType
) {
217 return NS_ERROR_NOT_IMPLEMENTED
;
220 /* boolean equals (in nsIMIMEInfo aMIMEInfo); */
221 NS_IMETHODIMP
ProxyMIMEInfo::Equals(nsIMIMEInfo
* aMIMEInfo
, bool* _retval
) {
222 return NS_ERROR_NOT_IMPLEMENTED
;
225 /* readonly attribute nsIArray possibleLocalHandlers; */
226 NS_IMETHODIMP
ProxyMIMEInfo::GetPossibleLocalHandlers(
227 nsIArray
** aPossibleLocalHandlers
) {
228 return NS_ERROR_NOT_IMPLEMENTED
;
231 /* void launchWithFile (in nsIFile aFile); */
232 NS_IMETHODIMP
ProxyMIMEInfo::LaunchWithFile(nsIFile
* aFile
) {
233 return NS_ERROR_NOT_IMPLEMENTED
;
236 /* boolean isCurrentAppOSDefault(); */
237 NS_IMETHODIMP
ProxyMIMEInfo::IsCurrentAppOSDefault(bool* _retval
) {
238 return NS_ERROR_NOT_IMPLEMENTED
;
241 static already_AddRefed
<nsIHandlerInfo
> WrapHandlerInfo(
242 const HandlerInfo
& aHandlerInfo
) {
243 nsCOMPtr
<nsIHandlerInfo
> info
;
244 if (aHandlerInfo
.isMIMEInfo()) {
245 info
= new ProxyMIMEInfo(aHandlerInfo
);
247 info
= new ProxyHandlerInfo(aHandlerInfo
);
249 return info
.forget();
252 } // anonymous namespace
254 HandlerServiceParent::HandlerServiceParent() {}
256 HandlerServiceParent::~HandlerServiceParent() {}
258 mozilla::ipc::IPCResult
HandlerServiceParent::RecvFillHandlerInfo(
259 const HandlerInfo
& aHandlerInfoData
, const nsACString
& aOverrideType
,
260 HandlerInfo
* handlerInfoData
) {
261 nsCOMPtr
<nsIHandlerInfo
> info(WrapHandlerInfo(aHandlerInfoData
));
262 nsCOMPtr
<nsIHandlerService
> handlerSvc
=
263 do_GetService(NS_HANDLERSERVICE_CONTRACTID
);
264 handlerSvc
->FillHandlerInfo(info
, aOverrideType
);
265 ContentHandlerService::nsIHandlerInfoToHandlerInfo(info
, handlerInfoData
);
269 mozilla::ipc::IPCResult
HandlerServiceParent::RecvGetMIMEInfoFromOS(
270 const nsACString
& aMIMEType
, const nsACString
& aExtension
, nsresult
* aRv
,
271 HandlerInfo
* aHandlerInfoData
, bool* aFound
) {
273 if (aMIMEType
.Length() > MAX_MIMETYPE_LENGTH
||
274 aExtension
.Length() > MAX_EXT_LENGTH
) {
279 nsCOMPtr
<nsIMIMEService
> mimeService
=
280 do_GetService(NS_MIMESERVICE_CONTRACTID
, aRv
);
281 if (NS_WARN_IF(NS_FAILED(*aRv
))) {
285 nsCOMPtr
<nsIMIMEInfo
> mimeInfo
;
286 *aRv
= mimeService
->GetMIMEInfoFromOS(aMIMEType
, aExtension
, aFound
,
287 getter_AddRefs(mimeInfo
));
288 if (NS_WARN_IF(NS_FAILED(*aRv
))) {
293 ContentHandlerService::nsIHandlerInfoToHandlerInfo(mimeInfo
,
300 mozilla::ipc::IPCResult
HandlerServiceParent::RecvExists(
301 const HandlerInfo
& aHandlerInfo
, bool* exists
) {
302 nsCOMPtr
<nsIHandlerInfo
> info(WrapHandlerInfo(aHandlerInfo
));
303 nsCOMPtr
<nsIHandlerService
> handlerSvc
=
304 do_GetService(NS_HANDLERSERVICE_CONTRACTID
);
305 handlerSvc
->Exists(info
, exists
);
309 mozilla::ipc::IPCResult
HandlerServiceParent::RecvExistsForProtocolOS(
310 const nsACString
& aProtocolScheme
, bool* aHandlerExists
) {
311 if (aProtocolScheme
.Length() > MAX_SCHEME_LENGTH
) {
312 *aHandlerExists
= false;
315 #ifdef MOZ_WIDGET_GTK
316 // Check the GNOME registry for a protocol handler
318 nsGNOMERegistry::HandlerExists(PromiseFlatCString(aProtocolScheme
).get());
320 *aHandlerExists
= false;
326 * Check if a handler exists for the provided protocol. Check the datastore
327 * first and then fallback to checking the OS for a handler.
329 mozilla::ipc::IPCResult
HandlerServiceParent::RecvExistsForProtocol(
330 const nsACString
& aProtocolScheme
, bool* aHandlerExists
) {
331 if (aProtocolScheme
.Length() > MAX_SCHEME_LENGTH
) {
332 *aHandlerExists
= false;
335 // Check the datastore and fallback to an OS check.
336 // ExternalProcotolHandlerExists() does the fallback.
338 nsCOMPtr
<nsIExternalProtocolService
> protoSvc
=
339 do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID
, &rv
);
340 if (NS_WARN_IF(NS_FAILED(rv
))) {
341 *aHandlerExists
= false;
344 rv
= protoSvc
->ExternalProtocolHandlerExists(
345 PromiseFlatCString(aProtocolScheme
).get(), aHandlerExists
);
347 if (NS_WARN_IF(NS_FAILED(rv
))) {
348 *aHandlerExists
= false;
353 mozilla::ipc::IPCResult
HandlerServiceParent::RecvGetTypeFromExtension(
354 const nsACString
& aFileExtension
, nsCString
* type
) {
355 if (aFileExtension
.Length() > MAX_EXT_LENGTH
) {
360 nsCOMPtr
<nsIHandlerService
> handlerSvc
=
361 do_GetService(NS_HANDLERSERVICE_CONTRACTID
, &rv
);
362 if (NS_WARN_IF(NS_FAILED(rv
))) {
366 rv
= handlerSvc
->GetTypeFromExtension(aFileExtension
, *type
);
367 mozilla::Unused
<< NS_WARN_IF(NS_FAILED(rv
));
372 mozilla::ipc::IPCResult
HandlerServiceParent::RecvGetApplicationDescription(
373 const nsACString
& aScheme
, nsresult
* aRv
, nsString
* aDescription
) {
374 if (aScheme
.Length() > MAX_SCHEME_LENGTH
) {
375 *aRv
= NS_ERROR_NOT_AVAILABLE
;
378 nsCOMPtr
<nsIExternalProtocolService
> protoSvc
=
379 do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID
);
380 NS_ASSERTION(protoSvc
, "No Helper App Service!");
381 *aRv
= protoSvc
->GetApplicationDescription(aScheme
, *aDescription
);
385 void HandlerServiceParent::ActorDestroy(ActorDestroyReason aWhy
) {}