зеркало из https://github.com/mozilla/gecko-dev.git
195 строки
6.4 KiB
C++
195 строки
6.4 KiB
C++
/* -*- 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);
|
|
}
|