Bug 1345611 - Change behavior of subdocument Flash blocking to be Third-Party Flash blocking r=bsmedberg,qdot

The previous implementation regarding to the Flash Blocking Subdocument list blocked all subdocuments that matched the list. This patch changes that so that subdocuments are only blocked if they are on the Subdocument Block List and also are loaded in a Third-Party context.

The changes to cert8.db and key3.db add the https certificate for subdocument.example.com so that testing can verify that a scheme mismatch between the document and its parent results in a third-party classification.

MozReview-Commit-ID: IXnA4iPzB4y

--HG--
extra : rebase_source : 103c1e184d4219e6db9d00da1ea54674a0e216dd
This commit is contained in:
Kirk Steuber 2017-03-10 10:50:21 -08:00
parent 3a09e7487d
commit bae89898aa
8 changed files with 114 additions and 7 deletions

Binary file not shown.

Binary file not shown.

View file

@ -190,6 +190,7 @@ http://exception.flashallow.example.com:80
http://flashblock.example.com:80
http://exception.flashblock.example.com:80
http://subdocument.example.com:80
https://subdocument.example.com:443
http://exception.subdocument.example.com:80
#

View file

@ -13075,9 +13075,10 @@ ArrayContainsTable(const nsTArray<nsCString>& aTableArray,
* toolkit/components/url-classifier/flash-block-lists.rst
*/
FlashClassification
nsDocument::PrincipalFlashClassification(bool aIsTopLevel)
nsDocument::PrincipalFlashClassification()
{
nsresult rv;
bool isThirdPartyDoc = IsThirdParty();
// If flash blocking is disabled, it is equivalent to all sites being
// whitelisted.
@ -13110,7 +13111,7 @@ nsDocument::PrincipalFlashClassification(bool aIsTopLevel)
Preferences::GetCString("urlclassifier.flashExceptTable",
&denyExceptionsTables);
MaybeAddTableToTableList(denyExceptionsTables, tables);
if (!aIsTopLevel) {
if (isThirdPartyDoc) {
Preferences::GetCString("urlclassifier.flashSubDocTable",
&subDocDenyTables);
MaybeAddTableToTableList(subDocDenyTables, tables);
@ -13155,7 +13156,7 @@ nsDocument::PrincipalFlashClassification(bool aIsTopLevel)
return FlashClassification::Allowed;
}
if (!aIsTopLevel && ArrayContainsTable(results, subDocDenyTables) &&
if (isThirdPartyDoc && ArrayContainsTable(results, subDocDenyTables) &&
!ArrayContainsTable(results, subDocDenyExceptionsTables)) {
return FlashClassification::Denied;
}
@ -13178,7 +13179,7 @@ nsDocument::ComputeFlashClassification()
bool isTopLevel = !parent;
FlashClassification classification;
if (isTopLevel) {
classification = PrincipalFlashClassification(isTopLevel);
classification = PrincipalFlashClassification();
} else {
nsCOMPtr<nsIDocument> parentDocument = GetParentDocument();
if (!parentDocument) {
@ -13190,7 +13191,7 @@ nsDocument::ComputeFlashClassification()
if (parentClassification == FlashClassification::Denied) {
classification = FlashClassification::Denied;
} else {
classification = PrincipalFlashClassification(isTopLevel);
classification = PrincipalFlashClassification();
// Allow unknown children to inherit allowed status from parent, but
// do not allow denied children to do so.
@ -13224,3 +13225,83 @@ nsDocument::DocumentFlashClassification()
return mFlashClassification;
}
/**
* Initializes |mIsThirdParty| if necessary and returns its value. The value
* returned represents whether this document should be considered Third-Party.
*
* A top-level document cannot be a considered Third-Party; only subdocuments
* may. For a subdocument to be considered Third-Party, it must meet ANY ONE
* of the following requirements:
* - The document's parent is Third-Party
* - The document has a different scheme (http/https) than its parent document
* - The document's domain and subdomain do not match those of its parent
* document.
*
* If there is an error in determining whether the document is Third-Party,
* it will be assumed to be Third-Party for security reasons.
*/
bool
nsDocument::IsThirdParty()
{
if (mIsThirdParty.isSome()) {
return mIsThirdParty.value();
}
nsCOMPtr<nsIDocShellTreeItem> docshell = this->GetDocShell();
if (!docshell) {
mIsThirdParty.emplace(true);
return mIsThirdParty.value();
}
nsCOMPtr<nsIDocShellTreeItem> parent;
nsresult rv = docshell->GetSameTypeParent(getter_AddRefs(parent));
MOZ_ASSERT(NS_SUCCEEDED(rv),
"nsIDocShellTreeItem::GetSameTypeParent should never fail");
bool isTopLevel = !parent;
if (isTopLevel) {
mIsThirdParty.emplace(false);
return mIsThirdParty.value();
}
nsCOMPtr<nsIDocument> parentDocument = GetParentDocument();
if (!parentDocument) {
// Failure
mIsThirdParty.emplace(true);
return mIsThirdParty.value();
}
if (parentDocument->IsThirdParty()) {
mIsThirdParty.emplace(true);
return mIsThirdParty.value();
}
nsCOMPtr<nsIPrincipal> principal = GetPrincipal();
nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(parentDocument,
&rv);
if (NS_WARN_IF(NS_FAILED(rv) || !sop)) {
// Failure
mIsThirdParty.emplace(true);
return mIsThirdParty.value();
}
nsCOMPtr<nsIPrincipal> parentPrincipal = sop->GetPrincipal();
bool principalsMatch = false;
rv = principal->Equals(parentPrincipal, &principalsMatch);
if (NS_WARN_IF(NS_FAILED(rv))) {
// Failure
mIsThirdParty.emplace(true);
return mIsThirdParty.value();
}
if (!principalsMatch) {
mIsThirdParty.emplace(true);
return mIsThirdParty.value();
}
// Fall-through. Document is not a Third-Party Document.
mIsThirdParty.emplace(false);
return mIsThirdParty.value();
}

View file

@ -70,6 +70,7 @@
#include "mozilla/LinkedList.h"
#include "CustomElementRegistry.h"
#include "mozilla/dom/Performance.h"
#include "mozilla/Maybe.h"
#define XML_DECLARATION_BITS_DECLARATION_EXISTS (1 << 0)
#define XML_DECLARATION_BITS_ENCODING_EXISTS (1 << 1)
@ -1308,6 +1309,7 @@ protected:
void UpdateScreenOrientation();
virtual mozilla::dom::FlashClassification DocumentFlashClassification() override;
virtual bool IsThirdParty() override;
#define NS_DOCUMENT_NOTIFY_OBSERVERS(func_, params_) \
NS_OBSERVER_ARRAY_NOTIFY_XPCOM_OBSERVERS(mObservers, nsIDocumentObserver, \
@ -1331,7 +1333,7 @@ protected:
// Retrieves the classification of the Flash plugins in the document based on
// the classification lists.
mozilla::dom::FlashClassification PrincipalFlashClassification(bool aIsTopLevel);
mozilla::dom::FlashClassification PrincipalFlashClassification();
// Attempts to determine the Flash classification of this page based on the
// the classification lists and the classification of parent documents.
@ -1383,6 +1385,9 @@ protected:
nsWeakPtr mFullscreenRoot;
mozilla::dom::FlashClassification mFlashClassification;
// Do not use this value directly. Call the |IsThirdParty()| method, which
// caches its result here.
mozilla::Maybe<bool> mIsThirdParty;
private:
static bool CustomElementConstructor(JSContext* aCx, unsigned aArgc, JS::Value* aVp);

View file

@ -2903,6 +2903,7 @@ public:
// For more information on Flash classification, see
// toolkit/components/url-classifier/flash-block-lists.rst
virtual mozilla::dom::FlashClassification DocumentFlashClassification() = 0;
virtual bool IsThirdParty() = 0;
protected:
bool GetUseCounter(mozilla::UseCounter aUseCounter)

View file

@ -27,7 +27,8 @@ Documents with an Unknown classification will have Flash set to Click To Activat
If the document is at the top level (its address is in the URL bar), then the Deny List is checked first followed by the Allow List to determine its classification.
If the document is not at the top level, it will receive a Deny classification if the classification of the parent document is Deny or if the document is on the Deny List or the Sub-Document Deny List.
If the document is not at the top level, it will receive a Deny classification if the classification of the parent document is Deny or if the document is on the Deny List.
It will also receive a Deny classification if the sub-document is not same-origin and the document is on the Sub-Document Deny List.
If the document did not receive a Deny classification, it can receive an Allow classification if it is on the Allow List or if the parent document received an Allow classification.
If for any reason, the document has a null principal, it will receive a Deny classification.

View file

@ -184,6 +184,24 @@ var testCases = [
pluginListed: false,
expectedFlashClassification: "denied"
},
{
name: "Sub-document blocked domain in non-Third-Party context",
domains: ["http://subdocument.example.com", "http://subdocument.example.com"],
expectedPluginFallbackType: Ci.nsIObjectLoadingContent.PLUGIN_CLICK_TO_PLAY,
expectedActivated: false,
expectedHasRunningPlugin: false,
pluginListed: true,
expectedFlashClassification: "unknown"
},
{
name: "Sub-document blocked domain differing only by scheme",
domains: ["http://subdocument.example.com", "https://subdocument.example.com"],
expectedPluginFallbackType: Ci.nsIObjectLoadingContent.PLUGIN_USER_DISABLED,
expectedActivated: false,
expectedHasRunningPlugin: false,
pluginListed: false,
expectedFlashClassification: "denied"
},
{
name: "Sub-document blocked subdocument of an allowed domain",
domains: ["http://flashallow.example.com", "http://subdocument.example.com"],