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 "ContentHandlerService.h"
13 #include "nsStringEnumerator.h"
15 # include "unix/nsGNOMERegistry.h"
18 using mozilla::dom::ContentHandlerService
;
19 using mozilla::dom::HandlerApp
;
20 using mozilla::dom::HandlerInfo
;
21 using mozilla::dom::RemoteHandlerApp
;
25 class ProxyHandlerInfo final
: public nsIHandlerInfo
{
27 explicit ProxyHandlerInfo(const HandlerInfo
& aHandlerInfo
);
29 NS_DECL_NSIHANDLERINFO
;
31 nsTArray
<nsCString
>& Extensions() { return mHandlerInfo
.extensions(); }
34 ~ProxyHandlerInfo() {}
35 HandlerInfo mHandlerInfo
;
36 nsHandlerInfoAction mPrefAction
;
37 nsCOMPtr
<nsIMutableArray
> mPossibleApps
;
40 NS_IMPL_ISUPPORTS(ProxyHandlerInfo
, nsIHandlerInfo
)
42 ProxyHandlerInfo::ProxyHandlerInfo(const HandlerInfo
& aHandlerInfo
)
43 : mHandlerInfo(aHandlerInfo
),
44 mPrefAction(nsIHandlerInfo::alwaysAsk
),
45 mPossibleApps(do_CreateInstance(NS_ARRAY_CONTRACTID
)) {
46 for (auto& happ
: aHandlerInfo
.possibleApplicationHandlers()) {
47 mPossibleApps
->AppendElement(new RemoteHandlerApp(happ
));
51 /* readonly attribute ACString type; */
52 NS_IMETHODIMP
ProxyHandlerInfo::GetType(nsACString
& aType
) {
53 aType
.Assign(mHandlerInfo
.type());
57 /* attribute AString description; */
58 NS_IMETHODIMP
ProxyHandlerInfo::GetDescription(nsAString
& aDescription
) {
59 return NS_ERROR_NOT_IMPLEMENTED
;
61 NS_IMETHODIMP
ProxyHandlerInfo::SetDescription(const nsAString
& aDescription
) {
62 return NS_ERROR_NOT_IMPLEMENTED
;
65 /* attribute nsIHandlerApp preferredApplicationHandler; */
66 NS_IMETHODIMP
ProxyHandlerInfo::GetPreferredApplicationHandler(
67 nsIHandlerApp
** aPreferredApplicationHandler
) {
68 *aPreferredApplicationHandler
=
69 new RemoteHandlerApp(mHandlerInfo
.preferredApplicationHandler());
70 NS_IF_ADDREF(*aPreferredApplicationHandler
);
74 NS_IMETHODIMP
ProxyHandlerInfo::SetPreferredApplicationHandler(
75 nsIHandlerApp
* aApp
) {
77 nsString detailedDescription
;
80 aApp
->GetDetailedDescription(detailedDescription
);
83 mHandlerInfo
.preferredApplicationHandler() =
84 HandlerApp(name
, detailedDescription
);
88 /* readonly attribute nsIMutableArray possibleApplicationHandlers; */
89 NS_IMETHODIMP
ProxyHandlerInfo::GetPossibleApplicationHandlers(
90 nsIMutableArray
** aPossibleApplicationHandlers
) {
91 *aPossibleApplicationHandlers
= mPossibleApps
;
92 NS_IF_ADDREF(*aPossibleApplicationHandlers
);
96 /* readonly attribute boolean hasDefaultHandler; */
97 NS_IMETHODIMP
ProxyHandlerInfo::GetHasDefaultHandler(bool* aHasDefaultHandler
) {
98 return NS_ERROR_NOT_IMPLEMENTED
;
101 /* readonly attribute AString defaultDescription; */
102 NS_IMETHODIMP
ProxyHandlerInfo::GetDefaultDescription(
103 nsAString
& aDefaultDescription
) {
104 return NS_ERROR_NOT_IMPLEMENTED
;
107 /* void launchWithURI (in nsIURI aURI,
108 [optional] in BrowsingContext aBrowsingContext); */
109 NS_IMETHODIMP
ProxyHandlerInfo::LaunchWithURI(
110 nsIURI
* aURI
, mozilla::dom::BrowsingContext
* aBrowsingContext
) {
111 return NS_ERROR_NOT_IMPLEMENTED
;
114 /* attribute ProxyHandlerInfoAction preferredAction; */
115 NS_IMETHODIMP
ProxyHandlerInfo::GetPreferredAction(
116 nsHandlerInfoAction
* aPreferredAction
) {
117 *aPreferredAction
= mPrefAction
;
120 NS_IMETHODIMP
ProxyHandlerInfo::SetPreferredAction(
121 nsHandlerInfoAction aPreferredAction
) {
122 mHandlerInfo
.preferredAction() = aPreferredAction
;
123 mPrefAction
= aPreferredAction
;
127 /* attribute boolean alwaysAskBeforeHandling; */
128 NS_IMETHODIMP
ProxyHandlerInfo::GetAlwaysAskBeforeHandling(
129 bool* aAlwaysAskBeforeHandling
) {
130 *aAlwaysAskBeforeHandling
= mHandlerInfo
.alwaysAskBeforeHandling();
133 NS_IMETHODIMP
ProxyHandlerInfo::SetAlwaysAskBeforeHandling(
134 bool aAlwaysAskBeforeHandling
) {
135 mHandlerInfo
.alwaysAskBeforeHandling() = aAlwaysAskBeforeHandling
;
139 class ProxyMIMEInfo
: public nsIMIMEInfo
{
143 NS_FORWARD_NSIHANDLERINFO(mProxyHandlerInfo
->);
145 explicit ProxyMIMEInfo(const HandlerInfo
& aHandlerInfo
)
146 : mProxyHandlerInfo(new ProxyHandlerInfo(aHandlerInfo
)) {}
149 virtual ~ProxyMIMEInfo() {}
150 RefPtr
<ProxyHandlerInfo
> mProxyHandlerInfo
;
153 /* additional members */
156 NS_IMPL_ISUPPORTS(ProxyMIMEInfo
, nsIMIMEInfo
, nsIHandlerInfo
)
158 /* nsIUTF8StringEnumerator getFileExtensions (); */
159 NS_IMETHODIMP
ProxyMIMEInfo::GetFileExtensions(
160 nsIUTF8StringEnumerator
** _retval
) {
161 return NS_NewUTF8StringEnumerator(_retval
, &mProxyHandlerInfo
->Extensions(),
165 /* void setFileExtensions (in AUTF8String aExtensions); */
166 NS_IMETHODIMP
ProxyMIMEInfo::SetFileExtensions(const nsACString
& aExtensions
) {
167 return NS_ERROR_NOT_IMPLEMENTED
;
170 /* boolean extensionExists (in AUTF8String aExtension); */
171 NS_IMETHODIMP
ProxyMIMEInfo::ExtensionExists(const nsACString
& aExtension
,
173 *_retval
= mProxyHandlerInfo
->Extensions().Contains(
174 aExtension
, nsCaseInsensitiveCStringArrayComparator());
178 /* void appendExtension (in AUTF8String aExtension); */
179 NS_IMETHODIMP
ProxyMIMEInfo::AppendExtension(const nsACString
& aExtension
) {
180 if (!aExtension
.IsEmpty() &&
181 !mProxyHandlerInfo
->Extensions().Contains(
182 aExtension
, nsCaseInsensitiveCStringArrayComparator())) {
183 mProxyHandlerInfo
->Extensions().AppendElement(aExtension
);
188 /* attribute AUTF8String primaryExtension; */
189 NS_IMETHODIMP
ProxyMIMEInfo::GetPrimaryExtension(
190 nsACString
& aPrimaryExtension
) {
191 const auto& extensions
= mProxyHandlerInfo
->Extensions();
192 if (extensions
.IsEmpty()) {
193 aPrimaryExtension
.Truncate();
194 return NS_ERROR_FAILURE
;
196 aPrimaryExtension
= extensions
[0];
200 NS_IMETHODIMP
ProxyMIMEInfo::SetPrimaryExtension(
201 const nsACString
& aPrimaryExtension
) {
202 return NS_ERROR_NOT_IMPLEMENTED
;
205 /* readonly attribute ACString MIMEType; */
206 NS_IMETHODIMP
ProxyMIMEInfo::GetMIMEType(nsACString
& aMIMEType
) {
207 return NS_ERROR_NOT_IMPLEMENTED
;
210 /* boolean equals (in nsIMIMEInfo aMIMEInfo); */
211 NS_IMETHODIMP
ProxyMIMEInfo::Equals(nsIMIMEInfo
* aMIMEInfo
, bool* _retval
) {
212 return NS_ERROR_NOT_IMPLEMENTED
;
215 /* readonly attribute nsIArray possibleLocalHandlers; */
216 NS_IMETHODIMP
ProxyMIMEInfo::GetPossibleLocalHandlers(
217 nsIArray
** aPossibleLocalHandlers
) {
218 return NS_ERROR_NOT_IMPLEMENTED
;
221 /* void launchWithFile (in nsIFile aFile); */
222 NS_IMETHODIMP
ProxyMIMEInfo::LaunchWithFile(nsIFile
* aFile
) {
223 return NS_ERROR_NOT_IMPLEMENTED
;
226 /* boolean isCurrentAppOSDefault(); */
227 NS_IMETHODIMP
ProxyMIMEInfo::IsCurrentAppOSDefault(bool* _retval
) {
228 return NS_ERROR_NOT_IMPLEMENTED
;
231 static already_AddRefed
<nsIHandlerInfo
> WrapHandlerInfo(
232 const HandlerInfo
& aHandlerInfo
) {
233 nsCOMPtr
<nsIHandlerInfo
> info
;
234 if (aHandlerInfo
.isMIMEInfo()) {
235 info
= new ProxyMIMEInfo(aHandlerInfo
);
237 info
= new ProxyHandlerInfo(aHandlerInfo
);
239 return info
.forget();
242 } // anonymous namespace
244 HandlerServiceParent::HandlerServiceParent() {}
246 HandlerServiceParent::~HandlerServiceParent() {}
248 mozilla::ipc::IPCResult
HandlerServiceParent::RecvFillHandlerInfo(
249 const HandlerInfo
& aHandlerInfoData
, const nsCString
& aOverrideType
,
250 HandlerInfo
* handlerInfoData
) {
251 nsCOMPtr
<nsIHandlerInfo
> info(WrapHandlerInfo(aHandlerInfoData
));
252 nsCOMPtr
<nsIHandlerService
> handlerSvc
=
253 do_GetService(NS_HANDLERSERVICE_CONTRACTID
);
254 handlerSvc
->FillHandlerInfo(info
, aOverrideType
);
255 ContentHandlerService::nsIHandlerInfoToHandlerInfo(info
, handlerInfoData
);
259 mozilla::ipc::IPCResult
HandlerServiceParent::RecvGetMIMEInfoFromOS(
260 const nsCString
& aMIMEType
, const nsCString
& aExtension
, nsresult
* aRv
,
261 HandlerInfo
* aHandlerInfoData
, bool* aFound
) {
263 if (aMIMEType
.Length() > MAX_MIMETYPE_LENGTH
||
264 aExtension
.Length() > MAX_EXT_LENGTH
) {
269 nsCOMPtr
<nsIMIMEService
> mimeService
=
270 do_GetService(NS_MIMESERVICE_CONTRACTID
, aRv
);
271 if (NS_WARN_IF(NS_FAILED(*aRv
))) {
275 nsCOMPtr
<nsIMIMEInfo
> mimeInfo
;
276 *aRv
= mimeService
->GetMIMEInfoFromOS(aMIMEType
, aExtension
, aFound
,
277 getter_AddRefs(mimeInfo
));
278 if (NS_WARN_IF(NS_FAILED(*aRv
))) {
283 ContentHandlerService::nsIHandlerInfoToHandlerInfo(mimeInfo
,
290 mozilla::ipc::IPCResult
HandlerServiceParent::RecvExists(
291 const HandlerInfo
& aHandlerInfo
, bool* exists
) {
292 nsCOMPtr
<nsIHandlerInfo
> info(WrapHandlerInfo(aHandlerInfo
));
293 nsCOMPtr
<nsIHandlerService
> handlerSvc
=
294 do_GetService(NS_HANDLERSERVICE_CONTRACTID
);
295 handlerSvc
->Exists(info
, exists
);
299 mozilla::ipc::IPCResult
HandlerServiceParent::RecvExistsForProtocolOS(
300 const nsCString
& aProtocolScheme
, bool* aHandlerExists
) {
301 if (aProtocolScheme
.Length() > MAX_SCHEME_LENGTH
) {
302 *aHandlerExists
= false;
305 #ifdef MOZ_WIDGET_GTK
306 // Check the GNOME registry for a protocol handler
307 *aHandlerExists
= nsGNOMERegistry::HandlerExists(aProtocolScheme
.get());
309 *aHandlerExists
= false;
315 * Check if a handler exists for the provided protocol. Check the datastore
316 * first and then fallback to checking the OS for a handler.
318 mozilla::ipc::IPCResult
HandlerServiceParent::RecvExistsForProtocol(
319 const nsCString
& aProtocolScheme
, bool* aHandlerExists
) {
320 if (aProtocolScheme
.Length() > MAX_SCHEME_LENGTH
) {
321 *aHandlerExists
= false;
324 #if defined(XP_MACOSX) || defined(XP_WIN)
325 // Check the datastore and fallback to an OS check.
326 // ExternalProcotolHandlerExists() does the fallback.
328 nsCOMPtr
<nsIExternalProtocolService
> protoSvc
=
329 do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID
, &rv
);
330 if (NS_WARN_IF(NS_FAILED(rv
))) {
331 *aHandlerExists
= false;
334 rv
= protoSvc
->ExternalProtocolHandlerExists(aProtocolScheme
.get(),
337 if (NS_WARN_IF(NS_FAILED(rv
))) {
338 *aHandlerExists
= false;
341 MOZ_RELEASE_ASSERT(false, "No implementation on this platform.");
342 *aHandlerExists
= false;
347 mozilla::ipc::IPCResult
HandlerServiceParent::RecvGetTypeFromExtension(
348 const nsCString
& aFileExtension
, nsCString
* type
) {
349 if (aFileExtension
.Length() > MAX_EXT_LENGTH
) {
354 nsCOMPtr
<nsIHandlerService
> handlerSvc
=
355 do_GetService(NS_HANDLERSERVICE_CONTRACTID
, &rv
);
356 if (NS_WARN_IF(NS_FAILED(rv
))) {
360 rv
= handlerSvc
->GetTypeFromExtension(aFileExtension
, *type
);
361 mozilla::Unused
<< NS_WARN_IF(NS_FAILED(rv
));
366 mozilla::ipc::IPCResult
HandlerServiceParent::RecvGetApplicationDescription(
367 const nsCString
& aScheme
, nsresult
* aRv
, nsString
* aDescription
) {
368 if (aScheme
.Length() > MAX_SCHEME_LENGTH
) {
369 *aRv
= NS_ERROR_NOT_AVAILABLE
;
372 nsCOMPtr
<nsIExternalProtocolService
> protoSvc
=
373 do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID
);
374 NS_ASSERTION(protoSvc
, "No Helper App Service!");
375 *aRv
= protoSvc
->GetApplicationDescription(aScheme
, *aDescription
);
379 void HandlerServiceParent::ActorDestroy(ActorDestroyReason aWhy
) {}