diff options
Diffstat (limited to '')
-rw-r--r-- | comm/mailnews/base/src/nsNewMailnewsURI.cpp | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/comm/mailnews/base/src/nsNewMailnewsURI.cpp b/comm/mailnews/base/src/nsNewMailnewsURI.cpp new file mode 100644 index 0000000000..305e9273a4 --- /dev/null +++ b/comm/mailnews/base/src/nsNewMailnewsURI.cpp @@ -0,0 +1,155 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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 "nsNewMailnewsURI.h" +#include "nsURLHelper.h" +#include "nsSimpleURI.h" +#include "nsStandardURL.h" +#include "nsThreadUtils.h" +#include "MainThreadUtils.h" +#include "mozilla/SyncRunnable.h" +#include "nsIMsgProtocolHandler.h" +#include "nsIComponentRegistrar.h" +#include "nsXULAppAPI.h" + +#include "../../local/src/nsPop3URL.h" +#include "../../local/src/nsMailboxService.h" +#include "../../compose/src/nsSmtpUrl.h" +#include "../../addrbook/src/nsLDAPURL.h" +#include "../../imap/src/nsImapService.h" +#include "../../news/src/nsNntpUrl.h" +#include "../src/nsCidProtocolHandler.h" + +nsresult NS_NewMailnewsURI(nsIURI** aURI, const nsACString& aSpec, + const char* aCharset /* = nullptr */, + nsIURI* aBaseURI /* = nullptr */) { + // Mailnews URIs aren't allowed in child processes. + if (!XRE_IsParentProcess()) { + return NS_ERROR_UNKNOWN_PROTOCOL; + } + + nsAutoCString scheme; + nsresult rv = net_ExtractURLScheme(aSpec, scheme); + if (NS_FAILED(rv)) { + // then aSpec is relative + if (!aBaseURI) { + return NS_ERROR_MALFORMED_URI; + } + + rv = aBaseURI->GetScheme(scheme); + if (NS_FAILED(rv)) return rv; + } + + // Creating IMAP/mailbox URIs off the main thread can lead to crashes. + // Seems to happen when viewing PDFs. + if (scheme.EqualsLiteral("mailbox") || + scheme.EqualsLiteral("mailbox-message")) { + if (NS_IsMainThread()) { + return nsMailboxService::NewURI(aSpec, aCharset, aBaseURI, aURI); + } + auto NewURI = [&aSpec, &aCharset, &aBaseURI, aURI, &rv ]() -> auto{ + rv = nsMailboxService::NewURI(aSpec, aCharset, aBaseURI, aURI); + }; + nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction("NewURI", NewURI); + mozilla::SyncRunnable::DispatchToThread( + mozilla::GetMainThreadSerialEventTarget(), task); + return rv; + } + if (scheme.EqualsLiteral("imap") || scheme.EqualsLiteral("imap-message")) { + if (NS_IsMainThread()) { + return nsImapService::NewURI(aSpec, aCharset, aBaseURI, aURI); + } + auto NewURI = [&aSpec, &aCharset, &aBaseURI, aURI, &rv ]() -> auto{ + rv = nsImapService::NewURI(aSpec, aCharset, aBaseURI, aURI); + }; + nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction("NewURI", NewURI); + mozilla::SyncRunnable::DispatchToThread( + mozilla::GetMainThreadSerialEventTarget(), task); + return rv; + } + if (scheme.EqualsLiteral("smtp") || scheme.EqualsLiteral("smtps")) { + return nsSmtpUrl::NewSmtpURI(aSpec, aBaseURI, aURI); + } + if (scheme.EqualsLiteral("mailto")) { + if (NS_IsMainThread()) { + return nsMailtoUrl::NewMailtoURI(aSpec, aBaseURI, aURI); + } + // If we're for some reason not on the main thread, dispatch to main + // or else we'll crash. + auto NewURI = [&aSpec, &aBaseURI, aURI, &rv ]() -> auto{ + rv = nsMailtoUrl::NewMailtoURI(aSpec, aBaseURI, aURI); + }; + nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction("NewURI", NewURI); + mozilla::SyncRunnable::DispatchToThread( + mozilla::GetMainThreadSerialEventTarget(), task); + return rv; + } + if (scheme.EqualsLiteral("pop") || scheme.EqualsLiteral("pop3")) { + return nsPop3URL::NewURI(aSpec, aBaseURI, aURI); + } + if (scheme.EqualsLiteral("news") || scheme.EqualsLiteral("snews") || + scheme.EqualsLiteral("news-message") || scheme.EqualsLiteral("nntp")) { + return nsNntpUrl::NewURI(aSpec, aBaseURI, aURI); + } + if (scheme.EqualsLiteral("cid")) { + return nsCidProtocolHandler::NewURI(aSpec, aCharset, aBaseURI, aURI); + } + if (scheme.EqualsLiteral("ldap") || scheme.EqualsLiteral("ldaps")) { + nsCOMPtr<nsILDAPURL> url = do_CreateInstance(NS_LDAPURL_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + rv = url->Init(nsIStandardURL::URLTYPE_STANDARD, + scheme.EqualsLiteral("ldap") ? 389 : 636, aSpec, aCharset, + aBaseURI); + NS_ENSURE_SUCCESS(rv, rv); + url.forget(aURI); + return NS_OK; + } + if (scheme.EqualsLiteral("smile")) { + return NS_MutateURI(new mozilla::net::nsSimpleURI::Mutator()) + .SetSpec(aSpec) + .Finalize(aURI); + } + if (scheme.EqualsLiteral("moz-cal-handle-itip")) { + return NS_MutateURI(new mozilla::net::nsStandardURL::Mutator()) + .SetSpec(aSpec) + .Finalize(aURI); + } + if (scheme.EqualsLiteral("webcal") || scheme.EqualsLiteral("webcals")) { + return NS_MutateURI(new mozilla::net::nsStandardURL::Mutator()) + .SetSpec(aSpec) + .Finalize(aURI); + } + + rv = NS_ERROR_UNKNOWN_PROTOCOL; // Let M-C handle it by default. + + nsCOMPtr<nsIComponentRegistrar> compMgr; + NS_GetComponentRegistrar(getter_AddRefs(compMgr)); + if (compMgr) { + nsAutoCString contractID(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX); + contractID += scheme; + bool isRegistered = false; + compMgr->IsContractIDRegistered(contractID.get(), &isRegistered); + if (isRegistered) { + auto NewURI = + [&aSpec, &aCharset, &aBaseURI, aURI, &contractID, &rv ]() -> auto{ + nsCOMPtr<nsIMsgProtocolHandler> handler( + do_GetService(contractID.get())); + if (handler) { + // We recognise this URI. Use the protocol handler's result. + rv = handler->NewURI(aSpec, aCharset, aBaseURI, aURI); + } + }; + if (NS_IsMainThread()) { + NewURI(); + } else { + nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction("NewURI", NewURI); + mozilla::SyncRunnable::DispatchToThread( + mozilla::GetMainThreadSerialEventTarget(), task); + } + } + } + + return rv; +} |