Bug 906276 - Add attribute to nsIDocShell to disable content retargeting. r=jlebar, sr=biesinger

This commit is contained in:
Drew Willcoxon 2013-08-24 01:10:50 -07:00
parent 8d777e079c
commit b7e11dbae6
13 changed files with 159 additions and 18 deletions

View File

@ -761,6 +761,7 @@ nsDocShell::nsDocShell():
mAllowMedia(true),
mAllowDNSPrefetch(true),
mAllowWindowControl(true),
mAllowContentRetargeting(true),
mCreatingDocument(false),
mUseErrorPages(false),
mObserveErrorPages(true),
@ -2346,6 +2347,20 @@ NS_IMETHODIMP nsDocShell::SetAllowWindowControl(bool aAllowWindowControl)
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetAllowContentRetargeting(bool* aAllowContentRetargeting)
{
*aAllowContentRetargeting = mAllowContentRetargeting;
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::SetAllowContentRetargeting(bool aAllowContentRetargeting)
{
mAllowContentRetargeting = aAllowContentRetargeting;
return NS_OK;
}
NS_IMETHODIMP
nsDocShell::GetFullscreenAllowed(bool* aFullscreenAllowed)
{
@ -2869,6 +2884,8 @@ nsDocShell::SetDocLoaderParent(nsDocLoader * aParent)
{
SetAllowWindowControl(value);
}
SetAllowContentRetargeting(
parentAsDocShell->GetAllowContentRetargeting());
if (NS_SUCCEEDED(parentAsDocShell->GetIsActive(&value)))
{
SetIsActive(value);
@ -7783,6 +7800,8 @@ nsDocShell::RestoreFromHistory()
bool allowDNSPrefetch;
childShell->GetAllowDNSPrefetch(&allowDNSPrefetch);
bool allowContentRetargeting = childShell->GetAllowContentRetargeting();
// this.AddChild(child) calls child.SetDocLoaderParent(this), meaning
// that the child inherits our state. Among other things, this means
// that the child inherits our mIsActive and mInPrivateBrowsing, which
@ -7796,6 +7815,7 @@ nsDocShell::RestoreFromHistory()
childShell->SetAllowImages(allowImages);
childShell->SetAllowMedia(allowMedia);
childShell->SetAllowDNSPrefetch(allowDNSPrefetch);
childShell->SetAllowContentRetargeting(allowContentRetargeting);
rv = childShell->BeginRestore(nullptr, false);
NS_ENSURE_SUCCESS(rv, rv);
@ -9863,9 +9883,14 @@ nsresult nsDocShell::DoChannelLoad(nsIChannel * aChannel,
(void) aChannel->SetLoadFlags(loadFlags);
rv = aURILoader->OpenURI(aChannel,
(mLoadType == LOAD_LINK),
this);
uint32_t openFlags = 0;
if (mLoadType == LOAD_LINK) {
openFlags |= nsIURILoader::IS_CONTENT_PREFERRED;
}
if (!mAllowContentRetargeting) {
openFlags |= nsIURILoader::DONT_RETARGET;
}
rv = aURILoader->OpenURI(aChannel, openFlags, this);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;

View File

@ -812,6 +812,7 @@ protected:
bool mAllowMedia;
bool mAllowDNSPrefetch;
bool mAllowWindowControl;
bool mAllowContentRetargeting;
bool mCreatingDocument; // (should be) debugging only
bool mUseErrorPages;
bool mObserveErrorPages;

View File

@ -42,7 +42,7 @@ interface nsIVariant;
interface nsIPrivacyTransitionObserver;
interface nsIReflowObserver;
[scriptable, builtinclass, uuid(365e7446-6c4b-45ae-ae08-b7b401900093)]
[scriptable, builtinclass, uuid(4bb2261b-4c13-44a4-ace3-fc2eec17cc34)]
interface nsIDocShell : nsIDocShellTreeItem
{
/**
@ -258,6 +258,13 @@ interface nsIDocShell : nsIDocShellTreeItem
*/
attribute boolean allowWindowControl;
/**
* True if the docshell allows its content to be handled by a content listener
* other than the docshell itself, including the external helper app service,
* and false otherwise. Defaults to true.
*/
[infallible] attribute boolean allowContentRetargeting;
/**
* Get an enumerator over this docShell and its children.
*

View File

@ -25,6 +25,7 @@ MOCHITEST_FILES = \
582176_dummy.html \
582176_xml.xml \
582176_xslt.xsl \
allowContentRetargeting.sjs \
$(NULL)
MOCHITEST_CHROME_FILES = \
@ -100,6 +101,7 @@ MOCHITEST_CHROME_FILES = \
generic.html \
test_bug846906.xul \
bug846906.html \
test_allowContentRetargeting.html \
$(NULL)
ifneq ($(MOZ_WIDGET_TOOLKIT),gtk2)

View File

@ -0,0 +1,7 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
function handleRequest(req, resp) {
resp.setHeader("Content-Type", "application/octet-stream", false);
resp.write("hi");
}

View File

@ -0,0 +1,94 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
<script type="application/javascript">
SimpleTest.waitForExplicitFinish();
addLoadEvent(runNextTest);
var TEST_URL = "http://mochi.test:8888/tests/docshell/test/chrome/allowContentRetargeting.sjs";
var Ci = Components.interfaces;
function runNextTest() {
var test = tests.shift();
if (!test) {
SimpleTest.finish();
return;
}
test();
}
var tests = [
// Set allowContentRetargeting = false, load a downloadable URL, verify the
// downloadable stops loading.
function basic() {
var iframe = insertIframe();
docshellForWindow(iframe.contentWindow).allowContentRetargeting = false;
loadIframe(iframe);
},
// Set allowContentRetargeting = false on parent docshell, load a downloadable
// URL, verify the downloadable stops loading.
function inherit() {
var docshell = docshellForWindow(window);
docshell.allowContentRetargeting = false;
loadIframe(insertIframe());
},
];
function docshellForWindow(win) {
return win.
QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIWebNavigation).
QueryInterface(Ci.nsIDocShell);
}
function insertIframe() {
var iframe = document.createElement("iframe");
document.body.appendChild(iframe);
return iframe;
}
function loadIframe(iframe) {
iframe.setAttribute("src", TEST_URL);
docshellForWindow(iframe.contentWindow).
QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIWebProgress).
addProgressListener(progressListener,
Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
}
var progressListener = {
onStateChange: function (webProgress, req, flags, status) {
if (!(flags & Ci.nsIWebProgressListener.STATE_STOP))
return;
is(Components.isSuccessCode(status), false,
"Downloadable should have failed to load");
document.querySelector("iframe").remove();
runNextTest();
},
QueryInterface: function (iid) {
var iids = [
Ci.nsIWebProgressListener,
Ci.nsISupportsWeakReference,
Ci.nsISupports,
];
if (iids.some(function (i) { return iid.equals(i); }))
return this;
throw Components.results.NS_ERROR_NO_INTERFACE;
},
};
</script>
</head>
<body>
<p id="display">
</p>
</body>
</html>

View File

@ -92,7 +92,8 @@ function runNextTest()
httpserver.identity.primaryPort +
set.serverPath);
let uriloader = Cc["@mozilla.org/uriloader;1"].getService(Ci.nsIURILoader);
uriloader.openURI(channel, true, new WindowContext());
uriloader.openURI(channel, Ci.nsIURILoader.IS_CONTENT_PREFERRED,
new WindowContext());
}
// sends the responses for the files. sends the same content twice if we resume

View File

@ -115,7 +115,8 @@ function runNextTest()
httpserver.identity.primaryPort +
set.serverURL);
let uriloader = Cc["@mozilla.org/uriloader;1"].getService(Ci.nsIURILoader);
uriloader.openURI(channel, true, new WindowContext());
uriloader.openURI(channel, Ci.nsIURILoader.IS_CONTENT_PREFERRED,
new WindowContext());
}
// sends the responses for the files. sends the same content twice if we resume

View File

@ -1137,6 +1137,8 @@ function openURL(aURL)
var channel = Services.io.newChannelFromURI(uri);
var uriLoader = Components.classes["@mozilla.org/uriloader;1"]
.getService(Components.interfaces.nsIURILoader);
uriLoader.openURI(channel, true, uriListener);
uriLoader.openURI(channel,
Components.interfaces.nsIURILoader.IS_CONTENT_PREFERRED,
uriListener);
}
}

View File

@ -35,7 +35,7 @@ interface nsIInterfaceRequestor;
* or helper app. Or it may hand the url off to an OS registered
* application.
*/
[scriptable, uuid(2f7e8051-f1c9-4bcc-8584-9cfd5849e343)]
[scriptable, uuid(8762c4e7-be35-4958-9b81-a05685bb516d)]
interface nsIURILoader : nsISupports
{
/**
@ -78,9 +78,9 @@ interface nsIURILoader : nsISupports
* The channel that should be opened. This must not be asyncOpen'd yet!
* If a loadgroup is set on the channel, it will get replaced with a
* different one.
* @param aIsContentPreferred
* Should the content be displayed in a container that prefers the
* content-type, or will any container do.
* @param aFlags
* Combination (bitwise OR) of the flags specified above. 0 indicates
* default handling.
* @param aWindowContext
* If you are running the url from a doc shell or a web shell, this is
* your window context. If you have a content listener you want to
@ -90,7 +90,7 @@ interface nsIURILoader : nsISupports
* <b>Must not be null!</b>
*/
void openURI(in nsIChannel aChannel,
in boolean aIsContentPreferred,
in unsigned long aFlags,
in nsIInterfaceRequestor aWindowContext);
/**

View File

@ -753,7 +753,7 @@ NS_IMETHODIMP nsURILoader::UnRegisterContentListener(nsIURIContentListener * aCo
}
NS_IMETHODIMP nsURILoader::OpenURI(nsIChannel *channel,
bool aIsContentPreferred,
uint32_t aFlags,
nsIInterfaceRequestor *aWindowContext)
{
NS_ENSURE_ARG_POINTER(channel);
@ -770,7 +770,7 @@ NS_IMETHODIMP nsURILoader::OpenURI(nsIChannel *channel,
nsCOMPtr<nsIStreamListener> loader;
nsresult rv = OpenChannel(channel,
aIsContentPreferred ? IS_CONTENT_PREFERRED : 0,
aFlags,
aWindowContext,
false,
getter_AddRefs(loader));

View File

@ -86,12 +86,13 @@ nsWebHandlerApp.prototype = {
// load the channel
var uriLoader = Cc["@mozilla.org/uriloader;1"].
getService(Ci.nsIURILoader);
// XXX ideally, aIsContentPreferred (the second param) should really be
// passed in from above. Practically, true is probably a reasonable
// XXX ideally, whether to pass the IS_CONTENT_PREFERRED flag should be
// passed in from above. Practically, the flag is probably a reasonable
// default since browsers don't care much, and link click is likely to be
// the more interesting case for non-browser apps. See
// <https://bugzilla.mozilla.org/show_bug.cgi?id=392957#c9> for details.
uriLoader.openURI(channel, true, aWindowContext);
uriLoader.openURI(channel, Ci.nsIURILoader.IS_CONTENT_PREFERRED,
aWindowContext);
return;
}

View File

@ -150,7 +150,7 @@ function runChildTestSet(set)
sendCommand('\
let uri = ioservice.newURI("http://localhost:4444' + set[0] + '", null, null);\
let channel = ioservice.newChannelFromURI(uri); \
uriloader.openURI(channel, true, new WindowContext()); \
uriloader.openURI(channel, Ci.nsIURILoader.IS_CONTENT_PREFERRED, new WindowContext()); \
');
}