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 /* void launchWithURI (in nsIURI aURI,
114 [optional] in BrowsingContext aBrowsingContext); */
115 NS_IMETHODIMP
ProxyHandlerInfo::LaunchWithURI(
116 nsIURI
* aURI
, mozilla::dom::BrowsingContext
* aBrowsingContext
) {
117 return NS_ERROR_NOT_IMPLEMENTED
;
120 /* attribute ProxyHandlerInfoAction preferredAction; */
121 NS_IMETHODIMP
ProxyHandlerInfo::GetPreferredAction(
122 nsHandlerInfoAction
* aPreferredAction
) {
123 *aPreferredAction
= mPrefAction
;
126 NS_IMETHODIMP
ProxyHandlerInfo::SetPreferredAction(
127 nsHandlerInfoAction aPreferredAction
) {
128 mHandlerInfo
.preferredAction() = aPreferredAction
;
129 mPrefAction
= aPreferredAction
;
133 /* attribute boolean alwaysAskBeforeHandling; */
134 NS_IMETHODIMP
ProxyHandlerInfo::GetAlwaysAskBeforeHandling(
135 bool* aAlwaysAskBeforeHandling
) {
136 *aAlwaysAskBeforeHandling
= mHandlerInfo
.alwaysAskBeforeHandling();
139 NS_IMETHODIMP
ProxyHandlerInfo::SetAlwaysAskBeforeHandling(
140 bool aAlwaysAskBeforeHandling
) {
141 mHandlerInfo
.alwaysAskBeforeHandling() = aAlwaysAskBeforeHandling
;
145 class ProxyMIMEInfo
: public nsIMIMEInfo
{
149 NS_FORWARD_NSIHANDLERINFO(mProxyHandlerInfo
->);
151 explicit ProxyMIMEInfo(const HandlerInfo
& aHandlerInfo
)
152 : mProxyHandlerInfo(new ProxyHandlerInfo(aHandlerInfo
)) {}
155 virtual ~ProxyMIMEInfo() {}
156 RefPtr
<ProxyHandlerInfo
> mProxyHandlerInfo
;
159 /* additional members */
162 NS_IMPL_ISUPPORTS(ProxyMIMEInfo
, nsIMIMEInfo
, nsIHandlerInfo
)
164 /* nsIUTF8StringEnumerator getFileExtensions (); */
165 NS_IMETHODIMP
ProxyMIMEInfo::GetFileExtensions(
166 nsIUTF8StringEnumerator
** _retval
) {
167 return NS_NewUTF8StringEnumerator(_retval
, &mProxyHandlerInfo
->Extensions(),
171 /* void setFileExtensions (in AUTF8String aExtensions); */
172 NS_IMETHODIMP
ProxyMIMEInfo::SetFileExtensions(const nsACString
& aExtensions
) {
173 return NS_ERROR_NOT_IMPLEMENTED
;
176 /* boolean extensionExists (in AUTF8String aExtension); */
177 NS_IMETHODIMP
ProxyMIMEInfo::ExtensionExists(const nsACString
& aExtension
,
179 *_retval
= mProxyHandlerInfo
->Extensions().Contains(
180 aExtension
, nsCaseInsensitiveCStringArrayComparator());
184 /* void appendExtension (in AUTF8String aExtension); */
185 NS_IMETHODIMP
ProxyMIMEInfo::AppendExtension(const nsACString
& aExtension
) {
186 if (!aExtension
.IsEmpty() &&
187 !mProxyHandlerInfo
->Extensions().Contains(
188 aExtension
, nsCaseInsensitiveCStringArrayComparator())) {
189 mProxyHandlerInfo
->Extensions().AppendElement(aExtension
);
194 /* attribute AUTF8String primaryExtension; */
195 NS_IMETHODIMP
ProxyMIMEInfo::GetPrimaryExtension(
196 nsACString
& aPrimaryExtension
) {
197 const auto& extensions
= mProxyHandlerInfo
->Extensions();
198 if (extensions
.IsEmpty()) {
199 aPrimaryExtension
.Truncate();
200 return NS_ERROR_FAILURE
;
202 aPrimaryExtension
= extensions
[0];
206 NS_IMETHODIMP
ProxyMIMEInfo::SetPrimaryExtension(
207 const nsACString
& aPrimaryExtension
) {
208 return NS_ERROR_NOT_IMPLEMENTED
;
211 /* readonly attribute ACString MIMEType; */
212 NS_IMETHODIMP
ProxyMIMEInfo::GetMIMEType(nsACString
& aMIMEType
) {
213 return NS_ERROR_NOT_IMPLEMENTED
;
216 /* boolean equals (in nsIMIMEInfo aMIMEInfo); */
217 NS_IMETHODIMP
ProxyMIMEInfo::Equals(nsIMIMEInfo
* aMIMEInfo
, bool* _retval
) {
218 return NS_ERROR_NOT_IMPLEMENTED
;
221 /* readonly attribute nsIArray possibleLocalHandlers; */
222 NS_IMETHODIMP
ProxyMIMEInfo::GetPossibleLocalHandlers(
223 nsIArray
** aPossibleLocalHandlers
) {
224 return NS_ERROR_NOT_IMPLEMENTED
;
227 /* void launchWithFile (in nsIFile aFile); */
228 NS_IMETHODIMP
ProxyMIMEInfo::LaunchWithFile(nsIFile
* aFile
) {
229 return NS_ERROR_NOT_IMPLEMENTED
;
232 /* boolean isCurrentAppOSDefault(); */
233 NS_IMETHODIMP
ProxyMIMEInfo::IsCurrentAppOSDefault(bool* _retval
) {
234 return NS_ERROR_NOT_IMPLEMENTED
;
237 static already_AddRefed
<nsIHandlerInfo
> WrapHandlerInfo(
238 const HandlerInfo
& aHandlerInfo
) {
239 nsCOMPtr
<nsIHandlerInfo
> info
;
240 if (aHandlerInfo
.isMIMEInfo()) {
241 info
= new ProxyMIMEInfo(aHandlerInfo
);
243 info
= new ProxyHandlerInfo(aHandlerInfo
);
245 return info
.forget();
248 } // anonymous namespace
250 HandlerServiceParent::HandlerServiceParent() {}
252 HandlerServiceParent::~HandlerServiceParent() {}
254 mozilla::ipc::IPCResult
HandlerServiceParent::RecvFillHandlerInfo(
255 const HandlerInfo
& aHandlerInfoData
, const nsACString
& aOverrideType
,
256 HandlerInfo
* handlerInfoData
) {
257 nsCOMPtr
<nsIHandlerInfo
> info(WrapHandlerInfo(aHandlerInfoData
));
258 nsCOMPtr
<nsIHandlerService
> handlerSvc
=
259 do_GetService(NS_HANDLERSERVICE_CONTRACTID
);
260 handlerSvc
->FillHandlerInfo(info
, aOverrideType
);
261 ContentHandlerService::nsIHandlerInfoToHandlerInfo(info
, handlerInfoData
);
265 mozilla::ipc::IPCResult
HandlerServiceParent::RecvGetMIMEInfoFromOS(
266 const nsACString
& aMIMEType
, const nsACString
& aExtension
, nsresult
* aRv
,
267 HandlerInfo
* aHandlerInfoData
, bool* aFound
) {
269 if (aMIMEType
.Length() > MAX_MIMETYPE_LENGTH
||
270 aExtension
.Length() > MAX_EXT_LENGTH
) {
275 nsCOMPtr
<nsIMIMEService
> mimeService
=
276 do_GetService(NS_MIMESERVICE_CONTRACTID
, aRv
);
277 if (NS_WARN_IF(NS_FAILED(*aRv
))) {
281 nsCOMPtr
<nsIMIMEInfo
> mimeInfo
;
282 *aRv
= mimeService
->GetMIMEInfoFromOS(aMIMEType
, aExtension
, aFound
,
283 getter_AddRefs(mimeInfo
));
284 if (NS_WARN_IF(NS_FAILED(*aRv
))) {
289 ContentHandlerService::nsIHandlerInfoToHandlerInfo(mimeInfo
,
296 mozilla::ipc::IPCResult
HandlerServiceParent::RecvExists(
297 const HandlerInfo
& aHandlerInfo
, bool* exists
) {
298 nsCOMPtr
<nsIHandlerInfo
> info(WrapHandlerInfo(aHandlerInfo
));
299 nsCOMPtr
<nsIHandlerService
> handlerSvc
=
300 do_GetService(NS_HANDLERSERVICE_CONTRACTID
);
301 handlerSvc
->Exists(info
, exists
);
305 mozilla::ipc::IPCResult
HandlerServiceParent::RecvExistsForProtocolOS(
306 const nsACString
& aProtocolScheme
, bool* aHandlerExists
) {
307 if (aProtocolScheme
.Length() > MAX_SCHEME_LENGTH
) {
308 *aHandlerExists
= false;
311 #ifdef MOZ_WIDGET_GTK
312 // Check the GNOME registry for a protocol handler
314 nsGNOMERegistry::HandlerExists(PromiseFlatCString(aProtocolScheme
).get());
316 *aHandlerExists
= false;
322 * Check if a handler exists for the provided protocol. Check the datastore
323 * first and then fallback to checking the OS for a handler.
325 mozilla::ipc::IPCResult
HandlerServiceParent::RecvExistsForProtocol(
326 const nsACString
& aProtocolScheme
, bool* aHandlerExists
) {
327 if (aProtocolScheme
.Length() > MAX_SCHEME_LENGTH
) {
328 *aHandlerExists
= false;
331 // Check the datastore and fallback to an OS check.
332 // ExternalProcotolHandlerExists() does the fallback.
334 nsCOMPtr
<nsIExternalProtocolService
> protoSvc
=
335 do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID
, &rv
);
336 if (NS_WARN_IF(NS_FAILED(rv
))) {
337 *aHandlerExists
= false;
340 rv
= protoSvc
->ExternalProtocolHandlerExists(
341 PromiseFlatCString(aProtocolScheme
).get(), aHandlerExists
);
343 if (NS_WARN_IF(NS_FAILED(rv
))) {
344 *aHandlerExists
= false;
349 mozilla::ipc::IPCResult
HandlerServiceParent::RecvGetTypeFromExtension(
350 const nsACString
& aFileExtension
, nsCString
* type
) {
351 if (aFileExtension
.Length() > MAX_EXT_LENGTH
) {
356 nsCOMPtr
<nsIHandlerService
> handlerSvc
=
357 do_GetService(NS_HANDLERSERVICE_CONTRACTID
, &rv
);
358 if (NS_WARN_IF(NS_FAILED(rv
))) {
362 rv
= handlerSvc
->GetTypeFromExtension(aFileExtension
, *type
);
363 mozilla::Unused
<< NS_WARN_IF(NS_FAILED(rv
));
368 mozilla::ipc::IPCResult
HandlerServiceParent::RecvGetApplicationDescription(
369 const nsACString
& aScheme
, nsresult
* aRv
, nsString
* aDescription
) {
370 if (aScheme
.Length() > MAX_SCHEME_LENGTH
) {
371 *aRv
= NS_ERROR_NOT_AVAILABLE
;
374 nsCOMPtr
<nsIExternalProtocolService
> protoSvc
=
375 do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID
);
376 NS_ASSERTION(protoSvc
, "No Helper App Service!");
377 *aRv
= protoSvc
->GetApplicationDescription(aScheme
, *aDescription
);
381 void HandlerServiceParent::ActorDestroy(ActorDestroyReason aWhy
) {}