Bug 1845017 - Disable the TestPHCExhaustion test r=glandium
[gecko.git] / uriloader / exthandler / HandlerServiceParent.cpp
blobab77657dd5f378af0955c43ef958a8abea620134
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"
20 #ifdef MOZ_WIDGET_GTK
21 # include "unix/nsGNOMERegistry.h"
22 #endif
24 using mozilla::dom::ContentHandlerService;
25 using mozilla::dom::HandlerApp;
26 using mozilla::dom::HandlerInfo;
27 using mozilla::dom::RemoteHandlerApp;
29 namespace {
31 class ProxyHandlerInfo final : public nsIHandlerInfo {
32 public:
33 explicit ProxyHandlerInfo(const HandlerInfo& aHandlerInfo);
34 NS_DECL_ISUPPORTS;
35 NS_DECL_NSIHANDLERINFO;
37 nsTArray<nsCString>& Extensions() { return mHandlerInfo.extensions(); }
39 protected:
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());
60 return NS_OK;
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);
77 return NS_OK;
80 NS_IMETHODIMP ProxyHandlerInfo::SetPreferredApplicationHandler(
81 nsIHandlerApp* aApp) {
82 nsString name;
83 nsString detailedDescription;
84 if (aApp) {
85 aApp->GetName(name);
86 aApp->GetDetailedDescription(detailedDescription);
89 mHandlerInfo.preferredApplicationHandler() =
90 HandlerApp(name, detailedDescription);
91 return NS_OK;
94 /* readonly attribute nsIMutableArray possibleApplicationHandlers; */
95 NS_IMETHODIMP ProxyHandlerInfo::GetPossibleApplicationHandlers(
96 nsIMutableArray** aPossibleApplicationHandlers) {
97 *aPossibleApplicationHandlers = mPossibleApps;
98 NS_IF_ADDREF(*aPossibleApplicationHandlers);
99 return NS_OK;
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;
124 return NS_OK;
126 NS_IMETHODIMP ProxyHandlerInfo::SetPreferredAction(
127 nsHandlerInfoAction aPreferredAction) {
128 mHandlerInfo.preferredAction() = aPreferredAction;
129 mPrefAction = aPreferredAction;
130 return NS_OK;
133 /* attribute boolean alwaysAskBeforeHandling; */
134 NS_IMETHODIMP ProxyHandlerInfo::GetAlwaysAskBeforeHandling(
135 bool* aAlwaysAskBeforeHandling) {
136 *aAlwaysAskBeforeHandling = mHandlerInfo.alwaysAskBeforeHandling();
137 return NS_OK;
139 NS_IMETHODIMP ProxyHandlerInfo::SetAlwaysAskBeforeHandling(
140 bool aAlwaysAskBeforeHandling) {
141 mHandlerInfo.alwaysAskBeforeHandling() = aAlwaysAskBeforeHandling;
142 return NS_OK;
145 class ProxyMIMEInfo : public nsIMIMEInfo {
146 public:
147 NS_DECL_ISUPPORTS
148 NS_DECL_NSIMIMEINFO
149 NS_FORWARD_NSIHANDLERINFO(mProxyHandlerInfo->);
151 explicit ProxyMIMEInfo(const HandlerInfo& aHandlerInfo)
152 : mProxyHandlerInfo(new ProxyHandlerInfo(aHandlerInfo)) {}
154 private:
155 virtual ~ProxyMIMEInfo() {}
156 RefPtr<ProxyHandlerInfo> mProxyHandlerInfo;
158 protected:
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(),
168 this);
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,
178 bool* _retval) {
179 *_retval = mProxyHandlerInfo->Extensions().Contains(
180 aExtension, nsCaseInsensitiveCStringArrayComparator());
181 return NS_OK;
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);
191 return NS_OK;
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];
203 return NS_OK;
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);
242 } else {
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);
262 return IPC_OK();
265 mozilla::ipc::IPCResult HandlerServiceParent::RecvGetMIMEInfoFromOS(
266 const nsACString& aMIMEType, const nsACString& aExtension, nsresult* aRv,
267 HandlerInfo* aHandlerInfoData, bool* aFound) {
268 *aFound = false;
269 if (aMIMEType.Length() > MAX_MIMETYPE_LENGTH ||
270 aExtension.Length() > MAX_EXT_LENGTH) {
271 *aRv = NS_OK;
272 return IPC_OK();
275 nsCOMPtr<nsIMIMEService> mimeService =
276 do_GetService(NS_MIMESERVICE_CONTRACTID, aRv);
277 if (NS_WARN_IF(NS_FAILED(*aRv))) {
278 return IPC_OK();
281 nsCOMPtr<nsIMIMEInfo> mimeInfo;
282 *aRv = mimeService->GetMIMEInfoFromOS(aMIMEType, aExtension, aFound,
283 getter_AddRefs(mimeInfo));
284 if (NS_WARN_IF(NS_FAILED(*aRv))) {
285 return IPC_OK();
288 if (mimeInfo) {
289 ContentHandlerService::nsIHandlerInfoToHandlerInfo(mimeInfo,
290 aHandlerInfoData);
293 return IPC_OK();
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);
302 return IPC_OK();
305 mozilla::ipc::IPCResult HandlerServiceParent::RecvExistsForProtocolOS(
306 const nsACString& aProtocolScheme, bool* aHandlerExists) {
307 if (aProtocolScheme.Length() > MAX_SCHEME_LENGTH) {
308 *aHandlerExists = false;
309 return IPC_OK();
311 #ifdef MOZ_WIDGET_GTK
312 // Check the GNOME registry for a protocol handler
313 *aHandlerExists =
314 nsGNOMERegistry::HandlerExists(PromiseFlatCString(aProtocolScheme).get());
315 #else
316 *aHandlerExists = false;
317 #endif
318 return IPC_OK();
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;
329 return IPC_OK();
331 // Check the datastore and fallback to an OS check.
332 // ExternalProcotolHandlerExists() does the fallback.
333 nsresult rv;
334 nsCOMPtr<nsIExternalProtocolService> protoSvc =
335 do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID, &rv);
336 if (NS_WARN_IF(NS_FAILED(rv))) {
337 *aHandlerExists = false;
338 return IPC_OK();
340 rv = protoSvc->ExternalProtocolHandlerExists(
341 PromiseFlatCString(aProtocolScheme).get(), aHandlerExists);
343 if (NS_WARN_IF(NS_FAILED(rv))) {
344 *aHandlerExists = false;
346 return IPC_OK();
349 mozilla::ipc::IPCResult HandlerServiceParent::RecvGetTypeFromExtension(
350 const nsACString& aFileExtension, nsCString* type) {
351 if (aFileExtension.Length() > MAX_EXT_LENGTH) {
352 return IPC_OK();
355 nsresult rv;
356 nsCOMPtr<nsIHandlerService> handlerSvc =
357 do_GetService(NS_HANDLERSERVICE_CONTRACTID, &rv);
358 if (NS_WARN_IF(NS_FAILED(rv))) {
359 return IPC_OK();
362 rv = handlerSvc->GetTypeFromExtension(aFileExtension, *type);
363 mozilla::Unused << NS_WARN_IF(NS_FAILED(rv));
365 return IPC_OK();
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;
372 return IPC_OK();
374 nsCOMPtr<nsIExternalProtocolService> protoSvc =
375 do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID);
376 NS_ASSERTION(protoSvc, "No Helper App Service!");
377 *aRv = protoSvc->GetApplicationDescription(aScheme, *aDescription);
378 return IPC_OK();
381 void HandlerServiceParent::ActorDestroy(ActorDestroyReason aWhy) {}