mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-22 01:35:35 +00:00
e9e7d608be
Similarly to nsITabParent, TabChild is exposed to frontend code via nsITabChild. It's not clear what the future of this interface will be, but for now we can just rename it to nsIBrowserChild. Differential Revision: https://phabricator.services.mozilla.com/D28134 --HG-- rename : dom/interfaces/base/nsITabChild.idl => dom/interfaces/base/nsIBrowserChild.idl extra : rebase_source : a6c42a661e35b19e46c60f6f6a6f3dab64c0a1bc extra : histedit_source : 1eb475bd840bf37a3f86294685c9b3c250684e79
216 lines
8.3 KiB
C++
216 lines
8.3 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
// vim: ft=cpp tw=80 sw=2 et ts=8
|
|
/* 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/. */
|
|
|
|
/*
|
|
* Implementation of the "@mozilla.org/layout/content-policy;1" contract.
|
|
*/
|
|
|
|
#include "mozilla/Logging.h"
|
|
|
|
#include "nsISupports.h"
|
|
#include "nsXPCOM.h"
|
|
#include "nsContentPolicyUtils.h"
|
|
#include "mozilla/dom/nsCSPService.h"
|
|
#include "nsContentPolicy.h"
|
|
#include "nsIURI.h"
|
|
#include "nsIDocShell.h"
|
|
#include "nsIDOMWindow.h"
|
|
#include "nsIBrowserChild.h"
|
|
#include "nsIContent.h"
|
|
#include "nsIImageLoadingContent.h"
|
|
#include "nsILoadContext.h"
|
|
#include "nsCOMArray.h"
|
|
#include "nsContentUtils.h"
|
|
#include "mozilla/dom/nsMixedContentBlocker.h"
|
|
#include "nsIContentSecurityPolicy.h"
|
|
#include "mozilla/dom/TabGroup.h"
|
|
#include "mozilla/TaskCategory.h"
|
|
|
|
using mozilla::LogLevel;
|
|
|
|
NS_IMPL_ISUPPORTS(nsContentPolicy, nsIContentPolicy)
|
|
|
|
static mozilla::LazyLogModule gConPolLog("nsContentPolicy");
|
|
|
|
nsresult NS_NewContentPolicy(nsIContentPolicy **aResult) {
|
|
*aResult = new nsContentPolicy;
|
|
NS_ADDREF(*aResult);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsContentPolicy::nsContentPolicy() : mPolicies(NS_CONTENTPOLICY_CATEGORY) {}
|
|
|
|
nsContentPolicy::~nsContentPolicy() {}
|
|
|
|
#ifdef DEBUG
|
|
# define WARN_IF_URI_UNINITIALIZED(uri, name) \
|
|
PR_BEGIN_MACRO \
|
|
if ((uri)) { \
|
|
nsAutoCString spec; \
|
|
(uri)->GetAsciiSpec(spec); \
|
|
if (spec.IsEmpty()) { \
|
|
NS_WARNING(name " is uninitialized, fix caller"); \
|
|
} \
|
|
} \
|
|
PR_END_MACRO
|
|
|
|
#else // ! defined(DEBUG)
|
|
|
|
# define WARN_IF_URI_UNINITIALIZED(uri, name)
|
|
|
|
#endif // defined(DEBUG)
|
|
|
|
inline nsresult nsContentPolicy::CheckPolicy(CPMethod policyMethod,
|
|
nsIURI *contentLocation,
|
|
nsILoadInfo *loadInfo,
|
|
const nsACString &mimeType,
|
|
int16_t *decision) {
|
|
nsContentPolicyType contentType = loadInfo->InternalContentPolicyType();
|
|
nsCOMPtr<nsISupports> requestingContext = loadInfo->GetLoadingContext();
|
|
nsCOMPtr<nsIPrincipal> requestPrincipal = loadInfo->TriggeringPrincipal();
|
|
nsCOMPtr<nsIURI> requestingLocation;
|
|
nsCOMPtr<nsIPrincipal> loadingPrincipal = loadInfo->LoadingPrincipal();
|
|
if (loadingPrincipal) {
|
|
loadingPrincipal->GetURI(getter_AddRefs(requestingLocation));
|
|
}
|
|
|
|
// sanity-check passed-through parameters
|
|
MOZ_ASSERT(decision, "Null out pointer");
|
|
WARN_IF_URI_UNINITIALIZED(contentLocation, "Request URI");
|
|
WARN_IF_URI_UNINITIALIZED(requestingLocation, "Requesting URI");
|
|
|
|
#ifdef DEBUG
|
|
{
|
|
nsCOMPtr<nsINode> node(do_QueryInterface(requestingContext));
|
|
nsCOMPtr<nsIDOMWindow> window(do_QueryInterface(requestingContext));
|
|
nsCOMPtr<nsIBrowserChild> browserChild(
|
|
do_QueryInterface(requestingContext));
|
|
NS_ASSERTION(!requestingContext || node || window || browserChild,
|
|
"Context should be a DOM node, DOM window or a browserChild!");
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* There might not be a requestinglocation. This can happen for
|
|
* iframes with an image as src. Get the uri from the dom node.
|
|
* See bug 254510
|
|
*/
|
|
if (!requestingLocation) {
|
|
nsCOMPtr<Document> doc;
|
|
nsCOMPtr<nsIContent> node = do_QueryInterface(requestingContext);
|
|
if (node) {
|
|
doc = node->OwnerDoc();
|
|
}
|
|
if (!doc) {
|
|
doc = do_QueryInterface(requestingContext);
|
|
}
|
|
if (doc) {
|
|
requestingLocation = doc->GetDocumentURI();
|
|
}
|
|
}
|
|
|
|
nsContentPolicyType externalType =
|
|
nsContentUtils::InternalContentPolicyTypeToExternal(contentType);
|
|
|
|
/*
|
|
* Enumerate mPolicies and ask each of them, taking the logical AND of
|
|
* their permissions.
|
|
*/
|
|
nsresult rv;
|
|
const nsCOMArray<nsIContentPolicy> &entries = mPolicies.GetCachedEntries();
|
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> window;
|
|
if (nsCOMPtr<nsINode> node = do_QueryInterface(requestingContext)) {
|
|
window = node->OwnerDoc()->GetWindow();
|
|
} else {
|
|
window = do_QueryInterface(requestingContext);
|
|
}
|
|
|
|
if (requestPrincipal) {
|
|
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
|
requestPrincipal->GetCsp(getter_AddRefs(csp));
|
|
if (csp && window) {
|
|
csp->EnsureEventTarget(
|
|
window->EventTargetFor(mozilla::TaskCategory::Other));
|
|
}
|
|
}
|
|
|
|
int32_t count = entries.Count();
|
|
for (int32_t i = 0; i < count; i++) {
|
|
/* check the appropriate policy */
|
|
rv = (entries[i]->*policyMethod)(contentLocation, loadInfo, mimeType,
|
|
decision);
|
|
|
|
if (NS_SUCCEEDED(rv) && NS_CP_REJECTED(*decision)) {
|
|
// If we are blocking an image, we have to let the
|
|
// ImageLoadingContent know that we blocked the load.
|
|
if (externalType == nsIContentPolicy::TYPE_IMAGE ||
|
|
externalType == nsIContentPolicy::TYPE_IMAGESET) {
|
|
nsCOMPtr<nsIImageLoadingContent> img =
|
|
do_QueryInterface(requestingContext);
|
|
if (img) {
|
|
img->SetBlockedRequest(*decision);
|
|
}
|
|
}
|
|
/* policy says no, no point continuing to check */
|
|
return NS_OK;
|
|
}
|
|
}
|
|
|
|
// everyone returned failure, or no policies: sanitize result
|
|
*decision = nsIContentPolicy::ACCEPT;
|
|
return NS_OK;
|
|
}
|
|
|
|
// uses the parameters from ShouldXYZ to produce and log a message
|
|
// logType must be a literal string constant
|
|
#define LOG_CHECK(logType) \
|
|
PR_BEGIN_MACRO \
|
|
nsCOMPtr<nsIURI> requestingLocation; \
|
|
nsCOMPtr<nsIPrincipal> loadingPrincipal = loadInfo->LoadingPrincipal(); \
|
|
if (loadingPrincipal) { \
|
|
loadingPrincipal->GetURI(getter_AddRefs(requestingLocation)); \
|
|
} \
|
|
/* skip all this nonsense if the call failed or logging is disabled */ \
|
|
if (NS_SUCCEEDED(rv) && MOZ_LOG_TEST(gConPolLog, LogLevel::Debug)) { \
|
|
const char *resultName; \
|
|
if (decision) { \
|
|
resultName = NS_CP_ResponseName(*decision); \
|
|
} else { \
|
|
resultName = "(null ptr)"; \
|
|
} \
|
|
MOZ_LOG( \
|
|
gConPolLog, LogLevel::Debug, \
|
|
("Content Policy: " logType ": <%s> <Ref:%s> result=%s", \
|
|
contentLocation ? contentLocation->GetSpecOrDefault().get() : "None", \
|
|
requestingLocation ? requestingLocation->GetSpecOrDefault().get() \
|
|
: "None", \
|
|
resultName)); \
|
|
} \
|
|
PR_END_MACRO
|
|
|
|
NS_IMETHODIMP
|
|
nsContentPolicy::ShouldLoad(nsIURI *contentLocation, nsILoadInfo *loadInfo,
|
|
const nsACString &mimeType, int16_t *decision) {
|
|
// ShouldProcess does not need a content location, but we do
|
|
MOZ_ASSERT(contentLocation, "Must provide request location");
|
|
nsresult rv = CheckPolicy(&nsIContentPolicy::ShouldLoad, contentLocation,
|
|
loadInfo, mimeType, decision);
|
|
LOG_CHECK("ShouldLoad");
|
|
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsContentPolicy::ShouldProcess(nsIURI *contentLocation, nsILoadInfo *loadInfo,
|
|
const nsACString &mimeType, int16_t *decision) {
|
|
nsresult rv = CheckPolicy(&nsIContentPolicy::ShouldProcess, contentLocation,
|
|
loadInfo, mimeType, decision);
|
|
LOG_CHECK("ShouldProcess");
|
|
|
|
return rv;
|
|
}
|