mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 13:51:41 +00:00
7a61308533
UI needs to distinguish the cases when a channel is shimmed and is unshimmed. When a channel is unshimmed, we unblock the channel and simply treat the channel as a non-tracking channel. When a channel is shimmed, although the channel is unblocked by URLCLassifier, we still want to show it in the UI. For this case, URLClassifier will notify a content blocking event when a channel is unblocked. This patch adds a new allow API, so the caller can use unblock() or allow() depending upon the case it requires. Differential Revision: https://phabricator.services.mozilla.com/D93271
269 lines
7.4 KiB
C++
269 lines
7.4 KiB
C++
/* -*- 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 "ChannelClassifierService.h"
|
|
|
|
#include "mozilla/ClearOnShutdown.h"
|
|
#include "mozilla/dom/BrowserParent.h"
|
|
#include "mozilla/dom/BrowsingContext.h"
|
|
#include "mozilla/dom/CanonicalBrowsingContext.h"
|
|
#include "mozilla/dom/WindowGlobalParent.h"
|
|
#include "mozilla/net/UrlClassifierCommon.h"
|
|
|
|
#include "UrlClassifierFeatureCryptominingProtection.h"
|
|
#include "UrlClassifierFeatureFingerprintingProtection.h"
|
|
#include "UrlClassifierFeatureSocialTrackingProtection.h"
|
|
#include "UrlClassifierFeatureTrackingProtection.h"
|
|
|
|
namespace mozilla {
|
|
namespace net {
|
|
|
|
static StaticRefPtr<ChannelClassifierService> gChannelClassifierService;
|
|
|
|
NS_IMPL_ISUPPORTS(UrlClassifierBlockedChannel, nsIUrlClassifierBlockedChannel)
|
|
|
|
UrlClassifierBlockedChannel::UrlClassifierBlockedChannel(nsIChannel* aChannel)
|
|
: mChannel(aChannel),
|
|
mDecision(ChannelBlockDecision::Blocked),
|
|
mReason(TRACKING_PROTECTION) {
|
|
MOZ_ASSERT(aChannel);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
UrlClassifierBlockedChannel::GetReason(uint8_t* aReason) {
|
|
NS_ENSURE_ARG_POINTER(aReason);
|
|
|
|
*aReason = mReason;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
UrlClassifierBlockedChannel::GetUrl(nsAString& aUrl) {
|
|
nsCOMPtr<nsIURI> uri;
|
|
mChannel->GetURI(getter_AddRefs(uri));
|
|
if (uri) {
|
|
CopyUTF8toUTF16(uri->GetSpecOrDefault(), aUrl);
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
UrlClassifierBlockedChannel::GetTabId(uint64_t* aTabId) {
|
|
NS_ENSURE_ARG_POINTER(aTabId);
|
|
|
|
*aTabId = 0;
|
|
|
|
nsCOMPtr<nsILoadInfo> loadInfo = mChannel->LoadInfo();
|
|
MOZ_ASSERT(loadInfo);
|
|
|
|
RefPtr<dom::BrowsingContext> browsingContext;
|
|
nsresult rv =
|
|
loadInfo->GetTargetBrowsingContext(getter_AddRefs(browsingContext));
|
|
if (NS_WARN_IF(NS_FAILED(rv)) || !browsingContext) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
// Get top-level browsing context to ensure window global parent is ready
|
|
// to use, tabId is the same anyway.
|
|
dom::CanonicalBrowsingContext* top = browsingContext->Canonical()->Top();
|
|
dom::WindowGlobalParent* wgp = top->GetCurrentWindowGlobal();
|
|
if (!wgp) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
RefPtr<dom::BrowserParent> browserParent = wgp->GetBrowserParent();
|
|
if (!browserParent) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
*aTabId = browserParent->GetTabId();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
UrlClassifierBlockedChannel::GetChannelId(uint64_t* aChannelId) {
|
|
NS_ENSURE_ARG_POINTER(aChannelId);
|
|
|
|
nsCOMPtr<nsIIdentChannel> channel(do_QueryInterface(mChannel));
|
|
*aChannelId = channel ? channel->ChannelId() : 0;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
UrlClassifierBlockedChannel::GetTopLevelUrl(nsAString& aTopLevelUrl) {
|
|
nsCOMPtr<nsILoadInfo> loadInfo = mChannel->LoadInfo();
|
|
MOZ_ASSERT(loadInfo);
|
|
|
|
RefPtr<dom::BrowsingContext> browsingContext;
|
|
nsresult rv =
|
|
loadInfo->GetTargetBrowsingContext(getter_AddRefs(browsingContext));
|
|
if (NS_WARN_IF(NS_FAILED(rv)) || !browsingContext) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
// Get top-level browsing context to ensure window global parent is ready
|
|
// to use, tabId is the same anyway.
|
|
dom::CanonicalBrowsingContext* top = browsingContext->Canonical()->Top();
|
|
dom::WindowGlobalParent* wgp = top->GetCurrentWindowGlobal();
|
|
if (!wgp) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
RefPtr<nsIURI> uri = wgp->GetDocumentURI();
|
|
if (!uri) {
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
CopyUTF8toUTF16(uri->GetSpecOrDefault(), aTopLevelUrl);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
UrlClassifierBlockedChannel::GetTables(nsACString& aTables) {
|
|
aTables.Assign(mTables);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
UrlClassifierBlockedChannel::GetIsPrivateBrowsing(bool* aIsPrivateBrowsing) {
|
|
NS_ENSURE_ARG_POINTER(aIsPrivateBrowsing);
|
|
|
|
*aIsPrivateBrowsing = NS_UsePrivateBrowsing(mChannel);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
UrlClassifierBlockedChannel::Allow() {
|
|
UC_LOG(("ChannelClassifierService: allow loading the channel %p",
|
|
mChannel.get()));
|
|
|
|
mDecision = ChannelBlockDecision::Allowed;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
UrlClassifierBlockedChannel::Unblock() {
|
|
UC_LOG(("ChannelClassifierService: unblock channel %p", mChannel.get()));
|
|
|
|
mDecision = ChannelBlockDecision::Unblocked;
|
|
return NS_OK;
|
|
}
|
|
|
|
void UrlClassifierBlockedChannel::SetReason(const nsACString& aFeatureName,
|
|
const nsACString& aTableName) {
|
|
mTables = aTableName;
|
|
|
|
nsCOMPtr<nsIUrlClassifierFeature> feature;
|
|
feature =
|
|
UrlClassifierFeatureTrackingProtection::GetIfNameMatches(aFeatureName);
|
|
if (feature) {
|
|
mReason = TRACKING_PROTECTION;
|
|
return;
|
|
}
|
|
|
|
feature = UrlClassifierFeatureSocialTrackingProtection::GetIfNameMatches(
|
|
aFeatureName);
|
|
if (feature) {
|
|
mReason = SOCIAL_TRACKING_PROTECTION;
|
|
return;
|
|
}
|
|
|
|
feature = UrlClassifierFeatureFingerprintingProtection::GetIfNameMatches(
|
|
aFeatureName);
|
|
if (feature) {
|
|
mReason = FINGERPRINTING_PROTECTION;
|
|
return;
|
|
}
|
|
|
|
feature = UrlClassifierFeatureCryptominingProtection::GetIfNameMatches(
|
|
aFeatureName);
|
|
if (feature) {
|
|
mReason = CRYPTOMINING_PROTECTION;
|
|
return;
|
|
}
|
|
}
|
|
|
|
NS_IMPL_ISUPPORTS(ChannelClassifierService, nsIChannelClassifierService)
|
|
|
|
// static
|
|
already_AddRefed<nsIChannelClassifierService>
|
|
ChannelClassifierService::GetSingleton() {
|
|
if (gChannelClassifierService) {
|
|
return do_AddRef(gChannelClassifierService);
|
|
}
|
|
|
|
gChannelClassifierService = new ChannelClassifierService();
|
|
ClearOnShutdown(&gChannelClassifierService);
|
|
return do_AddRef(gChannelClassifierService);
|
|
}
|
|
|
|
ChannelClassifierService::ChannelClassifierService() { mListeners.Clear(); }
|
|
|
|
NS_IMETHODIMP
|
|
ChannelClassifierService::AddListener(nsIObserver* aObserver) {
|
|
MOZ_ASSERT(aObserver);
|
|
MOZ_ASSERT(!mListeners.Contains(aObserver));
|
|
|
|
mListeners.AppendElement(aObserver);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
ChannelClassifierService::RemoveListener(nsIObserver* aObserver) {
|
|
MOZ_ASSERT(aObserver);
|
|
MOZ_ASSERT(mListeners.Contains(aObserver));
|
|
|
|
mListeners.RemoveElement(aObserver);
|
|
return NS_OK;
|
|
}
|
|
|
|
/* static */
|
|
ChannelBlockDecision ChannelClassifierService::OnBeforeBlockChannel(
|
|
nsIChannel* aChannel, const nsACString& aFeatureName,
|
|
const nsACString& aTableName) {
|
|
MOZ_ASSERT(aChannel);
|
|
|
|
// Don't bother continuing if no one has ever registered listener
|
|
if (!gChannelClassifierService || !gChannelClassifierService->HasListener()) {
|
|
return ChannelBlockDecision::Blocked;
|
|
}
|
|
|
|
ChannelBlockDecision decision;
|
|
nsresult rv = gChannelClassifierService->OnBeforeBlockChannel(
|
|
aChannel, aFeatureName, aTableName, decision);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return ChannelBlockDecision::Blocked;
|
|
}
|
|
|
|
return decision;
|
|
}
|
|
|
|
nsresult ChannelClassifierService::OnBeforeBlockChannel(
|
|
nsIChannel* aChannel, const nsACString& aFeatureName,
|
|
const nsACString& aTableName, ChannelBlockDecision& aDecision) {
|
|
MOZ_ASSERT(aChannel);
|
|
|
|
aDecision = ChannelBlockDecision::Blocked;
|
|
|
|
RefPtr<UrlClassifierBlockedChannel> channel =
|
|
new UrlClassifierBlockedChannel(aChannel);
|
|
channel->SetReason(aFeatureName, aTableName);
|
|
|
|
for (const auto& listener : mListeners) {
|
|
listener->Observe(
|
|
NS_ISUPPORTS_CAST(nsIUrlClassifierBlockedChannel*, channel),
|
|
"urlclassifier-before-block-channel", nullptr);
|
|
|
|
aDecision = channel->GetDecision();
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
} // namespace net
|
|
} // namespace mozilla
|