Bug 1170190 - Part 2: Add the nsIHttpChannel::IsTrackingResource() API to query the channel's tracking annotation; r=mayhemer

This commit is contained in:
Ehsan Akhgari 2016-12-16 15:19:19 -05:00
parent 2aa37e3665
commit cd895c94f2
15 changed files with 151 additions and 8 deletions

View file

@ -15,6 +15,7 @@
#include "nsIDocShell.h"
#include "nsIDocument.h"
#include "nsIDOMDocument.h"
#include "nsIHttpChannel.h"
#include "nsIHttpChannelInternal.h"
#include "nsIIOService.h"
#include "nsIParentChannel.h"
@ -31,10 +32,12 @@
#include "nsNetUtil.h"
#include "nsPIDOMWindow.h"
#include "nsXULAppAPI.h"
#include "nsQueryObject.h"
#include "mozilla/ErrorNames.h"
#include "mozilla/Logging.h"
#include "mozilla/Preferences.h"
#include "mozilla/net/HttpBaseChannel.h"
namespace mozilla {
namespace net {
@ -702,6 +705,20 @@ nsChannelClassifier::OnClassifyComplete(nsresult aErrorCode)
if (aErrorCode == NS_ERROR_TRACKING_URI &&
!mTrackingProtectionEnabled.valueOr(false)) {
if (sAnnotateChannelEnabled) {
nsCOMPtr<nsIParentChannel> parentChannel;
NS_QueryNotificationCallbacks(mChannel, parentChannel);
if (parentChannel) {
// This channel is a parent-process proxy for a child process
// request. We should notify the child process as well.
parentChannel->NotifyTrackingResource();
}
RefPtr<HttpBaseChannel> httpChannel = do_QueryObject(mChannel);
if (httpChannel) {
httpChannel->SetIsTrackingResource();
}
}
if (sLowerNetworkPriority) {
if (LOG_ENABLED()) {
nsCOMPtr<nsIURI> uri;

View file

@ -34,6 +34,12 @@ interface nsIParentChannel : nsIStreamListener
*/
[noscript] void notifyTrackingProtectionDisabled();
/**
* Called to notify the HttpChannelChild that the resource being loaded
* is on the tracking protection list.
*/
[noscript] void notifyTrackingResource();
/**
* Called to invoke deletion of the IPC protocol.
*/

View file

@ -42,6 +42,13 @@ DataChannelParent::NotifyTrackingProtectionDisabled()
return NS_OK;
}
NS_IMETHODIMP
DataChannelParent::NotifyTrackingResource()
{
// Nothing to do.
return NS_OK;
}
NS_IMETHODIMP
DataChannelParent::Delete()
{

View file

@ -563,6 +563,13 @@ FTPChannelParent::NotifyTrackingProtectionDisabled()
return NS_OK;
}
NS_IMETHODIMP
FTPChannelParent::NotifyTrackingResource()
{
// One day, this should probably be filled in.
return NS_OK;
}
NS_IMETHODIMP
FTPChannelParent::Delete()
{

View file

@ -119,6 +119,7 @@ HttpBaseChannel::HttpBaseChannel()
, mRequireCORSPreflight(false)
, mReportCollector(new ConsoleReportCollector())
, mForceMainDocumentChannel(false)
, mIsTrackingResource(false)
{
LOG(("Creating HttpBaseChannel @%x\n", this));
@ -233,6 +234,9 @@ NS_INTERFACE_MAP_BEGIN(HttpBaseChannel)
NS_INTERFACE_MAP_ENTRY(nsITimedChannel)
NS_INTERFACE_MAP_ENTRY(nsIConsoleReportCollector)
NS_INTERFACE_MAP_ENTRY(nsIThrottledInputChannel)
if (aIID.Equals(NS_GET_IID(HttpBaseChannel))) {
foundInterface = static_cast<nsIWritablePropertyBag*>(this);
} else
NS_INTERFACE_MAP_END_INHERITING(nsHashPropertyBag)
//-----------------------------------------------------------------------------
@ -1223,6 +1227,13 @@ NS_IMETHODIMP HttpBaseChannel::SetTopLevelContentWindowId(uint64_t aWindowId)
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::GetIsTrackingResource(bool* aIsTrackingResource)
{
*aIsTrackingResource = mIsTrackingResource;
return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::GetTransferSize(uint64_t *aTransferSize)
{

View file

@ -45,6 +45,11 @@
#include "mozilla/net/ChannelEventQueue.h"
#include "nsIThrottledInputChannel.h"
#define HTTP_BASE_CHANNEL_IID \
{ 0x9d5cde03, 0xe6e9, 0x4612, \
{ 0xbf, 0xef, 0xbb, 0x66, 0xf3, 0xbb, 0x74, 0x46 } }
class nsISecurityConsoleMessage;
class nsIPrincipal;
@ -94,6 +99,8 @@ public:
NS_DECL_NSITIMEDCHANNEL
NS_DECL_NSITHROTTLEDINPUTCHANNEL
NS_DECLARE_STATIC_IID_ACCESSOR(HTTP_BASE_CHANNEL_IID)
HttpBaseChannel();
virtual nsresult Init(nsIURI *aURI, uint32_t aCaps, nsProxyInfo *aProxyInfo,
@ -190,6 +197,7 @@ public:
NS_IMETHOD SetChannelId(const nsACString& aChannelId) override;
NS_IMETHOD GetTopLevelContentWindowId(uint64_t *aContentWindowId) override;
NS_IMETHOD SetTopLevelContentWindowId(uint64_t aContentWindowId) override;
NS_IMETHOD GetIsTrackingResource(bool* aIsTrackingResource) override;
// nsIHttpChannelInternal
NS_IMETHOD GetDocumentURI(nsIURI **aDocumentURI) override;
@ -333,6 +341,11 @@ public: /* Necko internal use only... */
// the new mUploadStream.
void EnsureUploadStreamIsCloneableComplete(nsresult aStatus);
void SetIsTrackingResource()
{
mIsTrackingResource = true;
}
protected:
nsCOMArray<nsISecurityConsoleMessage> mSecurityConsoleMessages;
@ -567,12 +580,15 @@ protected:
nsCString mAvailableCachedAltDataType;
bool mForceMainDocumentChannel;
bool mIsTrackingResource;
nsID mChannelId;
nsString mIntegrityMetadata;
};
NS_DEFINE_STATIC_IID_ACCESSOR(HttpBaseChannel, HTTP_BASE_CHANNEL_IID)
// Share some code while working around C++'s absurd inability to handle casting
// of member functions between base/derived types.
// - We want to store member function pointer to call at resume time, but one

View file

@ -1497,6 +1497,13 @@ HttpChannelChild::RecvNotifyTrackingProtectionDisabled()
return IPC_OK();
}
mozilla::ipc::IPCResult
HttpChannelChild::RecvNotifyTrackingResource()
{
SetIsTrackingResource();
return IPC_OK();
}
void
HttpChannelChild::FlushedForDiversion()
{

View file

@ -106,6 +106,7 @@ public:
bool IsSuspended();
mozilla::ipc::IPCResult RecvNotifyTrackingProtectionDisabled() override;
mozilla::ipc::IPCResult RecvNotifyTrackingResource() override;
void FlushedForDiversion();
protected:

View file

@ -1358,6 +1358,14 @@ HttpChannelParent::NotifyTrackingProtectionDisabled()
return NS_OK;
}
NS_IMETHODIMP
HttpChannelParent::NotifyTrackingResource()
{
if (!mIPCClosed)
Unused << SendNotifyTrackingResource();
return NS_OK;
}
NS_IMETHODIMP
HttpChannelParent::Delete()
{

View file

@ -81,6 +81,12 @@ NullHttpChannel::SetTopLevelContentWindowId(uint64_t aWindowId)
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
NullHttpChannel::GetIsTrackingResource(bool* aIsTrackingResource)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
NullHttpChannel::GetTransferSize(uint64_t *aTransferSize)
{

View file

@ -149,6 +149,10 @@ child:
// Tell the child that tracking protection was disabled for this load.
async NotifyTrackingProtectionDisabled();
// Tell the child that the resource being loaded is on the tracking
// protection list.
async NotifyTrackingResource();
// Parent has been suspended for diversion; no more events to be enqueued.
async FlushedForDiversion();

View file

@ -469,4 +469,12 @@ interface nsIHttpChannel : nsIChannel
* this channels is being load in.
*/
attribute uint64_t topLevelContentWindowId;
/**
* Returns true if the channel has loaded a resource that is on the tracking
* protection list. This is only available if the
* privacy.trackingprotection.annotate_channels pref is set and its value
* should only be relied on after the channel has established a connection.
*/
[infallible] readonly attribute boolean isTrackingResource;
};

View file

@ -739,6 +739,13 @@ nsViewSourceChannel::SetTopLevelContentWindowId(uint64_t aWindowId)
mHttpChannel->SetTopLevelContentWindowId(aWindowId);
}
NS_IMETHODIMP
nsViewSourceChannel::GetIsTrackingResource(bool* aIsTrackingResource)
{
return !mHttpChannel ? NS_ERROR_NULL_POINTER :
mHttpChannel->GetIsTrackingResource(aIsTrackingResource);
}
NS_IMETHODIMP
nsViewSourceChannel::GetRequestMethod(nsACString & aRequestMethod)
{

View file

@ -7,14 +7,18 @@ do_get_profile();
var Ci = Components.interfaces;
function listener(priority, nextTest) {
function listener(tracking, priority, nextTest) {
this._tracking = tracking;
this._priority = priority;
this._nextTest = nextTest;
}
listener.prototype = {
onStartRequest: function(request, context) {
do_check_eq(request.QueryInterface(Ci.nsIHttpChannel).isTrackingResource,
this._tracking);
do_check_eq(request.QueryInterface(Ci.nsISupportsPriority).priority,
this._priority);
request.cancel(Components.results.NS_ERROR_ABORT);
this._nextTest();
},
onDataAvailable: function(request, context, stream, offset, count) {
@ -24,7 +28,7 @@ listener.prototype = {
};
var httpServer;
var origin;
var normalOrigin, trackingOrigin;
var testPriorityMap;
var currentTest;
@ -32,7 +36,9 @@ function setup_test() {
httpServer = new HttpServer();
httpServer.start(-1);
httpServer.identity.setPrimary("http", "tracking.example.com", httpServer.identity.primaryPort);
origin = "http://tracking.example.com:" + httpServer.identity.primaryPort;
httpServer.identity.add("http", "example.com", httpServer.identity.primaryPort);
normalOrigin = "http://localhost:" + httpServer.identity.primaryPort;
trackingOrigin = "http://tracking.example.com:" + httpServer.identity.primaryPort;
runTests();
}
@ -45,7 +51,9 @@ function doPriorityTest() {
currentTest = testPriorityMap.shift();
var channel = makeChannel(currentTest.path);
channel.asyncOpen2(new listener(currentTest.expectedPriority, doPriorityTest));
channel.asyncOpen2(new listener(currentTest.expectedTracking,
currentTest.expectedPriority,
doPriorityTest));
}
function makeChannel(path) {
@ -76,11 +84,23 @@ var tests =[
Services.prefs.setBoolPref("privacy.trackingprotection.lower_network_priority", false);
testPriorityMap = [
{
path: origin + "/evil.css",
path: normalOrigin + "/innocent.css",
expectedTracking: false,
expectedPriority: Ci.nsISupportsPriority.PRIORITY_NORMAL
},
{
path: origin + "/evil.js",
path: normalOrigin + "/innocent.js",
expectedTracking: false,
expectedPriority: Ci.nsISupportsPriority.PRIORITY_NORMAL
},
{
path: trackingOrigin + "/evil.css",
expectedTracking: false,
expectedPriority: Ci.nsISupportsPriority.PRIORITY_NORMAL
},
{
path: trackingOrigin + "/evil.js",
expectedTracking: false,
expectedPriority: Ci.nsISupportsPriority.PRIORITY_NORMAL
},
];
@ -94,11 +114,23 @@ var tests =[
Services.prefs.setBoolPref("privacy.trackingprotection.lower_network_priority", true);
testPriorityMap = [
{
path: origin + "/evil.css",
path: normalOrigin + "/innocent.css",
expectedTracking: false,
expectedPriority: Ci.nsISupportsPriority.PRIORITY_NORMAL
},
{
path: normalOrigin + "/innocent.js",
expectedTracking: false,
expectedPriority: Ci.nsISupportsPriority.PRIORITY_NORMAL
},
{
path: trackingOrigin + "/evil.css",
expectedTracking: true,
expectedPriority: Ci.nsISupportsPriority.PRIORITY_LOWEST
},
{
path: origin + "/evil.js",
path: trackingOrigin + "/evil.js",
expectedTracking: true,
expectedPriority: Ci.nsISupportsPriority.PRIORITY_LOWEST
},
];

View file

@ -401,6 +401,12 @@ NS_IMETHODIMP nsExtProtocolChannel::NotifyTrackingProtectionDisabled()
return NS_OK;
}
NS_IMETHODIMP nsExtProtocolChannel::NotifyTrackingResource()
{
// nothing to do
return NS_OK;
}
NS_IMETHODIMP nsExtProtocolChannel::Delete()
{
// nothing to do