summaryrefslogtreecommitdiffstats
path: root/netwerk/protocol/res/nsResProtocolHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/protocol/res/nsResProtocolHandler.cpp')
-rw-r--r--netwerk/protocol/res/nsResProtocolHandler.cpp194
1 files changed, 194 insertions, 0 deletions
diff --git a/netwerk/protocol/res/nsResProtocolHandler.cpp b/netwerk/protocol/res/nsResProtocolHandler.cpp
new file mode 100644
index 0000000000..6918799e35
--- /dev/null
+++ b/netwerk/protocol/res/nsResProtocolHandler.cpp
@@ -0,0 +1,194 @@
+/* -*- 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 "mozilla/chrome/RegistryMessageUtils.h"
+#include "mozilla/dom/ContentParent.h"
+#include "mozilla/Unused.h"
+
+#include "nsResProtocolHandler.h"
+#include "nsNetCID.h"
+#include "nsNetUtil.h"
+#include "nsURLHelper.h"
+#include "nsEscape.h"
+
+#include "mozilla/Omnijar.h"
+
+using mozilla::LogLevel;
+using mozilla::Unused;
+using mozilla::dom::ContentParent;
+
+#define kAPP "app"
+#define kGRE "gre"
+#define kAndroid "android"
+
+mozilla::StaticRefPtr<nsResProtocolHandler> nsResProtocolHandler::sSingleton;
+
+already_AddRefed<nsResProtocolHandler> nsResProtocolHandler::GetSingleton() {
+ if (!sSingleton) {
+ RefPtr<nsResProtocolHandler> handler = new nsResProtocolHandler();
+ if (NS_WARN_IF(NS_FAILED(handler->Init()))) {
+ return nullptr;
+ }
+ sSingleton = handler;
+ ClearOnShutdown(&sSingleton);
+ }
+ return do_AddRef(sSingleton);
+}
+
+nsresult nsResProtocolHandler::Init() {
+ nsresult rv;
+ rv = mozilla::Omnijar::GetURIString(mozilla::Omnijar::APP, mAppURI);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = mozilla::Omnijar::GetURIString(mozilla::Omnijar::GRE, mGREURI);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // mozilla::Omnijar::GetURIString always returns a string ending with /,
+ // and we want to remove it.
+ mGREURI.Truncate(mGREURI.Length() - 1);
+ if (mAppURI.Length()) {
+ mAppURI.Truncate(mAppURI.Length() - 1);
+ } else {
+ mAppURI = mGREURI;
+ }
+
+#ifdef ANDROID
+ rv = GetApkURI(mApkURI);
+#endif
+
+ // XXXbsmedberg Neil wants a resource://pchrome/ for the profile chrome dir...
+ // but once I finish multiple chrome registration I'm not sure that it is
+ // needed
+
+ // XXX dveditz: resource://pchrome/ defeats profile directory salting
+ // if web content can load it. Tread carefully.
+
+ return rv;
+}
+
+#ifdef ANDROID
+nsresult nsResProtocolHandler::GetApkURI(nsACString& aResult) {
+ nsCString::const_iterator start, iter;
+ mGREURI.BeginReading(start);
+ mGREURI.EndReading(iter);
+ nsCString::const_iterator start_iter = start;
+
+ // This is like jar:jar:file://path/to/apk/base.apk!/path/to/omni.ja!/
+ bool found = FindInReadable("!/"_ns, start_iter, iter);
+ NS_ENSURE_TRUE(found, NS_ERROR_UNEXPECTED);
+
+ // like jar:jar:file://path/to/apk/base.apk!/
+ const nsDependentCSubstring& withoutPath = Substring(start, iter);
+ NS_ENSURE_TRUE(withoutPath.Length() >= 4, NS_ERROR_UNEXPECTED);
+
+ // Let's make sure we're removing what we expect to remove
+ NS_ENSURE_TRUE(Substring(withoutPath, 0, 4).EqualsLiteral("jar:"),
+ NS_ERROR_UNEXPECTED);
+
+ // like jar:file://path/to/apk/base.apk!/
+ aResult = ToNewCString(Substring(withoutPath, 4));
+
+ // Remove the trailing /
+ NS_ENSURE_TRUE(aResult.Length() >= 1, NS_ERROR_UNEXPECTED);
+ aResult.Truncate(aResult.Length() - 1);
+ return NS_OK;
+}
+#endif
+
+//----------------------------------------------------------------------------
+// nsResProtocolHandler::nsISupports
+//----------------------------------------------------------------------------
+
+NS_IMPL_QUERY_INTERFACE(nsResProtocolHandler, nsIResProtocolHandler,
+ nsISubstitutingProtocolHandler, nsIProtocolHandler,
+ nsISupportsWeakReference)
+NS_IMPL_ADDREF_INHERITED(nsResProtocolHandler, SubstitutingProtocolHandler)
+NS_IMPL_RELEASE_INHERITED(nsResProtocolHandler, SubstitutingProtocolHandler)
+
+NS_IMETHODIMP
+nsResProtocolHandler::AllowContentToAccess(nsIURI* aURI, bool* aResult) {
+ *aResult = false;
+
+ nsAutoCString host;
+ nsresult rv = aURI->GetAsciiHost(host);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ uint32_t flags;
+ rv = GetSubstitutionFlags(host, &flags);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ *aResult = flags & nsISubstitutingProtocolHandler::ALLOW_CONTENT_ACCESS;
+ return NS_OK;
+}
+
+nsresult nsResProtocolHandler::GetSubstitutionInternal(const nsACString& aRoot,
+ nsIURI** aResult,
+ uint32_t* aFlags) {
+ nsAutoCString uri;
+
+ if (!ResolveSpecialCases(aRoot, "/"_ns, "/"_ns, uri)) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
+ if (aRoot.Equals(kAndroid)) {
+ *aFlags = nsISubstitutingProtocolHandler::RESOLVE_JAR_URI;
+ } else {
+ *aFlags = 0; // No content access.
+ }
+ return NS_NewURI(aResult, uri);
+}
+
+bool nsResProtocolHandler::ResolveSpecialCases(const nsACString& aHost,
+ const nsACString& aPath,
+ const nsACString& aPathname,
+ nsACString& aResult) {
+ if (aHost.EqualsLiteral("") || aHost.EqualsLiteral(kAPP)) {
+ aResult.Assign(mAppURI);
+ } else if (aHost.Equals(kGRE)) {
+ aResult.Assign(mGREURI);
+#ifdef ANDROID
+ } else if (aHost.Equals(kAndroid)) {
+ aResult.Assign(mApkURI);
+#endif
+ } else {
+ return false;
+ }
+ aResult.Append(aPath);
+ return true;
+}
+
+nsresult nsResProtocolHandler::SetSubstitution(const nsACString& aRoot,
+ nsIURI* aBaseURI) {
+ MOZ_ASSERT(!aRoot.EqualsLiteral(""));
+ MOZ_ASSERT(!aRoot.EqualsLiteral(kAPP));
+ MOZ_ASSERT(!aRoot.EqualsLiteral(kGRE));
+ MOZ_ASSERT(!aRoot.EqualsLiteral(kAndroid));
+ return SubstitutingProtocolHandler::SetSubstitution(aRoot, aBaseURI);
+}
+
+nsresult nsResProtocolHandler::SetSubstitutionWithFlags(const nsACString& aRoot,
+ nsIURI* aBaseURI,
+ uint32_t aFlags) {
+ MOZ_ASSERT(!aRoot.EqualsLiteral(""));
+ MOZ_ASSERT(!aRoot.EqualsLiteral(kAPP));
+ MOZ_ASSERT(!aRoot.EqualsLiteral(kGRE));
+ MOZ_ASSERT(!aRoot.EqualsLiteral(kAndroid));
+ return SubstitutingProtocolHandler::SetSubstitutionWithFlags(aRoot, aBaseURI,
+ aFlags);
+}
+
+nsresult nsResProtocolHandler::HasSubstitution(const nsACString& aRoot,
+ bool* aResult) {
+ if (aRoot.EqualsLiteral(kAPP) || aRoot.EqualsLiteral(kGRE)
+#ifdef ANDROID
+ || aRoot.EqualsLiteral(kAndroid)
+#endif
+ ) {
+ *aResult = true;
+ return NS_OK;
+ }
+
+ return mozilla::net::SubstitutingProtocolHandler::HasSubstitution(aRoot,
+ aResult);
+}