Bug 1402944: Part 5 - Move request filtering and permission matching into ChannelWrapper. r=mixedpuppy,ehsan

This allows us to reuse the same URLInfo objects for each permission or
extension that we match, and also avoids a lot of XPConnect overhead we wind
up incurring when we access URI objects from the JS side.

MozReview-Commit-ID: GqgVRjQ3wYQ
This commit is contained in:
Kris Maglione
2017-09-27 18:15:12 -07:00
parent d4776d075c
commit 813dfdec77
10 changed files with 204 additions and 96 deletions

View File

@@ -82,14 +82,15 @@ ChannelWrapper::SetChannel(nsIChannel* aChannel)
{
detail::ChannelHolder::SetChannel(aChannel);
ClearCachedAttributes();
ChannelWrapperBinding::ClearCachedFinalURIValue(this);
ChannelWrapperBinding::ClearCachedFinalURLValue(this);
mFinalURLInfo.reset();
ChannelWrapperBinding::ClearCachedProxyInfoValue(this);
}
void
ChannelWrapper::ClearCachedAttributes()
{
ChannelWrapperBinding::ClearCachedFinalURIValue(this);
ChannelWrapperBinding::ClearCachedFinalURLValue(this);
ChannelWrapperBinding::ClearCachedProxyInfoValue(this);
ChannelWrapperBinding::ClearCachedRemoteAddressValue(this);
ChannelWrapperBinding::ClearCachedStatusCodeValue(this);
ChannelWrapperBinding::ClearCachedStatusLineValue(this);
@@ -370,7 +371,7 @@ ChannelWrapper::IsSystemLoad() const
bool
ChannelWrapper::GetCanModify(ErrorResult& aRv) const
{
nsCOMPtr<nsIURI> uri = GetFinalURI(aRv);
nsCOMPtr<nsIURI> uri = FinalURI();
nsAutoCString spec;
if (uri) {
uri->GetSpec(spec);
@@ -440,6 +441,93 @@ ChannelWrapper::GetDocumentURL(nsCString& aRetVal) const
}
}
const URLInfo&
ChannelWrapper::FinalURLInfo() const
{
if (mFinalURLInfo.isNothing()) {
ErrorResult rv;
nsCOMPtr<nsIURI> uri = FinalURI();
MOZ_ASSERT(uri);
mFinalURLInfo.emplace(uri.get(), true);
// If this is a WebSocket request, mangle the URL so that the scheme is
// ws: or wss:, as appropriate.
auto& url = mFinalURLInfo.ref();
if (Type() == MozContentPolicyType::Websocket &&
(url.Scheme() == nsGkAtoms::http ||
url.Scheme() == nsGkAtoms::https)) {
nsAutoCString spec(url.CSpec());
spec.Replace(0, 4, NS_LITERAL_CSTRING("ws"));
Unused << NS_NewURI(getter_AddRefs(uri), spec);
MOZ_RELEASE_ASSERT(uri);
mFinalURLInfo.reset();
mFinalURLInfo.emplace(uri.get(), true);
}
}
return mFinalURLInfo.ref();
}
const URLInfo*
ChannelWrapper::DocumentURLInfo() const
{
if (mDocumentURLInfo.isNothing()) {
nsCOMPtr<nsIURI> uri = GetDocumentURI();
if (!uri) {
return nullptr;
}
mDocumentURLInfo.emplace(uri.get(), true);
}
return &mDocumentURLInfo.ref();
}
bool
ChannelWrapper::Matches(const dom::MozRequestFilter& aFilter,
const WebExtensionPolicy* aExtension,
const dom::MozRequestMatchOptions& aOptions) const
{
if (!HaveChannel()) {
return false;
}
if (!aFilter.mTypes.IsNull() && !aFilter.mTypes.Value().Contains(Type())) {
return false;
}
auto& urlInfo = FinalURLInfo();
if (aFilter.mUrls && !aFilter.mUrls->Matches(urlInfo)) {
return false;
}
if (aExtension) {
if (!aExtension->CanAccessURI(urlInfo)) {
return false;
}
bool isProxy = aOptions.mIsProxy && aExtension->HasPermission(nsGkAtoms::proxy);
if (!isProxy && IsSystemLoad()) {
return false;
}
if (auto origin = DocumentURLInfo()) {
nsAutoCString baseURL;
aExtension->GetBaseURL(baseURL);
if (!isProxy &&
!StringBeginsWith(origin->CSpec(), baseURL) &&
!aExtension->CanAccessURI(*origin)) {
return false;
}
}
}
return true;
}
int64_t
NormalizeWindowID(nsILoadInfo* aLoadInfo, uint64_t windowID)
{
@@ -654,25 +742,20 @@ ChannelWrapper::GetStatusLine(nsCString& aRetVal) const
*****************************************************************************/
already_AddRefed<nsIURI>
ChannelWrapper::GetFinalURI(ErrorResult& aRv) const
ChannelWrapper::FinalURI() const
{
nsresult rv = NS_ERROR_UNEXPECTED;
nsCOMPtr<nsIURI> uri;
if (nsCOMPtr<nsIChannel> chan = MaybeChannel()) {
rv = NS_GetFinalChannelURI(chan, getter_AddRefs(uri));
}
if (NS_FAILED(rv)) {
aRv.Throw(rv);
NS_GetFinalChannelURI(chan, getter_AddRefs(uri));
}
return uri.forget();
}
void
ChannelWrapper::GetFinalURL(nsCString& aRetVal, ErrorResult& aRv) const
ChannelWrapper::GetFinalURL(nsString& aRetVal) const
{
nsCOMPtr<nsIURI> uri = GetFinalURI(aRv);
if (uri) {
Unused << uri->GetSpec(aRetVal);
if (HaveChannel()) {
aRetVal = FinalURLInfo().Spec();
}
}