From bb8e6be8a4e0f6282d8bfc3ebfe9ed9f3b70ac6d Mon Sep 17 00:00:00 2001 From: Drew Willcoxon Date: Sat, 24 Aug 2013 01:10:50 -0700 Subject: [PATCH] Bug 906276 - Add attribute to nsIDocShell to disable content retargeting. r=jlebar, sr=biesinger --- docshell/base/nsDocShell.cpp | 31 +++++- docshell/base/nsDocShell.h | 1 + docshell/base/nsIDocShell.idl | 9 +- docshell/test/chrome/Makefile.in | 2 + .../test/chrome/allowContentRetargeting.sjs | 7 ++ .../chrome/test_allowContentRetargeting.html | 94 +++++++++++++++++++ .../test_cancel_download_files_removed.js | 3 +- .../test/unit/test_download_samename.js | 3 +- toolkit/content/contentAreaUtils.js | 4 +- uriloader/base/nsIURILoader.idl | 10 +- uriloader/base/nsURILoader.cpp | 4 +- uriloader/exthandler/nsWebHandlerApp.js | 7 +- .../tests/unit_ipc/test_encoding.js | 2 +- 13 files changed, 159 insertions(+), 18 deletions(-) create mode 100644 docshell/test/chrome/allowContentRetargeting.sjs create mode 100644 docshell/test/chrome/test_allowContentRetargeting.html diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index bb2a03a0fc2d..74546019f8e6 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -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; diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h index 8ebe45fbfcd6..6eb537620c8e 100644 --- a/docshell/base/nsDocShell.h +++ b/docshell/base/nsDocShell.h @@ -812,6 +812,7 @@ protected: bool mAllowMedia; bool mAllowDNSPrefetch; bool mAllowWindowControl; + bool mAllowContentRetargeting; bool mCreatingDocument; // (should be) debugging only bool mUseErrorPages; bool mObserveErrorPages; diff --git a/docshell/base/nsIDocShell.idl b/docshell/base/nsIDocShell.idl index 63d5f2d4180f..61829c5aaad2 100644 --- a/docshell/base/nsIDocShell.idl +++ b/docshell/base/nsIDocShell.idl @@ -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. * diff --git a/docshell/test/chrome/Makefile.in b/docshell/test/chrome/Makefile.in index 2430e7173457..d70590afc4bc 100644 --- a/docshell/test/chrome/Makefile.in +++ b/docshell/test/chrome/Makefile.in @@ -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) diff --git a/docshell/test/chrome/allowContentRetargeting.sjs b/docshell/test/chrome/allowContentRetargeting.sjs new file mode 100644 index 000000000000..96e467ef68ff --- /dev/null +++ b/docshell/test/chrome/allowContentRetargeting.sjs @@ -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"); +} diff --git a/docshell/test/chrome/test_allowContentRetargeting.html b/docshell/test/chrome/test_allowContentRetargeting.html new file mode 100644 index 000000000000..58e838ca0114 --- /dev/null +++ b/docshell/test/chrome/test_allowContentRetargeting.html @@ -0,0 +1,94 @@ + + + + + + + + + +

+

+ + diff --git a/toolkit/components/downloads/test/unit/test_cancel_download_files_removed.js b/toolkit/components/downloads/test/unit/test_cancel_download_files_removed.js index 0fd04a93034d..8a8c7e8a1872 100644 --- a/toolkit/components/downloads/test/unit/test_cancel_download_files_removed.js +++ b/toolkit/components/downloads/test/unit/test_cancel_download_files_removed.js @@ -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 diff --git a/toolkit/components/downloads/test/unit/test_download_samename.js b/toolkit/components/downloads/test/unit/test_download_samename.js index eaf855bb7514..38c847f260d6 100644 --- a/toolkit/components/downloads/test/unit/test_download_samename.js +++ b/toolkit/components/downloads/test/unit/test_download_samename.js @@ -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 diff --git a/toolkit/content/contentAreaUtils.js b/toolkit/content/contentAreaUtils.js index 967e23c822d1..3de447e75760 100644 --- a/toolkit/content/contentAreaUtils.js +++ b/toolkit/content/contentAreaUtils.js @@ -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); } } diff --git a/uriloader/base/nsIURILoader.idl b/uriloader/base/nsIURILoader.idl index bfc60765342f..74f21e363951 100644 --- a/uriloader/base/nsIURILoader.idl +++ b/uriloader/base/nsIURILoader.idl @@ -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 * Must not be null! */ void openURI(in nsIChannel aChannel, - in boolean aIsContentPreferred, + in unsigned long aFlags, in nsIInterfaceRequestor aWindowContext); /** diff --git a/uriloader/base/nsURILoader.cpp b/uriloader/base/nsURILoader.cpp index db211c02cea7..ece2607e5c93 100644 --- a/uriloader/base/nsURILoader.cpp +++ b/uriloader/base/nsURILoader.cpp @@ -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 loader; nsresult rv = OpenChannel(channel, - aIsContentPreferred ? IS_CONTENT_PREFERRED : 0, + aFlags, aWindowContext, false, getter_AddRefs(loader)); diff --git a/uriloader/exthandler/nsWebHandlerApp.js b/uriloader/exthandler/nsWebHandlerApp.js index 54f8a95e313d..2c6cb760008a 100644 --- a/uriloader/exthandler/nsWebHandlerApp.js +++ b/uriloader/exthandler/nsWebHandlerApp.js @@ -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 // for details. - uriLoader.openURI(channel, true, aWindowContext); + uriLoader.openURI(channel, Ci.nsIURILoader.IS_CONTENT_PREFERRED, + aWindowContext); return; } diff --git a/uriloader/exthandler/tests/unit_ipc/test_encoding.js b/uriloader/exthandler/tests/unit_ipc/test_encoding.js index 10a8f1cab10a..28929ad3d78c 100644 --- a/uriloader/exthandler/tests/unit_ipc/test_encoding.js +++ b/uriloader/exthandler/tests/unit_ipc/test_encoding.js @@ -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()); \ '); }