Bug 1255894: Part 2 - Add mozIWebRequestService service for tracking filtered requests. r=mixedpuppy

In order to allow extensions running in a content process to connect extension
filters, we need to be able to track which requests they have permissions to
modify, and which processes they have permissions to modify them from.

This interface allows us to register channels that we've dispatched webRequest
listeners for, and the TabParent (and, by proxy, content parent) we've
dispatched them to. Extensions will only be able to filter those channels, and
only from those processes.

MozReview-Commit-ID: 46HTVeQ5ndi

--HG--
extra : rebase_source : aadfadef3b72044302b3f4e6c88a5a06ff138c84
This commit is contained in:
Kris Maglione 2017-03-23 12:18:29 -07:00
parent ad81a66617
commit 5613873ecb
7 changed files with 309 additions and 3 deletions

View File

@ -92,6 +92,9 @@
#define NS_ADDONPATHSERVICE_CONTRACTID \
"@mozilla.org/addon-path-service;1"
#define NS_WEBREQUESTSERVICE_CONTRACTID \
"@mozilla.org/addons/webrequest-service;1"
/////////////////////////////////////////////////////////////////////////////
#define ALERT_NOTIFICATION_CID \
@ -192,3 +195,7 @@
#define NS_ADDON_POLICY_SERVICE_CONTRACTID \
"@mozilla.org/addons/policy-service;1"
// {5dd0c968-d74d-42c3-b930-36145f885c3b}
#define NS_WEBREQUEST_SERVICE_CID \
{ 0x5dd0c968, 0xd74d, 0x42c3, { 0xb9, 0x30, 0x36, 0x14, 0x5f, 0x88, 0x5c, 0x3b } }

View File

@ -38,6 +38,7 @@
#include "mozilla/AddonManagerStartup.h"
#include "mozilla/AddonPathService.h"
#include "mozilla/ExtensionPolicyService.h"
#include "mozilla/WebRequestService.h"
#if defined(XP_WIN)
#include "NativeFileWatcherWin.h"
@ -128,6 +129,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(AddonContentPolicy)
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(AddonPathService, AddonPathService::GetInstance)
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(AddonManagerStartup, AddonManagerStartup::GetInstance)
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(ExtensionPolicyService, ExtensionPolicyService::GetInstance)
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(WebRequestService, WebRequestService::GetInstance)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsWebRequestListener)
@ -164,6 +166,7 @@ NS_DEFINE_NAMED_CID(NS_ADDONCONTENTPOLICY_CID);
NS_DEFINE_NAMED_CID(NS_ADDON_PATH_SERVICE_CID);
NS_DEFINE_NAMED_CID(NS_ADDON_MANAGER_STARTUP_CID);
NS_DEFINE_NAMED_CID(NS_ADDON_POLICY_SERVICE_CID);
NS_DEFINE_NAMED_CID(NS_WEBREQUEST_SERVICE_CID);
NS_DEFINE_NAMED_CID(NATIVE_FILEWATCHER_SERVICE_CID);
NS_DEFINE_NAMED_CID(NS_WEBREQUESTLISTENER_CID);
@ -200,6 +203,7 @@ static const Module::CIDEntry kToolkitCIDs[] = {
{ &kNS_ADDON_PATH_SERVICE_CID, false, nullptr, AddonPathServiceConstructor },
{ &kNS_ADDON_MANAGER_STARTUP_CID, false, nullptr, AddonManagerStartupConstructor },
{ &kNS_ADDON_POLICY_SERVICE_CID, false, nullptr, ExtensionPolicyServiceConstructor },
{ &kNS_WEBREQUEST_SERVICE_CID, false, nullptr, WebRequestServiceConstructor },
{ &kNATIVE_FILEWATCHER_SERVICE_CID, false, nullptr, NativeFileWatcherServiceConstructor },
{ &kNS_WEBREQUESTLISTENER_CID, false, nullptr, nsWebRequestListenerConstructor },
{ nullptr }
@ -239,6 +243,7 @@ static const Module::ContractIDEntry kToolkitContracts[] = {
{ NS_ADDONPATHSERVICE_CONTRACTID, &kNS_ADDON_PATH_SERVICE_CID },
{ NS_ADDONMANAGERSTARTUP_CONTRACTID, &kNS_ADDON_MANAGER_STARTUP_CID },
{ NS_ADDON_POLICY_SERVICE_CONTRACTID, &kNS_ADDON_POLICY_SERVICE_CID },
{ NS_WEBREQUESTSERVICE_CONTRACTID, &kNS_WEBREQUEST_SERVICE_CID },
{ NATIVE_FILEWATCHER_SERVICE_CONTRACTID, &kNATIVE_FILEWATCHER_SERVICE_CID },
{ NS_WEBREQUESTLISTENER_CONTRACTID, &kNS_WEBREQUESTLISTENER_CID },
{ nullptr }

View File

@ -4,6 +4,7 @@
# 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/.
with Files('**'):
BUG_COMPONENT = ('Toolkit', 'WebExtensions: General')

View File

@ -0,0 +1,163 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 "WebRequestService.h"
#include "mozilla/Assertions.h"
#include "mozilla/ClearOnShutdown.h"
#include "nsCOMPtr.h"
#include "nsIChannel.h"
#include "nsIDOMWindowUtils.h"
#include "nsISupports.h"
#include "nsITabParent.h"
#include "nsITraceableChannel.h"
#include "mozilla/dom/TabParent.h"
using namespace mozilla;
using namespace mozilla::dom;
WebRequestService::WebRequestService()
: mDataLock("WebRequest service data lock")
{
}
WebRequestService::~WebRequestService()
{
}
NS_IMPL_ISUPPORTS(WebRequestService, mozIWebRequestService)
/* static */ WebRequestService&
WebRequestService::GetSingleton()
{
static RefPtr<WebRequestService> instance;
if (!instance) {
instance = new WebRequestService();
ClearOnShutdown(&instance);
}
return *instance;
}
NS_IMETHODIMP
WebRequestService::RegisterTraceableChannel(uint64_t aChannelId,
nsIChannel* aChannel,
const nsAString& aAddonId,
nsITabParent* aTabParent,
nsIJSRAIIHelper** aHelper)
{
nsCOMPtr<nsITraceableChannel> traceableChannel = do_QueryInterface(aChannel);
NS_ENSURE_TRUE(traceableChannel, NS_ERROR_INVALID_ARG);
nsCOMPtr<nsIAtom> addonId = NS_Atomize(aAddonId);
ChannelParent* entry = new ChannelParent(aChannelId, aChannel,
addonId, aTabParent);
RefPtr<Destructor> destructor = new Destructor(entry);
destructor.forget(aHelper);
return NS_OK;
}
already_AddRefed<nsIChannel>
WebRequestService::GetTraceableChannel(uint64_t aChannelId,
nsIAtom* aAddonId,
nsIContentParent* aContentParent)
{
MutexAutoLock al(mDataLock);
auto entry = mChannelEntries.Get(aChannelId);
if (!entry) {
return nullptr;
}
for (auto channelEntry : entry->mTabParents) {
nsIContentParent* contentParent = nullptr;
if (channelEntry->mTabParent) {
contentParent = static_cast<nsIContentParent*>(
channelEntry->mTabParent->Manager());
}
if (channelEntry->mAddonId == aAddonId && contentParent == aContentParent) {
nsCOMPtr<nsIChannel> channel = do_QueryReferent(entry->mChannel);
return channel.forget();
}
}
return nullptr;
}
WebRequestService::ChannelParent::ChannelParent(uint64_t aChannelId, nsIChannel* aChannel,
nsIAtom* aAddonId, nsITabParent* aTabParent)
: mTabParent(static_cast<TabParent*>(aTabParent))
, mAddonId(aAddonId)
, mChannelId(aChannelId)
{
auto service = &GetSingleton();
MutexAutoLock al(service->mDataLock);
auto entry = service->mChannelEntries.LookupOrAdd(mChannelId);
entry->mChannel = do_GetWeakReference(aChannel);
entry->mTabParents.insertBack(this);
}
WebRequestService::ChannelParent::~ChannelParent()
{
MOZ_ASSERT(mDetached);
}
void
WebRequestService::ChannelParent::Detach()
{
if (mDetached) {
return;
}
auto service = &GetSingleton();
MutexAutoLock al(service->mDataLock);
auto& map = service->mChannelEntries;
auto entry = map.Get(mChannelId);
MOZ_ASSERT(entry);
removeFrom(entry->mTabParents);
if (entry->mTabParents.isEmpty()) {
map.Remove(mChannelId);
}
mDetached = true;
}
WebRequestService::ChannelEntry::~ChannelEntry()
{
while (ChannelParent* parent = mTabParents.getFirst()) {
parent->Detach();
}
}
WebRequestService::Destructor::~Destructor()
{
if (NS_WARN_IF(!mDestructCalled)) {
Destruct();
}
}
NS_IMETHODIMP
WebRequestService::Destructor::Destruct()
{
if (NS_WARN_IF(mDestructCalled)) {
return NS_ERROR_FAILURE;
}
mDestructCalled = true;
mChannelParent->Detach();
delete mChannelParent;
return NS_OK;
}
NS_IMPL_ISUPPORTS(WebRequestService::Destructor, nsIJSRAIIHelper)

View File

@ -0,0 +1,103 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 mozilla_WebRequestService_h
#define mozilla_WebRequestService_h
#include "mozIWebRequestService.h"
#include "mozilla/LinkedList.h"
#include "mozilla/Mutex.h"
#include "nsCOMPtr.h"
#include "nsHashKeys.h"
#include "nsClassHashtable.h"
#include "nsIAtom.h"
#include "nsIDOMWindowUtils.h"
#include "nsWeakPtr.h"
using namespace mozilla;
namespace mozilla {
namespace dom {
class TabParent;
class nsIContentParent;
}
}
class WebRequestService : public mozIWebRequestService
{
public:
NS_DECL_ISUPPORTS
NS_DECL_MOZIWEBREQUESTSERVICE
explicit WebRequestService();
static already_AddRefed<WebRequestService> GetInstance()
{
return do_AddRef(&GetSingleton());
}
static WebRequestService& GetSingleton();
already_AddRefed<nsIChannel>
GetTraceableChannel(uint64_t aChannelId, nsIAtom* aAddonId,
dom::nsIContentParent* aContentParent);
protected:
virtual ~WebRequestService();
private:
class ChannelParent : public LinkedListElement<ChannelParent>
{
public:
explicit ChannelParent(uint64_t aChannelId, nsIChannel* aChannel, nsIAtom* aAddonId, nsITabParent* aTabParent);
~ChannelParent();
void Detach();
const RefPtr<dom::TabParent> mTabParent;
const nsCOMPtr<nsIAtom> mAddonId;
private:
const uint64_t mChannelId;
bool mDetached = false;
};
class Destructor : public nsIJSRAIIHelper
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIJSRAIIHELPER
explicit Destructor(ChannelParent* aChannelParent)
: mChannelParent(aChannelParent)
, mDestructCalled(false)
{}
protected:
virtual ~Destructor();
private:
ChannelParent* mChannelParent;
bool mDestructCalled;
};
class ChannelEntry
{
public:
~ChannelEntry();
// Note: We can't keep a strong pointer to the channel here, since channels
// are not cycle collected, and a reference to this object will be stored on
// the channel in order to keep the entry alive.
nsWeakPtr mChannel;
LinkedList<ChannelParent> mTabParents;
};
nsClassHashtable<nsUint64HashKey, ChannelEntry> mChannelEntries;
Mutex mDataLock;
};
#endif // mozilla_WebRequestService_h

View File

@ -5,17 +5,26 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
XPIDL_SOURCES += [
'mozIWebRequestService.idl',
'nsIWebRequestListener.idl',
]
XPIDL_MODULE = 'webextensions'
UNIFIED_SOURCES += [
'nsWebRequestListener.cpp',
'WebRequestService.cpp',
]
EXPORTS += [
'nsWebRequestListener.h',
]
UNIFIED_SOURCES += [
'nsWebRequestListener.cpp',
EXPORTS.mozilla += [
'WebRequestService.h',
]
FINAL_LIBRARY = 'xul'
FINAL_LIBRARY = 'xul'
with Files("**"):
BUG_COMPONENT = ("Toolkit", "WebExtensions: Request Handling")

View File

@ -0,0 +1,18 @@
/* 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 "nsISupports.idl"
interface nsIChannel;
interface nsIJSRAIIHelper;
interface nsITabParent;
[scriptable, builtinclass, uuid(1b1118ed-f208-4cfc-b841-5b31a78c2b7a)]
interface mozIWebRequestService : nsISupports
{
nsIJSRAIIHelper registerTraceableChannel(in uint64_t channelId,
in nsIChannel channel,
in AString addonId,
[optional] in nsITabParent tabParent);
};