diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /uriloader/exthandler/android | |
parent | Initial commit. (diff) | |
download | firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'uriloader/exthandler/android')
8 files changed, 746 insertions, 0 deletions
diff --git a/uriloader/exthandler/android/nsAndroidHandlerApp.cpp b/uriloader/exthandler/android/nsAndroidHandlerApp.cpp new file mode 100644 index 0000000000..de9f6be509 --- /dev/null +++ b/uriloader/exthandler/android/nsAndroidHandlerApp.cpp @@ -0,0 +1,86 @@ +/* -*- Mode: c++; c-basic-offset: 2; tab-width: 20; indent-tabs-mode: nil; -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/java/GeckoAppShellWrappers.h" +#include "nsAndroidHandlerApp.h" + +using namespace mozilla; + +NS_IMPL_ISUPPORTS(nsAndroidHandlerApp, nsIHandlerApp, nsISharingHandlerApp) + +nsAndroidHandlerApp::nsAndroidHandlerApp(const nsAString& aName, + const nsAString& aDescription, + const nsAString& aPackageName, + const nsAString& aClassName, + const nsACString& aMimeType, + const nsAString& aAction) + : mName(aName), + mDescription(aDescription), + mPackageName(aPackageName), + mClassName(aClassName), + mMimeType(aMimeType), + mAction(aAction) {} + +nsAndroidHandlerApp::~nsAndroidHandlerApp() {} + +NS_IMETHODIMP +nsAndroidHandlerApp::GetName(nsAString& aName) { + aName.Assign(mName); + return NS_OK; +} + +NS_IMETHODIMP +nsAndroidHandlerApp::SetName(const nsAString& aName) { + mName.Assign(aName); + return NS_OK; +} + +NS_IMETHODIMP +nsAndroidHandlerApp::GetDetailedDescription(nsAString& aDescription) { + aDescription.Assign(mDescription); + return NS_OK; +} + +NS_IMETHODIMP +nsAndroidHandlerApp::SetDetailedDescription(const nsAString& aDescription) { + mDescription.Assign(aDescription); + + return NS_OK; +} + +NS_IMETHODIMP +nsAndroidHandlerApp::Equals(nsIHandlerApp* aHandlerApp, bool* aRetval) { + *aRetval = false; + if (!aHandlerApp) { + return NS_OK; + } + + nsAutoString name; + nsAutoString detailedDescription; + aHandlerApp->GetName(name); + aHandlerApp->GetDetailedDescription(detailedDescription); + + *aRetval = name.Equals(mName) && detailedDescription.Equals(mDescription); + return NS_OK; +} + +NS_IMETHODIMP +nsAndroidHandlerApp::LaunchWithURI( + nsIURI* aURI, mozilla::dom::BrowsingContext* aBrowsingContext) { + nsCString uriSpec; + aURI->GetSpec(uriSpec); + return java::GeckoAppShell::OpenUriExternal(uriSpec, mMimeType, mPackageName, + mClassName, mAction, u""_ns) + ? NS_OK + : NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsAndroidHandlerApp::Share(const nsAString& data, const nsAString& title) { + return java::GeckoAppShell::OpenUriExternal(data, mMimeType, mPackageName, + mClassName, mAction, u""_ns) + ? NS_OK + : NS_ERROR_FAILURE; +} diff --git a/uriloader/exthandler/android/nsAndroidHandlerApp.h b/uriloader/exthandler/android/nsAndroidHandlerApp.h new file mode 100644 index 0000000000..dab4042fd8 --- /dev/null +++ b/uriloader/exthandler/android/nsAndroidHandlerApp.h @@ -0,0 +1,33 @@ +/* -*- Mode: c++; c-basic-offset: 2; tab-width: 20; indent-tabs-mode: nil; -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsAndroidHandlerApp_h +#define nsAndroidHandlerApp_h + +#include "nsMIMEInfoImpl.h" +#include "nsISharingHandlerApp.h" + +class nsAndroidHandlerApp : public nsISharingHandlerApp { + public: + NS_DECL_ISUPPORTS + NS_DECL_NSIHANDLERAPP + NS_DECL_NSISHARINGHANDLERAPP + + nsAndroidHandlerApp(const nsAString& aName, const nsAString& aDescription, + const nsAString& aPackageName, + const nsAString& aClassName, const nsACString& aMimeType, + const nsAString& aAction); + + private: + virtual ~nsAndroidHandlerApp(); + + nsString mName; + nsString mDescription; + nsString mPackageName; + nsString mClassName; + nsCString mMimeType; + nsString mAction; +}; +#endif diff --git a/uriloader/exthandler/android/nsExternalURLHandlerService.cpp b/uriloader/exthandler/android/nsExternalURLHandlerService.cpp new file mode 100644 index 0000000000..60ccbbdfe9 --- /dev/null +++ b/uriloader/exthandler/android/nsExternalURLHandlerService.cpp @@ -0,0 +1,21 @@ +/* -*- Mode: c++; c-basic-offset: 2; tab-width: 20; indent-tabs-mode: nil; -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsExternalURLHandlerService.h" +#include "nsMIMEInfoAndroid.h" + +NS_IMPL_ISUPPORTS(nsExternalURLHandlerService, nsIExternalURLHandlerService) + +nsExternalURLHandlerService::nsExternalURLHandlerService() {} + +nsExternalURLHandlerService::~nsExternalURLHandlerService() {} + +NS_IMETHODIMP +nsExternalURLHandlerService::GetURLHandlerInfoFromOS(nsIURI* aURL, bool* found, + nsIHandlerInfo** info) { + // We don't want to get protocol handlers from the OS in GV; the app + // should take care of that in NavigationDelegate.onLoadRequest(). + return NS_ERROR_NOT_IMPLEMENTED; +} diff --git a/uriloader/exthandler/android/nsExternalURLHandlerService.h b/uriloader/exthandler/android/nsExternalURLHandlerService.h new file mode 100644 index 0000000000..18389c5286 --- /dev/null +++ b/uriloader/exthandler/android/nsExternalURLHandlerService.h @@ -0,0 +1,22 @@ +/* -*- Mode: c++; c-basic-offset: 2; tab-width: 20; indent-tabs-mode: nil; -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef NSEXTERNALURLHANDLERSERVICE_H +#define NSEXTERNALURLHANDLERSERVICE_H + +#include "nsIExternalURLHandlerService.h" + +class nsExternalURLHandlerService final : public nsIExternalURLHandlerService { + public: + NS_DECL_ISUPPORTS + NS_DECL_NSIEXTERNALURLHANDLERSERVICE + + nsExternalURLHandlerService(); + + private: + ~nsExternalURLHandlerService(); +}; + +#endif // NSEXTERNALURLHANDLERSERVICE_H diff --git a/uriloader/exthandler/android/nsMIMEInfoAndroid.cpp b/uriloader/exthandler/android/nsMIMEInfoAndroid.cpp new file mode 100644 index 0000000000..6d361d32c2 --- /dev/null +++ b/uriloader/exthandler/android/nsMIMEInfoAndroid.cpp @@ -0,0 +1,414 @@ +/* -*- Mode: c++; c-basic-offset: 2; tab-width: 20; indent-tabs-mode: nil; -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "nsMIMEInfoAndroid.h" +#include "AndroidBridge.h" +#include "nsAndroidHandlerApp.h" +#include "nsArrayUtils.h" +#include "nsISupportsUtils.h" +#include "nsStringEnumerator.h" +#include "nsNetUtil.h" +#include "mozilla/Utf8.h" + +using namespace mozilla; + +NS_IMPL_ISUPPORTS(nsMIMEInfoAndroid, nsIMIMEInfo, nsIHandlerInfo) + +NS_IMETHODIMP +nsMIMEInfoAndroid::LaunchDefaultWithFile(nsIFile* aFile) { + return LaunchWithFile(aFile); +} + +NS_IMETHODIMP +nsMIMEInfoAndroid::LoadUriInternal(nsIURI* aURI) { + nsCString uriSpec; + aURI->GetSpec(uriSpec); + + nsCString uriScheme; + aURI->GetScheme(uriScheme); + + nsAutoString mimeType; + if (mType.Equals(uriScheme) || mType.Equals(uriSpec)) { + mimeType.Truncate(); + } else { + CopyUTF8toUTF16(mType, mimeType); + } + + if (java::GeckoAppShell::OpenUriExternal(NS_ConvertUTF8toUTF16(uriSpec), + mimeType, u""_ns, u""_ns, u""_ns, + u""_ns)) { + return NS_OK; + } + return NS_ERROR_FAILURE; +} + +bool nsMIMEInfoAndroid::GetMimeInfoForMimeType(const nsACString& aMimeType, + nsMIMEInfoAndroid** aMimeInfo) { + RefPtr<nsMIMEInfoAndroid> info = new nsMIMEInfoAndroid(aMimeType); + mozilla::AndroidBridge* bridge = mozilla::AndroidBridge::Bridge(); + // we don't have access to the bridge, so just assume we can handle + // the mime type for now and let the system deal with it + if (!bridge) { + info.forget(aMimeInfo); + return false; + } + + nsIHandlerApp* systemDefault = nullptr; + + if (!IsUtf8(aMimeType)) return false; + + NS_ConvertUTF8toUTF16 mimeType(aMimeType); + + bridge->GetHandlersForMimeType(mimeType, info->mHandlerApps, &systemDefault); + + if (systemDefault) info->mPrefApp = systemDefault; + + nsAutoCString fileExt; + bridge->GetExtensionFromMimeType(aMimeType, fileExt); + info->SetPrimaryExtension(fileExt); + + uint32_t len; + info->mHandlerApps->GetLength(&len); + if (len == 1) { + info.forget(aMimeInfo); + return false; + } + + info.forget(aMimeInfo); + return true; +} + +bool nsMIMEInfoAndroid::GetMimeInfoForFileExt(const nsACString& aFileExt, + nsMIMEInfoAndroid** aMimeInfo) { + nsCString mimeType; + if (mozilla::AndroidBridge::Bridge()) + mozilla::AndroidBridge::Bridge()->GetMimeTypeFromExtensions(aFileExt, + mimeType); + + // "*/*" means that the bridge didn't know. + if (mimeType.Equals(nsDependentCString("*/*"), + nsCaseInsensitiveCStringComparator)) + return false; + + bool found = GetMimeInfoForMimeType(mimeType, aMimeInfo); + (*aMimeInfo)->SetPrimaryExtension(aFileExt); + return found; +} + +/** + * Returns MIME info for the aURL, which may contain the whole URL or only a + * protocol + */ +nsresult nsMIMEInfoAndroid::GetMimeInfoForURL(const nsACString& aURL, + bool* found, + nsIHandlerInfo** info) { + nsMIMEInfoAndroid* mimeinfo = new nsMIMEInfoAndroid(aURL); + NS_ADDREF(*info = mimeinfo); + *found = true; + + mozilla::AndroidBridge* bridge = mozilla::AndroidBridge::Bridge(); + if (!bridge) { + // we don't have access to the bridge, so just assume we can handle + // the protocol for now and let the system deal with it + return NS_OK; + } + + nsIHandlerApp* systemDefault = nullptr; + bridge->GetHandlersForURL(NS_ConvertUTF8toUTF16(aURL), mimeinfo->mHandlerApps, + &systemDefault); + + if (systemDefault) mimeinfo->mPrefApp = systemDefault; + + nsAutoCString fileExt; + nsAutoCString mimeType; + mimeinfo->GetType(mimeType); + bridge->GetExtensionFromMimeType(mimeType, fileExt); + mimeinfo->SetPrimaryExtension(fileExt); + + uint32_t len; + mimeinfo->mHandlerApps->GetLength(&len); + if (len == 1) { + // Code that calls this requires an object regardless if the OS has + // something for us, so we return the empty object. + *found = false; + return NS_OK; + } + + return NS_OK; +} + +NS_IMETHODIMP +nsMIMEInfoAndroid::GetType(nsACString& aType) { + aType.Assign(mType); + return NS_OK; +} + +NS_IMETHODIMP +nsMIMEInfoAndroid::GetDescription(nsAString& aDesc) { + aDesc.Assign(mDescription); + return NS_OK; +} + +NS_IMETHODIMP +nsMIMEInfoAndroid::SetDescription(const nsAString& aDesc) { + mDescription.Assign(aDesc); + return NS_OK; +} + +NS_IMETHODIMP +nsMIMEInfoAndroid::GetPreferredApplicationHandler(nsIHandlerApp** aApp) { + *aApp = mPrefApp; + NS_IF_ADDREF(*aApp); + return NS_OK; +} + +NS_IMETHODIMP +nsMIMEInfoAndroid::SetPreferredApplicationHandler(nsIHandlerApp* aApp) { + mPrefApp = aApp; + return NS_OK; +} + +NS_IMETHODIMP +nsMIMEInfoAndroid::GetPossibleApplicationHandlers( + nsIMutableArray** aHandlerApps) { + if (!mHandlerApps) mHandlerApps = do_CreateInstance(NS_ARRAY_CONTRACTID); + + if (!mHandlerApps) return NS_ERROR_OUT_OF_MEMORY; + + *aHandlerApps = mHandlerApps; + NS_IF_ADDREF(*aHandlerApps); + return NS_OK; +} + +NS_IMETHODIMP +nsMIMEInfoAndroid::GetHasDefaultHandler(bool* aHasDefault) { + uint32_t len; + *aHasDefault = false; + if (!mHandlerApps) return NS_OK; + + if (NS_FAILED(mHandlerApps->GetLength(&len))) return NS_OK; + + if (len == 0) return NS_OK; + + *aHasDefault = true; + return NS_OK; +} + +NS_IMETHODIMP +nsMIMEInfoAndroid::GetDefaultDescription(nsAString& aDesc) { + aDesc.Assign(u""_ns); + return NS_OK; +} + +NS_IMETHODIMP +nsMIMEInfoAndroid::LaunchWithURI( + nsIURI* aURI, mozilla::dom::BrowsingContext* aBrowsingContext) { + return mPrefApp->LaunchWithURI(aURI, aBrowsingContext); +} + +NS_IMETHODIMP +nsMIMEInfoAndroid::GetPreferredAction(nsHandlerInfoAction* aPrefAction) { + *aPrefAction = mPrefAction; + return NS_OK; +} + +NS_IMETHODIMP +nsMIMEInfoAndroid::SetPreferredAction(nsHandlerInfoAction aPrefAction) { + mPrefAction = aPrefAction; + return NS_OK; +} + +NS_IMETHODIMP +nsMIMEInfoAndroid::GetAlwaysAskBeforeHandling(bool* aAlwaysAsk) { + *aAlwaysAsk = mAlwaysAsk; + return NS_OK; +} + +NS_IMETHODIMP +nsMIMEInfoAndroid::SetAlwaysAskBeforeHandling(bool aAlwaysAsk) { + mAlwaysAsk = aAlwaysAsk; + return NS_OK; +} + +NS_IMETHODIMP +nsMIMEInfoAndroid::GetFileExtensions(nsIUTF8StringEnumerator** aResult) { + return NS_NewUTF8StringEnumerator(aResult, &mExtensions, this); +} + +NS_IMETHODIMP +nsMIMEInfoAndroid::SetFileExtensions(const nsACString& aExtensions) { + mExtensions.Clear(); + nsACString::const_iterator start, end; + aExtensions.BeginReading(start); + aExtensions.EndReading(end); + while (start != end) { + nsACString::const_iterator cursor = start; + mozilla::Unused << FindCharInReadable(',', cursor, end); + AddUniqueExtension(Substring(start, cursor)); + // If a comma was found, skip it for the next search. + start = cursor != end ? ++cursor : cursor; + } + return NS_OK; +} + +NS_IMETHODIMP +nsMIMEInfoAndroid::ExtensionExists(const nsACString& aExtension, + bool* aRetVal) { + NS_ASSERTION(!aExtension.IsEmpty(), "no extension"); + + nsCString mimeType; + if (mozilla::AndroidBridge::Bridge()) { + mozilla::AndroidBridge::Bridge()->GetMimeTypeFromExtensions(aExtension, + mimeType); + } + + // "*/*" means the bridge didn't find anything (i.e., extension doesn't + // exist). + *aRetVal = !mimeType.Equals(nsDependentCString("*/*"), + nsCaseInsensitiveCStringComparator); + return NS_OK; +} + +void nsMIMEInfoAndroid::AddUniqueExtension(const nsACString& aExtension) { + if (!aExtension.IsEmpty() && + !mExtensions.Contains(aExtension, + nsCaseInsensitiveCStringArrayComparator())) { + mExtensions.AppendElement(aExtension); + } +} + +NS_IMETHODIMP +nsMIMEInfoAndroid::AppendExtension(const nsACString& aExtension) { + MOZ_ASSERT(!aExtension.IsEmpty(), "No extension"); + AddUniqueExtension(aExtension); + return NS_OK; +} + +NS_IMETHODIMP +nsMIMEInfoAndroid::GetPrimaryExtension(nsACString& aPrimaryExtension) { + if (!mExtensions.Length()) { + aPrimaryExtension.Truncate(); + return NS_ERROR_NOT_INITIALIZED; + } + aPrimaryExtension = mExtensions[0]; + return NS_OK; +} + +NS_IMETHODIMP +nsMIMEInfoAndroid::SetPrimaryExtension(const nsACString& aExtension) { + if (MOZ_UNLIKELY(aExtension.IsEmpty())) { + // Don't assert since Java may return an empty extension for unknown types. + return NS_ERROR_INVALID_ARG; + } + int32_t i = mExtensions.IndexOf(aExtension, 0, + nsCaseInsensitiveCStringArrayComparator()); + if (i != -1) { + mExtensions.RemoveElementAt(i); + } + mExtensions.InsertElementAt(0, aExtension); + return NS_OK; +} + +NS_IMETHODIMP +nsMIMEInfoAndroid::GetMIMEType(nsACString& aMIMEType) { + aMIMEType.Assign(mType); + return NS_OK; +} + +NS_IMETHODIMP +nsMIMEInfoAndroid::Equals(nsIMIMEInfo* aMIMEInfo, bool* aRetVal) { + if (!aMIMEInfo) return NS_ERROR_NULL_POINTER; + + nsAutoCString type; + nsresult rv = aMIMEInfo->GetMIMEType(type); + if (NS_FAILED(rv)) return rv; + + *aRetVal = mType.Equals(type); + + return NS_OK; +} + +NS_IMETHODIMP +nsMIMEInfoAndroid::GetPossibleLocalHandlers(nsIArray** aPossibleLocalHandlers) { + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsMIMEInfoAndroid::LaunchWithFile(nsIFile* aFile) { + nsCOMPtr<nsIURI> uri; + NS_NewFileURI(getter_AddRefs(uri), aFile); + return LoadUriInternal(uri); +} + +NS_IMETHODIMP +nsMIMEInfoAndroid::IsCurrentAppOSDefault(bool* aRetVal) { + // FIXME: this should in theory be meaningfully implemented. However, android + // implements its own version of nsIHandlerApp instances which internally + // have package and class names - but do not expose those. So to meaningfully + // compare the handler app would require access to those and knowing what + // our own package/class names are, and it's not clear how to do that. + // It also seems less important to do this right on Android, given that + // Android UI normally limits what apps you can associate with what files, so + // it shouldn't be possible to get into the same kind of loop as on desktop. + *aRetVal = false; + return NS_OK; +} + +nsMIMEInfoAndroid::nsMIMEInfoAndroid(const nsACString& aMIMEType) + : mType(aMIMEType), + mAlwaysAsk(true), + mPrefAction(nsIMIMEInfo::useHelperApp) { + mPrefApp = new nsMIMEInfoAndroid::SystemChooser(this); + nsresult rv; + mHandlerApps = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv); + mHandlerApps->AppendElement(mPrefApp); +} + +#define SYSTEMCHOOSER_NAME u"Android chooser" +#define SYSTEMCHOOSER_DESCRIPTION \ + u"Android's default handler application chooser" + +NS_IMPL_ISUPPORTS(nsMIMEInfoAndroid::SystemChooser, nsIHandlerApp) + +nsresult nsMIMEInfoAndroid::SystemChooser::GetName(nsAString& aName) { + aName.AssignLiteral(SYSTEMCHOOSER_NAME); + return NS_OK; +} + +nsresult nsMIMEInfoAndroid::SystemChooser::SetName(const nsAString&) { + return NS_OK; +} + +nsresult nsMIMEInfoAndroid::SystemChooser::GetDetailedDescription( + nsAString& aDesc) { + aDesc.AssignLiteral(SYSTEMCHOOSER_DESCRIPTION); + return NS_OK; +} + +nsresult nsMIMEInfoAndroid::SystemChooser::SetDetailedDescription( + const nsAString&) { + return NS_OK; +} + +nsresult nsMIMEInfoAndroid::SystemChooser::Equals(nsIHandlerApp* aHandlerApp, + bool* aRetVal) { + *aRetVal = false; + if (!aHandlerApp) { + return NS_OK; + } + + nsAutoString name; + nsAutoString detailedDescription; + aHandlerApp->GetName(name); + aHandlerApp->GetDetailedDescription(detailedDescription); + + *aRetVal = name.Equals(SYSTEMCHOOSER_NAME) && + detailedDescription.Equals(SYSTEMCHOOSER_DESCRIPTION); + return NS_OK; +} + +nsresult nsMIMEInfoAndroid::SystemChooser::LaunchWithURI( + nsIURI* aURI, mozilla::dom::BrowsingContext*) { + return mOuter->LoadUriInternal(aURI); +} diff --git a/uriloader/exthandler/android/nsMIMEInfoAndroid.h b/uriloader/exthandler/android/nsMIMEInfoAndroid.h new file mode 100644 index 0000000000..bdac8f97f9 --- /dev/null +++ b/uriloader/exthandler/android/nsMIMEInfoAndroid.h @@ -0,0 +1,62 @@ +/* -*- Mode: c++; c-basic-offset: 2; tab-width: 20; indent-tabs-mode: nil; -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsMIMEInfoAndroid_h +#define nsMIMEInfoAndroid_h + +#include "nsMIMEInfoImpl.h" +#include "nsIMutableArray.h" +#include "nsAndroidHandlerApp.h" + +class nsMIMEInfoAndroid final : public nsIMIMEInfo { + public: + [[nodiscard]] static bool GetMimeInfoForMimeType( + const nsACString& aMimeType, nsMIMEInfoAndroid** aMimeInfo); + [[nodiscard]] static bool GetMimeInfoForFileExt( + const nsACString& aFileExt, nsMIMEInfoAndroid** aMimeInfo); + + [[nodiscard]] static nsresult GetMimeInfoForURL(const nsACString& aURL, + bool* found, + nsIHandlerInfo** info); + + NS_DECL_ISUPPORTS + NS_DECL_NSIMIMEINFO + NS_DECL_NSIHANDLERINFO + + explicit nsMIMEInfoAndroid(const nsACString& aMIMEType); + + private: + ~nsMIMEInfoAndroid() {} + + /** + * Internal helper to avoid adding duplicates. + */ + void AddUniqueExtension(const nsACString& aExtension); + + [[nodiscard]] virtual nsresult LaunchDefaultWithFile(nsIFile* aFile); + [[nodiscard]] virtual nsresult LoadUriInternal(nsIURI* aURI); + nsCOMPtr<nsIMutableArray> mHandlerApps; + nsCString mType; + nsTArray<nsCString> mExtensions; + bool mAlwaysAsk; + nsHandlerInfoAction mPrefAction; + nsString mDescription; + nsCOMPtr<nsIHandlerApp> mPrefApp; + + public: + class SystemChooser final : public nsIHandlerApp { + public: + NS_DECL_ISUPPORTS + NS_DECL_NSIHANDLERAPP + explicit SystemChooser(nsMIMEInfoAndroid* aOuter) : mOuter(aOuter) {} + + private: + ~SystemChooser() {} + + nsMIMEInfoAndroid* mOuter; + }; +}; + +#endif /* nsMIMEInfoAndroid_h */ diff --git a/uriloader/exthandler/android/nsOSHelperAppService.cpp b/uriloader/exthandler/android/nsOSHelperAppService.cpp new file mode 100644 index 0000000000..9849b66075 --- /dev/null +++ b/uriloader/exthandler/android/nsOSHelperAppService.cpp @@ -0,0 +1,70 @@ +/* -*- Mode: c++; c-basic-offset: 2; tab-width: 20; indent-tabs-mode: nil; -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsOSHelperAppService.h" +#include "nsMIMEInfoAndroid.h" +#include "AndroidBridge.h" + +nsOSHelperAppService::nsOSHelperAppService() : nsExternalHelperAppService() {} + +nsOSHelperAppService::~nsOSHelperAppService() {} + +nsresult nsOSHelperAppService::GetMIMEInfoFromOS(const nsACString& aMIMEType, + const nsACString& aFileExt, + bool* aFound, + nsIMIMEInfo** aMIMEInfo) { + RefPtr<nsMIMEInfoAndroid> mimeInfo; + *aFound = false; + if (!aMIMEType.IsEmpty()) + *aFound = nsMIMEInfoAndroid::GetMimeInfoForMimeType( + aMIMEType, getter_AddRefs(mimeInfo)); + if (!*aFound) + *aFound = nsMIMEInfoAndroid::GetMimeInfoForFileExt( + aFileExt, getter_AddRefs(mimeInfo)); + + // Code that calls this requires an object regardless if the OS has + // something for us, so we return the empty object. + if (!*aFound) mimeInfo = new nsMIMEInfoAndroid(aMIMEType); + + mimeInfo.forget(aMIMEInfo); + return NS_OK; +} + +nsresult nsOSHelperAppService::OSProtocolHandlerExists(const char* aScheme, + bool* aExists) { + // Support any URI barring a couple schemes we use in testing; let the + // app decide what to do with them. + nsAutoCString scheme(aScheme); + *aExists = + !scheme.Equals("unsupported"_ns) && !scheme.Equals("unknownextproto"_ns); + return NS_OK; +} + +NS_IMETHODIMP +nsOSHelperAppService::GetApplicationDescription(const nsACString& aScheme, + nsAString& _retval) { + return NS_ERROR_NOT_AVAILABLE; +} + +NS_IMETHODIMP +nsOSHelperAppService::IsCurrentAppOSDefaultForProtocol( + const nsACString& aScheme, bool* _retval) { + return NS_ERROR_NOT_AVAILABLE; +} + +nsresult nsOSHelperAppService::GetProtocolHandlerInfoFromOS( + const nsACString& aScheme, bool* found, nsIHandlerInfo** info) { + // We don't want to get protocol handlers from the OS in GV; the app + // should take care of that in NavigationDelegate.onLoadRequest(). + return NS_ERROR_NOT_IMPLEMENTED; +} + +nsIHandlerApp* nsOSHelperAppService::CreateAndroidHandlerApp( + const nsAString& aName, const nsAString& aDescription, + const nsAString& aPackageName, const nsAString& aClassName, + const nsACString& aMimeType, const nsAString& aAction) { + return new nsAndroidHandlerApp(aName, aDescription, aPackageName, aClassName, + aMimeType, aAction); +} diff --git a/uriloader/exthandler/android/nsOSHelperAppService.h b/uriloader/exthandler/android/nsOSHelperAppService.h new file mode 100644 index 0000000000..a333c4bcd3 --- /dev/null +++ b/uriloader/exthandler/android/nsOSHelperAppService.h @@ -0,0 +1,38 @@ +/* -*- Mode: c++; c-basic-offset: 2; tab-width: 20; indent-tabs-mode: nil; -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsOSHelperAppService_h +#define nsOSHelperAppService_h + +#include "nsCExternalHandlerService.h" +#include "nsExternalHelperAppService.h" + +class nsOSHelperAppService : public nsExternalHelperAppService { + public: + nsOSHelperAppService(); + virtual ~nsOSHelperAppService(); + + nsresult GetMIMEInfoFromOS(const nsACString& aMIMEType, + const nsACString& aFileExt, bool* aFound, + nsIMIMEInfo** aMIMEInfo) override; + + [[nodiscard]] nsresult OSProtocolHandlerExists(const char* aScheme, + bool* aExists) override; + + NS_IMETHOD GetProtocolHandlerInfoFromOS(const nsACString& aScheme, + bool* found, + nsIHandlerInfo** _retval) override; + NS_IMETHOD GetApplicationDescription(const nsACString& aScheme, + nsAString& _retval) override; + NS_IMETHOD IsCurrentAppOSDefaultForProtocol(const nsACString& aScheme, + bool* _retval) override; + + static nsIHandlerApp* CreateAndroidHandlerApp( + const nsAString& aName, const nsAString& aDescription, + const nsAString& aPackageName, const nsAString& aClassName, + const nsACString& aMimeType, const nsAString& aAction = u""_ns); +}; + +#endif /* nsOSHelperAppService_h */ |