зеркало из https://github.com/mozilla/gecko-dev.git
Merge inbound to mozilla-central. a=merge
This commit is contained in:
Коммит
21df1f7413
|
@ -1396,12 +1396,13 @@ nsAccessibilityService::CreateAccessibleByFrameType(nsIFrame* aFrame,
|
|||
|
||||
if (table) {
|
||||
nsIContent* parentContent =
|
||||
aContent->GetParentOrHostNode()->AsContent();
|
||||
aContent->GetParentOrShadowHostNode()->AsContent();
|
||||
nsIFrame* parentFrame = nullptr;
|
||||
if (parentContent) {
|
||||
parentFrame = parentContent->GetPrimaryFrame();
|
||||
if (!parentFrame || !parentFrame->IsTableWrapperFrame()) {
|
||||
parentContent = parentContent->GetParentOrHostNode()->AsContent();
|
||||
parentContent =
|
||||
parentContent->GetParentOrShadowHostNode()->AsContent();
|
||||
if (parentContent) {
|
||||
parentFrame = parentContent->GetPrimaryFrame();
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ function test() {
|
|||
Services.prefs.clearUserPref(kpkpEnforcementPref);
|
||||
Services.prefs.clearUserPref(khpkpPinninEnablePref);
|
||||
let uri = Services.io.newURI("https://" + kPinningDomain);
|
||||
gSSService.removeState(Ci.nsISiteSecurityService.HEADER_HPKP, uri, 0);
|
||||
gSSService.resetState(Ci.nsISiteSecurityService.HEADER_HPKP, uri, 0);
|
||||
});
|
||||
whenNewTabLoaded(window, loadPinningPage);
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ add_task(async function test_star_redirect() {
|
|||
let sss = Cc["@mozilla.org/ssservice;1"].getService(
|
||||
Ci.nsISiteSecurityService
|
||||
);
|
||||
sss.removeState(
|
||||
sss.resetState(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
NetUtil.newURI("http://example.com/"),
|
||||
0
|
||||
|
|
|
@ -54,7 +54,7 @@ function startTest() {
|
|||
.getService(Ci.nsIIOService);
|
||||
for (let {url} of TEST_CASES) {
|
||||
let uri = gIOService.newURI(url);
|
||||
gSSService.removeState(Ci.nsISiteSecurityService.HEADER_HPKP, uri, 0);
|
||||
gSSService.resetState(Ci.nsISiteSecurityService.HEADER_HPKP, uri, 0);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ function startTest()
|
|||
.getService(Ci.nsIIOService);
|
||||
|
||||
let uri = gIOService.newURI(TEST_CASES[0].url);
|
||||
gSSService.removeState(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0);
|
||||
gSSService.resetState(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0);
|
||||
});
|
||||
|
||||
info("Test detection of HTTP Strict Transport Security.");
|
||||
|
|
|
@ -759,7 +759,7 @@ static nsINode* FindChromeAccessOnlySubtreeOwner(nsINode* aNode) {
|
|||
aNode = aNode->GetParentNode();
|
||||
}
|
||||
|
||||
return aNode ? aNode->GetParentOrHostNode() : nullptr;
|
||||
return aNode ? aNode->GetParentOrShadowHostNode() : nullptr;
|
||||
}
|
||||
|
||||
already_AddRefed<nsINode> FindChromeAccessOnlySubtreeOwner(
|
||||
|
@ -990,8 +990,8 @@ void nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor) {
|
|||
// dispatching event to Window object in a content page and
|
||||
// propagating the event to a chrome Element.
|
||||
if (targetInKnownToBeHandledScope &&
|
||||
nsContentUtils::ContentIsShadowIncludingDescendantOf(
|
||||
this, targetInKnownToBeHandledScope->SubtreeRoot())) {
|
||||
IsShadowIncludingInclusiveDescendantOf(
|
||||
targetInKnownToBeHandledScope->SubtreeRoot())) {
|
||||
// Part of step 11.4.
|
||||
// "If target's root is a shadow-including inclusive ancestor of
|
||||
// parent, then"
|
||||
|
|
|
@ -2200,32 +2200,6 @@ bool nsContentUtils::ContentIsHostIncludingDescendantOf(
|
|||
return false;
|
||||
}
|
||||
|
||||
bool nsContentUtils::ContentIsShadowIncludingDescendantOf(
|
||||
const nsINode* aPossibleDescendant, const nsINode* aPossibleAncestor) {
|
||||
MOZ_ASSERT(aPossibleDescendant, "The possible descendant is null!");
|
||||
MOZ_ASSERT(aPossibleAncestor, "The possible ancestor is null!");
|
||||
|
||||
if (aPossibleAncestor == aPossibleDescendant->GetComposedDoc()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
do {
|
||||
if (aPossibleDescendant == aPossibleAncestor) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (aPossibleDescendant->NodeType() == nsINode::DOCUMENT_FRAGMENT_NODE) {
|
||||
ShadowRoot* shadowRoot =
|
||||
ShadowRoot::FromNode(const_cast<nsINode*>(aPossibleDescendant));
|
||||
aPossibleDescendant = shadowRoot ? shadowRoot->GetHost() : nullptr;
|
||||
} else {
|
||||
aPossibleDescendant = aPossibleDescendant->GetParentNode();
|
||||
}
|
||||
} while (aPossibleDescendant);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// static
|
||||
bool nsContentUtils::ContentIsCrossDocDescendantOf(nsINode* aPossibleDescendant,
|
||||
nsINode* aPossibleAncestor) {
|
||||
|
@ -2285,7 +2259,7 @@ nsINode* nsContentUtils::Retarget(nsINode* aTargetA, nsINode* aTargetB) {
|
|||
}
|
||||
|
||||
// or A's root is a shadow-including inclusive ancestor of B...
|
||||
if (nsContentUtils::ContentIsShadowIncludingDescendantOf(aTargetB, root)) {
|
||||
if (aTargetB->IsShadowIncludingInclusiveDescendantOf(root)) {
|
||||
// ...then return A.
|
||||
return aTargetA;
|
||||
}
|
||||
|
|
|
@ -344,13 +344,6 @@ class nsContentUtils {
|
|||
static bool ContentIsHostIncludingDescendantOf(
|
||||
const nsINode* aPossibleDescendant, const nsINode* aPossibleAncestor);
|
||||
|
||||
/**
|
||||
* Similar to above, but does special case only ShadowRoot,
|
||||
* not HTMLTemplateElement.
|
||||
*/
|
||||
static bool ContentIsShadowIncludingDescendantOf(
|
||||
const nsINode* aPossibleDescendant, const nsINode* aPossibleAncestor);
|
||||
|
||||
/**
|
||||
* Similar to nsINode::IsInclusiveDescendantOf except it crosses document
|
||||
* boundaries, this function uses ancestor/descendant relations in the
|
||||
|
|
|
@ -131,6 +131,26 @@ bool nsINode::IsInclusiveDescendantOf(const nsINode* aNode) const {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool nsINode::IsShadowIncludingInclusiveDescendantOf(
|
||||
const nsINode* aNode) const {
|
||||
MOZ_ASSERT(aNode, "The node is nullptr.");
|
||||
|
||||
if (this->GetComposedDoc() == aNode) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const nsINode* node = this;
|
||||
do {
|
||||
if (node == aNode) {
|
||||
return true;
|
||||
}
|
||||
|
||||
node = node->GetParentOrShadowHostNode();
|
||||
} while (node);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
nsINode::nsSlots::nsSlots() : mWeakReference(nullptr) {}
|
||||
|
||||
nsINode::nsSlots::~nsSlots() {
|
||||
|
@ -261,7 +281,7 @@ nsINode* nsINode::GetRootNode(const GetRootNodeOptions& aOptions) {
|
|||
return SubtreeRoot();
|
||||
}
|
||||
|
||||
nsINode* nsINode::GetParentOrHostNode() const {
|
||||
nsINode* nsINode::GetParentOrShadowHostNode() const {
|
||||
if (mParent) {
|
||||
return mParent;
|
||||
}
|
||||
|
|
|
@ -424,6 +424,13 @@ class nsINode : public mozilla::dom::EventTarget {
|
|||
*/
|
||||
bool IsInclusiveDescendantOf(const nsINode* aNode) const;
|
||||
|
||||
/**
|
||||
* https://dom.spec.whatwg.org/#concept-shadow-including-inclusive-descendant
|
||||
*
|
||||
* @param aNode must not be nullptr.
|
||||
*/
|
||||
bool IsShadowIncludingInclusiveDescendantOf(const nsINode* aNode) const;
|
||||
|
||||
/**
|
||||
* Return this node as a document fragment. Asserts IsDocumentFragment().
|
||||
*
|
||||
|
@ -884,11 +891,7 @@ class nsINode : public mozilla::dom::EventTarget {
|
|||
*/
|
||||
nsINode* GetParentNode() const { return mParent; }
|
||||
|
||||
/**
|
||||
* This is similar to above, but in case 'this' is ShadowRoot, we return its
|
||||
* host element.
|
||||
*/
|
||||
nsINode* GetParentOrHostNode() const;
|
||||
nsINode* GetParentOrShadowHostNode() const;
|
||||
|
||||
enum FlattenedParentType { eNotForStyle, eForStyle };
|
||||
|
||||
|
|
|
@ -114,6 +114,7 @@ BrowserParent* BrowserBridgeParent::Manager() {
|
|||
void BrowserBridgeParent::Destroy() {
|
||||
if (mBrowserParent) {
|
||||
mBrowserParent->Destroy();
|
||||
mBrowserParent->SetBrowserBridgeParent(nullptr);
|
||||
mBrowserParent = nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#include "mozilla/dom/CancelContentJSOptionsBinding.h"
|
||||
#include "mozilla/dom/WindowGlobalParent.h"
|
||||
|
||||
#include "nsIObserverService.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
|
@ -68,7 +70,14 @@ void BrowserHost::DestroyComplete() {
|
|||
}
|
||||
mRoot->SetOwnerElement(nullptr);
|
||||
mRoot->Destroy();
|
||||
mRoot->SetBrowserHost(nullptr);
|
||||
mRoot = nullptr;
|
||||
|
||||
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
||||
if (os) {
|
||||
os->NotifyObservers(NS_ISUPPORTS_CAST(nsIRemoteTab*, this),
|
||||
"ipc:browser-destroyed", nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
bool BrowserHost::Show(const ScreenIntSize& aSize, bool aParentIsActive) {
|
||||
|
|
|
@ -675,7 +675,6 @@ void BrowserParent::ActorDestroy(ActorDestroyReason why) {
|
|||
// Tell our embedder that the tab is now going away unless we're an
|
||||
// out-of-process iframe.
|
||||
RefPtr<nsFrameLoader> frameLoader = GetFrameLoader(true);
|
||||
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
||||
if (frameLoader) {
|
||||
ReceiveMessage(CHILD_PROCESS_SHUTDOWN_MESSAGE, false, nullptr, nullptr,
|
||||
nullptr);
|
||||
|
@ -694,10 +693,6 @@ void BrowserParent::ActorDestroy(ActorDestroyReason why) {
|
|||
}
|
||||
|
||||
mFrameLoader = nullptr;
|
||||
if (os && mBrowserHost) {
|
||||
os->NotifyObservers(NS_ISUPPORTS_CAST(nsIRemoteTab*, mBrowserHost),
|
||||
"ipc:browser-destroyed", nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult BrowserParent::RecvMoveFocus(
|
||||
|
@ -3712,20 +3707,18 @@ void BrowserParent::LiveResizeStarted() { SuppressDisplayport(true); }
|
|||
void BrowserParent::LiveResizeStopped() { SuppressDisplayport(false); }
|
||||
|
||||
void BrowserParent::SetBrowserBridgeParent(BrowserBridgeParent* aBrowser) {
|
||||
// We should not have either a browser bridge or browser host yet
|
||||
MOZ_ASSERT(!mBrowserBridgeParent);
|
||||
MOZ_ASSERT(!mBrowserHost);
|
||||
// We should not have owner content yet
|
||||
MOZ_ASSERT(!mFrameElement);
|
||||
// We should either be clearing out our reference to a browser bridge, or not
|
||||
// have either a browser bridge, browser host, or owner content yet.
|
||||
MOZ_ASSERT(!aBrowser ||
|
||||
(!mBrowserBridgeParent && !mBrowserHost && !mFrameElement));
|
||||
mBrowserBridgeParent = aBrowser;
|
||||
}
|
||||
|
||||
void BrowserParent::SetBrowserHost(BrowserHost* aBrowser) {
|
||||
// We should not have either a browser bridge or browser host yet
|
||||
MOZ_ASSERT(!mBrowserBridgeParent);
|
||||
MOZ_ASSERT(!mBrowserHost);
|
||||
// We should not have owner content yet
|
||||
MOZ_ASSERT(!mFrameElement);
|
||||
// We should either be clearing out our reference to a browser host, or not
|
||||
// have either a browser bridge, browser host, or owner content yet.
|
||||
MOZ_ASSERT(!aBrowser ||
|
||||
(!mBrowserBridgeParent && !mBrowserHost && !mFrameElement));
|
||||
mBrowserHost = aBrowser;
|
||||
}
|
||||
|
||||
|
|
|
@ -244,8 +244,8 @@ bool SVGUseElement::IsCyclicReferenceTo(const Element& aTarget) const {
|
|||
if (mOriginal && mOriginal->IsCyclicReferenceTo(aTarget)) {
|
||||
return true;
|
||||
}
|
||||
for (nsINode* parent = GetParentOrHostNode(); parent;
|
||||
parent = parent->GetParentOrHostNode()) {
|
||||
for (nsINode* parent = GetParentOrShadowHostNode(); parent;
|
||||
parent = parent->GetParentOrShadowHostNode()) {
|
||||
if (parent == &aTarget) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -10048,7 +10048,7 @@ nsresult HTMLEditRules::ConfirmSelectionInBody() {
|
|||
// XXXsmaug this code is insane.
|
||||
nsINode* temp = selectionStartPoint.GetContainer();
|
||||
while (temp && !temp->IsHTMLElement(nsGkAtoms::body)) {
|
||||
temp = temp->GetParentOrHostNode();
|
||||
temp = temp->GetParentOrShadowHostNode();
|
||||
}
|
||||
|
||||
// If we aren't in the <body> element, force the issue.
|
||||
|
@ -10074,7 +10074,7 @@ nsresult HTMLEditRules::ConfirmSelectionInBody() {
|
|||
// XXXsmaug this code is insane.
|
||||
temp = selectionEndPoint.GetContainer();
|
||||
while (temp && !temp->IsHTMLElement(nsGkAtoms::body)) {
|
||||
temp = temp->GetParentOrHostNode();
|
||||
temp = temp->GetParentOrShadowHostNode();
|
||||
}
|
||||
|
||||
// If we aren't in the <body> element, force the issue.
|
||||
|
|
|
@ -222,8 +222,7 @@ nsresult mozInlineSpellStatus::InitForNavigation(
|
|||
}
|
||||
// the anchor node might not be in the DOM anymore, check
|
||||
if (root && aOldAnchorNode &&
|
||||
!nsContentUtils::ContentIsShadowIncludingDescendantOf(aOldAnchorNode,
|
||||
root)) {
|
||||
!aOldAnchorNode->IsShadowIncludingInclusiveDescendantOf(root)) {
|
||||
*aContinue = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1271,10 +1270,8 @@ nsresult mozInlineSpellChecker::DoSpellCheck(
|
|||
// aWordUtil.GetRootNode()
|
||||
nsINode* rootNode = aWordUtil.GetRootNode();
|
||||
if (!beginNode->IsInComposedDoc() || !endNode->IsInComposedDoc() ||
|
||||
!nsContentUtils::ContentIsShadowIncludingDescendantOf(beginNode,
|
||||
rootNode) ||
|
||||
!nsContentUtils::ContentIsShadowIncludingDescendantOf(endNode,
|
||||
rootNode)) {
|
||||
!beginNode->IsShadowIncludingInclusiveDescendantOf(rootNode) ||
|
||||
!endNode->IsShadowIncludingInclusiveDescendantOf(rootNode)) {
|
||||
// Just bail out and don't try to spell-check this
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -4725,7 +4725,7 @@ UniquePtr<RangePaintInfo> PresShell::CreateRangePaintInfo(
|
|||
break;
|
||||
}
|
||||
|
||||
ancestor = ancestor->GetParentOrHostNode();
|
||||
ancestor = ancestor->GetParentOrShadowHostNode();
|
||||
}
|
||||
|
||||
// use the nearest ancestor frame that includes all continuations as the
|
||||
|
|
|
@ -1669,7 +1669,7 @@ int32_t nsLayoutUtils::DoCompareTreePosition(
|
|||
AutoTArray<nsINode*, 32> content1Ancestors;
|
||||
nsINode* c1;
|
||||
for (c1 = aContent1; c1 && c1 != aCommonAncestor;
|
||||
c1 = c1->GetParentOrHostNode()) {
|
||||
c1 = c1->GetParentOrShadowHostNode()) {
|
||||
content1Ancestors.AppendElement(c1);
|
||||
}
|
||||
if (!c1 && aCommonAncestor) {
|
||||
|
@ -1681,7 +1681,7 @@ int32_t nsLayoutUtils::DoCompareTreePosition(
|
|||
AutoTArray<nsINode*, 32> content2Ancestors;
|
||||
nsINode* c2;
|
||||
for (c2 = aContent2; c2 && c2 != aCommonAncestor;
|
||||
c2 = c2->GetParentOrHostNode()) {
|
||||
c2 = c2->GetParentOrShadowHostNode()) {
|
||||
content2Ancestors.AppendElement(c2);
|
||||
}
|
||||
if (!c2 && aCommonAncestor) {
|
||||
|
@ -1718,7 +1718,7 @@ int32_t nsLayoutUtils::DoCompareTreePosition(
|
|||
|
||||
// content1Ancestor != content2Ancestor, so they must be siblings with the
|
||||
// same parent
|
||||
nsINode* parent = content1Ancestor->GetParentOrHostNode();
|
||||
nsINode* parent = content1Ancestor->GetParentOrShadowHostNode();
|
||||
#ifdef DEBUG
|
||||
// TODO: remove the uglyness, see bug 598468.
|
||||
NS_ASSERTION(gPreventAssertInCompareTreePosition || parent,
|
||||
|
|
|
@ -160,10 +160,13 @@ interface nsISiteSecurityService : nsISupports
|
|||
[optional] out uint32_t aFailureResult);
|
||||
|
||||
/**
|
||||
* Given a header type, removes state relating to that header of a host,
|
||||
* Given a header type, resets state relating to that header of a host,
|
||||
* including the includeSubdomains state that would affect subdomains.
|
||||
* This essentially removes the state for the domain tree rooted at this
|
||||
* host.
|
||||
* host. If any preloaded information is present for that host, that
|
||||
* information will then be used instead of any other previously existing
|
||||
* state.
|
||||
*
|
||||
* @param aType the type of security state in question
|
||||
* @param aURI the URI of the target host
|
||||
* @param aFlags options for this request as defined in nsISocketProvider:
|
||||
|
@ -175,10 +178,10 @@ interface nsISiteSecurityService : nsISupports
|
|||
* happens).
|
||||
*/
|
||||
[implicit_jscontext, optional_argc, must_use]
|
||||
void removeState(in uint32_t aType,
|
||||
in nsIURI aURI,
|
||||
in uint32_t aFlags,
|
||||
[optional] in jsval aOriginAttributes);
|
||||
void resetState(in uint32_t aType,
|
||||
in nsIURI aURI,
|
||||
in uint32_t aFlags,
|
||||
[optional] in jsval aOriginAttributes);
|
||||
|
||||
/**
|
||||
* Checks whether or not the URI's hostname has a given security state set.
|
||||
|
|
|
@ -557,11 +557,12 @@ nsresult nsSiteSecurityService::SetHSTSState(
|
|||
SecurityPropertySource aSource, const OriginAttributes& aOriginAttributes) {
|
||||
nsAutoCString hostname(aHost);
|
||||
bool isPreload = (aSource == SourcePreload);
|
||||
// If max-age is zero, that's an indication to immediately remove the
|
||||
// security state, so here's a shortcut.
|
||||
if (!maxage) {
|
||||
return RemoveStateInternal(aType, hostname, flags, isPreload,
|
||||
aOriginAttributes);
|
||||
// If max-age is zero, the host is no longer considered HSTS. If the host was
|
||||
// preloaded, we store an entry indicating that this host is not HSTS, causing
|
||||
// the preloaded information to be ignored.
|
||||
if (maxage == 0) {
|
||||
return MarkHostAsNotHSTS(aType, hostname, flags, isPreload,
|
||||
aOriginAttributes);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(
|
||||
|
@ -608,28 +609,17 @@ nsresult nsSiteSecurityService::SetHSTSState(
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsSiteSecurityService::RemoveStateInternal(
|
||||
uint32_t aType, nsIURI* aURI, uint32_t aFlags,
|
||||
const OriginAttributes& aOriginAttributes) {
|
||||
nsAutoCString hostname;
|
||||
GetHost(aURI, hostname);
|
||||
return RemoveStateInternal(aType, hostname, aFlags, false, aOriginAttributes);
|
||||
}
|
||||
|
||||
nsresult nsSiteSecurityService::RemoveStateInternal(
|
||||
// Helper function to mark a host as not HSTS. In the general case, we can just
|
||||
// remove the HSTS state. However, for preloaded entries, we have to store an
|
||||
// entry that indicates this host is not HSTS to prevent the implementation
|
||||
// using the preloaded information.
|
||||
nsresult nsSiteSecurityService::MarkHostAsNotHSTS(
|
||||
uint32_t aType, const nsAutoCString& aHost, uint32_t aFlags,
|
||||
bool aIsPreload, const OriginAttributes& aOriginAttributes) {
|
||||
// Child processes are not allowed direct access to this.
|
||||
if (!XRE_IsParentProcess()) {
|
||||
MOZ_CRASH(
|
||||
"Child process: no direct access to "
|
||||
"nsISiteSecurityService::RemoveStateInternal");
|
||||
// This only applies to HSTS.
|
||||
if (aType != nsISiteSecurityService::HEADER_HSTS) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
// Only HSTS is supported at the moment.
|
||||
NS_ENSURE_TRUE(aType == nsISiteSecurityService::HEADER_HSTS ||
|
||||
aType == nsISiteSecurityService::HEADER_HPKP,
|
||||
NS_ERROR_NOT_IMPLEMENTED);
|
||||
if (aIsPreload && aOriginAttributes != OriginAttributes()) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
@ -638,7 +628,6 @@ nsresult nsSiteSecurityService::RemoveStateInternal(
|
|||
mozilla::DataStorageType storageType = isPrivate
|
||||
? mozilla::DataStorage_Private
|
||||
: mozilla::DataStorage_Persistent;
|
||||
// If this host is in the preload list, we have to store a knockout entry.
|
||||
nsAutoCString storageKey;
|
||||
SetStorageKey(aHost, aType, aOriginAttributes, storageKey);
|
||||
|
||||
|
@ -675,10 +664,18 @@ nsresult nsSiteSecurityService::RemoveStateInternal(
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSiteSecurityService::RemoveState(uint32_t aType, nsIURI* aURI,
|
||||
uint32_t aFlags,
|
||||
JS::HandleValue aOriginAttributes,
|
||||
JSContext* aCx, uint8_t aArgc) {
|
||||
nsSiteSecurityService::ResetState(uint32_t aType, nsIURI* aURI, uint32_t aFlags,
|
||||
JS::HandleValue aOriginAttributes,
|
||||
JSContext* aCx, uint8_t aArgc) {
|
||||
if (!XRE_IsParentProcess()) {
|
||||
MOZ_CRASH(
|
||||
"Child process: no direct access to "
|
||||
"nsISiteSecurityService::ResetState");
|
||||
}
|
||||
if (!aURI) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
OriginAttributes originAttributes;
|
||||
if (aArgc > 0) {
|
||||
// OriginAttributes were passed in.
|
||||
|
@ -687,7 +684,39 @@ nsSiteSecurityService::RemoveState(uint32_t aType, nsIURI* aURI,
|
|||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
return RemoveStateInternal(aType, aURI, aFlags, originAttributes);
|
||||
|
||||
return ResetStateInternal(aType, aURI, aFlags, originAttributes);
|
||||
}
|
||||
|
||||
// Helper function to reset stored state of the given type for the host
|
||||
// identified by the given URI. If there is preloaded information for the host,
|
||||
// that information will be used for future queries. C.f. MarkHostAsNotHSTS,
|
||||
// which will store a knockout entry for preloaded HSTS hosts that have sent a
|
||||
// header with max-age=0 (meaning preloaded information will then not be used
|
||||
// for that host).
|
||||
nsresult nsSiteSecurityService::ResetStateInternal(
|
||||
uint32_t aType, nsIURI* aURI, uint32_t aFlags,
|
||||
const OriginAttributes& aOriginAttributes) {
|
||||
if (!aURI) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
if (aType != nsISiteSecurityService::HEADER_HSTS &&
|
||||
aType != nsISiteSecurityService::HEADER_HPKP) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
nsAutoCString hostname;
|
||||
nsresult rv = GetHost(aURI, hostname);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
nsAutoCString storageKey;
|
||||
SetStorageKey(hostname, aType, aOriginAttributes, storageKey);
|
||||
bool isPrivate = aFlags & nsISocketProvider::NO_PERMANENT_STORAGE;
|
||||
mozilla::DataStorageType storageType = isPrivate
|
||||
? mozilla::DataStorage_Private
|
||||
: mozilla::DataStorage_Persistent;
|
||||
mSiteStateStorage->Remove(storageKey, storageType);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static bool HostIsIPAddress(const nsCString& hostname) {
|
||||
|
@ -1062,9 +1091,12 @@ nsresult nsSiteSecurityService::ProcessPKPHeader(
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// if maxAge == 0 we must delete all state, for now no hole-punching
|
||||
// If maxAge == 0, we remove dynamic HPKP state for this host. Due to
|
||||
// architectural constraints, if this host was preloaded, any future lookups
|
||||
// will use the preloaded state (i.e. we can't store a "this host is not HPKP"
|
||||
// entry like we can for HSTS).
|
||||
if (maxAge == 0) {
|
||||
return RemoveStateInternal(aType, aSourceURI, aFlags, aOriginAttributes);
|
||||
return ResetStateInternal(aType, aSourceURI, aFlags, aOriginAttributes);
|
||||
}
|
||||
|
||||
// clamp maxAge to the maximum set by pref
|
||||
|
|
|
@ -191,11 +191,11 @@ class nsSiteSecurityService : public nsISiteSecurityService,
|
|||
nsresult SetHPKPState(const char* aHost, SiteHPKPState& entry, uint32_t flags,
|
||||
bool aIsPreload,
|
||||
const OriginAttributes& aOriginAttributes);
|
||||
nsresult RemoveStateInternal(uint32_t aType, nsIURI* aURI, uint32_t aFlags,
|
||||
const OriginAttributes& aOriginAttributes);
|
||||
nsresult RemoveStateInternal(uint32_t aType, const nsAutoCString& aHost,
|
||||
uint32_t aFlags, bool aIsPreload,
|
||||
const OriginAttributes& aOriginAttributes);
|
||||
nsresult MarkHostAsNotHSTS(uint32_t aType, const nsAutoCString& aHost,
|
||||
uint32_t aFlags, bool aIsPreload,
|
||||
const OriginAttributes& aOriginAttributes);
|
||||
nsresult ResetStateInternal(uint32_t aType, nsIURI* aURI, uint32_t aFlags,
|
||||
const OriginAttributes& aOriginAttributes);
|
||||
bool HostHasHSTSEntry(const nsAutoCString& aHost,
|
||||
bool aRequireIncludeSubdomains, uint32_t aFlags,
|
||||
const OriginAttributes& aOriginAttributes,
|
||||
|
|
|
@ -93,7 +93,7 @@ function test() {
|
|||
aWin.close();
|
||||
});
|
||||
uri = Services.io.newURI("http://localhost");
|
||||
gSSService.removeState(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0);
|
||||
gSSService.resetState(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0);
|
||||
});
|
||||
|
||||
// test first when on private mode
|
||||
|
|
|
@ -69,7 +69,7 @@ function add_tests() {
|
|||
);
|
||||
|
||||
// Clear accumulated state.
|
||||
ssservice.removeState(Ci.nsISiteSecurityService.HEADER_HPKP, uri, 0);
|
||||
ssservice.resetState(Ci.nsISiteSecurityService.HEADER_HPKP, uri, 0);
|
||||
Services.prefs.clearUserPref(
|
||||
"security.cert_pinning.process_headers_from_non_builtin_roots"
|
||||
);
|
||||
|
|
|
@ -55,7 +55,7 @@ function checkPassValidPin(pinValue, settingPin, expectedMaxAge) {
|
|||
// setup preconditions for the test, if setting ensure there is no previous
|
||||
// state, if removing ensure there is a valid pin in place.
|
||||
if (settingPin) {
|
||||
gSSService.removeState(Ci.nsISiteSecurityService.HEADER_HPKP, uri, 0);
|
||||
gSSService.resetState(Ci.nsISiteSecurityService.HEADER_HPKP, uri, 0);
|
||||
} else {
|
||||
// add a known valid pin!
|
||||
let validPinValue = "max-age=5000;" + VALID_PIN1 + BACKUP_PIN1;
|
||||
|
|
|
@ -83,7 +83,7 @@ function doTest(originAttributes1, originAttributes2, shouldShare) {
|
|||
|
||||
if (!shouldShare) {
|
||||
// Remove originAttributes2 from the storage.
|
||||
sss.removeState(type, uri, 0, originAttributes2);
|
||||
sss.resetState(type, uri, 0, originAttributes2);
|
||||
ok(
|
||||
sss.isSecureURI(type, uri, 0, originAttributes1),
|
||||
"URI should still be secure given original origin attributes"
|
||||
|
@ -91,7 +91,7 @@ function doTest(originAttributes1, originAttributes2, shouldShare) {
|
|||
}
|
||||
|
||||
// Remove originAttributes1 from the storage.
|
||||
sss.removeState(type, uri, 0, originAttributes1);
|
||||
sss.resetState(type, uri, 0, originAttributes1);
|
||||
ok(
|
||||
!sss.isSecureURI(type, uri, 0, originAttributes1),
|
||||
"URI should be not be secure after removeState"
|
||||
|
@ -161,7 +161,7 @@ function testInvalidOriginAttributes(originAttributes) {
|
|||
originAttributes
|
||||
),
|
||||
() => sss.isSecureURI(type, uri, 0, originAttributes),
|
||||
() => sss.removeState(type, uri, 0, originAttributes),
|
||||
() => sss.resetState(type, uri, 0, originAttributes),
|
||||
];
|
||||
|
||||
for (let callback of callbacks) {
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
|
||||
// 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/.
|
||||
|
||||
"use strict";
|
||||
|
||||
// Tests that resetting HSTS/HPKP state in the way the "forget about this site"
|
||||
// functionality does works as expected for preloaded and non-preloaded sites.
|
||||
|
||||
do_get_profile();
|
||||
|
||||
var gCertDB = Cc["@mozilla.org/security/x509certdb;1"].getService(
|
||||
Ci.nsIX509CertDB
|
||||
);
|
||||
const ROOT_CERT = addCertFromFile(gCertDB, "bad_certs/test-ca.pem", "CTu,,");
|
||||
|
||||
var gSSService = Cc["@mozilla.org/ssservice;1"].getService(
|
||||
Ci.nsISiteSecurityService
|
||||
);
|
||||
|
||||
function run_test() {
|
||||
Services.prefs.setBoolPref(
|
||||
"security.cert_pinning.process_headers_from_non_builtin_roots",
|
||||
true
|
||||
);
|
||||
test_removeState(Ci.nsISiteSecurityService.HEADER_HSTS, 0);
|
||||
test_removeState(
|
||||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Ci.nsISocketProvider.NO_PERMANENT_STORAGE
|
||||
);
|
||||
test_removeState(Ci.nsISiteSecurityService.HEADER_HPKP, 0);
|
||||
test_removeState(
|
||||
Ci.nsISiteSecurityService.HEADER_HPKP,
|
||||
Ci.nsISocketProvider.NO_PERMANENT_STORAGE
|
||||
);
|
||||
}
|
||||
|
||||
function test_removeState(type, flags) {
|
||||
info(`running test_removeState(type=${type}, flags=${flags})`);
|
||||
const NON_ISSUED_KEY_HASH = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
|
||||
const PINNING_ROOT_KEY_HASH = "VCIlmPM9NkgFQtrs4Oa5TeFcDu6MWRTKSNdePEhOgD8=";
|
||||
const PINNING_HEADERS = `pin-sha256="${NON_ISSUED_KEY_HASH}"; pin-sha256="${PINNING_ROOT_KEY_HASH}"`;
|
||||
let headerAddendum =
|
||||
type == Ci.nsISiteSecurityService.HEADER_HPKP ? PINNING_HEADERS : "";
|
||||
let secInfo = new FakeTransportSecurityInfo(
|
||||
constructCertFromFile("bad_certs/default-ee.pem")
|
||||
);
|
||||
// Simulate visiting a non-preloaded site by processing an HSTS or HPKP header
|
||||
// (depending on which type we were given), check that the HSTS/HPKP bit gets
|
||||
// set, simulate "forget about this site" (call removeState), and then check
|
||||
// that the HSTS/HPKP bit isn't set.
|
||||
let notPreloadedURI = Services.io.newURI("https://not-preloaded.example.com");
|
||||
ok(!gSSService.isSecureURI(type, notPreloadedURI, flags));
|
||||
gSSService.processHeader(
|
||||
type,
|
||||
notPreloadedURI,
|
||||
"max-age=1000;" + headerAddendum,
|
||||
secInfo,
|
||||
flags,
|
||||
Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST
|
||||
);
|
||||
ok(gSSService.isSecureURI(type, notPreloadedURI, flags));
|
||||
gSSService.resetState(type, notPreloadedURI, flags);
|
||||
ok(!gSSService.isSecureURI(type, notPreloadedURI, flags));
|
||||
|
||||
// Simulate visiting a non-preloaded site that unsets HSTS/HPKP by processing
|
||||
// an HSTS/HPKP header with "max-age=0", check that the HSTS/HPKP bit isn't
|
||||
// set, simulate "forget about this site" (call removeState), and then check
|
||||
// that the HSTS/HPKP bit isn't set.
|
||||
gSSService.processHeader(
|
||||
type,
|
||||
notPreloadedURI,
|
||||
"max-age=0;" + headerAddendum,
|
||||
secInfo,
|
||||
flags,
|
||||
Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST
|
||||
);
|
||||
ok(!gSSService.isSecureURI(type, notPreloadedURI, flags));
|
||||
gSSService.resetState(type, notPreloadedURI, flags);
|
||||
ok(!gSSService.isSecureURI(type, notPreloadedURI, flags));
|
||||
|
||||
// Simulate visiting a preloaded site by processing an HSTS/HPKP header, check
|
||||
// that the HSTS/HPKP bit is still set, simulate "forget about this site"
|
||||
// (call removeState), and then check that the HSTS/HPKP bit is still set.
|
||||
let preloadedHost =
|
||||
type == Ci.nsISiteSecurityService.HEADER_HPKP
|
||||
? "include-subdomains.pinning.example.com"
|
||||
: "includesubdomains.preloaded.test";
|
||||
let preloadedURI = Services.io.newURI(`https://${preloadedHost}`);
|
||||
ok(gSSService.isSecureURI(type, preloadedURI, flags));
|
||||
gSSService.processHeader(
|
||||
type,
|
||||
preloadedURI,
|
||||
"max-age=1000;" + headerAddendum,
|
||||
secInfo,
|
||||
flags,
|
||||
Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST
|
||||
);
|
||||
ok(gSSService.isSecureURI(type, preloadedURI, flags));
|
||||
gSSService.resetState(type, preloadedURI, flags);
|
||||
ok(gSSService.isSecureURI(type, preloadedURI, flags));
|
||||
|
||||
// Simulate visiting a preloaded site that unsets HSTS/HPKP by processing an
|
||||
// HSTS/HPKP header with "max-age=0", check that the HSTS/HPKP bit is what we
|
||||
// expect (see below), simulate "forget about this site" (call removeState),
|
||||
// and then check that the HSTS/HPKP bit is set.
|
||||
gSSService.processHeader(
|
||||
type,
|
||||
preloadedURI,
|
||||
"max-age=0;" + headerAddendum,
|
||||
secInfo,
|
||||
flags,
|
||||
Ci.nsISiteSecurityService.SOURCE_ORGANIC_REQUEST
|
||||
);
|
||||
// Due to architectural constraints, encountering a "max-age=0" header for a
|
||||
// preloaded HPKP site does not mark that site as not HPKP (whereas with HSTS,
|
||||
// it does).
|
||||
if (type == Ci.nsISiteSecurityService.HEADER_HPKP) {
|
||||
ok(gSSService.isSecureURI(type, preloadedURI, flags));
|
||||
} else {
|
||||
ok(!gSSService.isSecureURI(type, preloadedURI, flags));
|
||||
}
|
||||
gSSService.resetState(type, preloadedURI, flags);
|
||||
ok(gSSService.isSecureURI(type, preloadedURI, flags));
|
||||
}
|
|
@ -29,7 +29,7 @@ function run_test() {
|
|||
ok(SSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri1, 0));
|
||||
ok(SSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri2, 0));
|
||||
|
||||
SSService.removeState(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0);
|
||||
SSService.resetState(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0);
|
||||
ok(!SSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri, 0));
|
||||
ok(!SSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri1, 0));
|
||||
ok(!SSService.isSecureURI(Ci.nsISiteSecurityService.HEADER_HSTS, uri2, 0));
|
||||
|
|
|
@ -199,6 +199,7 @@ skip-if = toolkit == 'android'
|
|||
[test_sss_readstate_empty.js]
|
||||
[test_sss_readstate_garbage.js]
|
||||
[test_sss_readstate_huge.js]
|
||||
[test_sss_resetState.js]
|
||||
[test_sss_savestate.js]
|
||||
[test_sss_sanitizeOnShutdown.js]
|
||||
firefox-appdir = browser
|
||||
|
|
|
@ -705,7 +705,7 @@ class SpecialPowersAPIParent extends JSWindowActorParent {
|
|||
let sss = Cc["@mozilla.org/ssservice;1"].getService(
|
||||
Ci.nsISiteSecurityService
|
||||
);
|
||||
sss.removeState(Ci.nsISiteSecurityService.HEADER_HSTS, uri, flags);
|
||||
sss.resetState(Ci.nsISiteSecurityService.HEADER_HSTS, uri, flags);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
|
|
@ -920,14 +920,14 @@ const SecuritySettingsCleaner = {
|
|||
Ci.nsISiteSecurityService.HEADER_HSTS,
|
||||
Ci.nsISiteSecurityService.HEADER_HPKP,
|
||||
]) {
|
||||
// Also remove HSTS/HPKP/OMS information for subdomains by enumerating
|
||||
// Also remove HSTS/HPKP information for subdomains by enumerating
|
||||
// the information in the site security service.
|
||||
for (let entry of sss.enumerate(type)) {
|
||||
let hostname = entry.hostname;
|
||||
if (Services.eTLD.hasRootDomain(hostname, aHost)) {
|
||||
// This uri is used as a key to remove the state.
|
||||
// This uri is used as a key to reset the state.
|
||||
let uri = Services.io.newURI("https://" + hostname);
|
||||
sss.removeState(type, uri, 0, entry.originAttributes);
|
||||
sss.resetState(type, uri, 0, entry.originAttributes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче