Bug 802895 - Docshell related changes for srcdoc iframe r=bz

This commit is contained in:
James Kitchener
2013-06-28 23:13:22 -04:00
parent c433085d39
commit 0a66efde86
11 changed files with 216 additions and 39 deletions

View File

@@ -6100,11 +6100,17 @@ nsContentUtils::SetUpChannelOwner(nsIPrincipal* aLoadingPrincipal,
if (aForceOwner || ((NS_SUCCEEDED(URIInheritsSecurityContext(aURI, &inherit)) &&
(inherit || (aSetUpForAboutBlank && NS_IsAboutBlank(aURI)))))) {
#ifdef DEBUG
// Assert that aForceOwner is only set for null principals
// Assert that aForceOwner is only set for null principals for non-srcdoc
// loads. (Strictly speaking not all uses of about:srcdoc would be
// srcdoc loads, but the URI is non-resolvable in cases where it is not).
if (aForceOwner) {
nsCOMPtr<nsIURI> ownerURI;
nsresult rv = aLoadingPrincipal->GetURI(getter_AddRefs(ownerURI));
MOZ_ASSERT(NS_SUCCEEDED(rv) && SchemeIs(ownerURI, NS_NULLPRINCIPAL_SCHEME));
nsAutoCString uriStr;
aURI->GetSpec(uriStr);
if(!uriStr.EqualsLiteral("about:srcdoc")) {
nsCOMPtr<nsIURI> ownerURI;
nsresult rv = aLoadingPrincipal->GetURI(getter_AddRefs(ownerURI));
MOZ_ASSERT(NS_SUCCEEDED(rv) && SchemeIs(ownerURI, NS_NULLPRINCIPAL_SCHEME));
}
}
#endif
aChannel->SetOwner(aLoadingPrincipal);

View File

@@ -35,4 +35,5 @@ LOCAL_INCLUDES += \
-I$(topsrcdir)/layout/generic \
-I$(topsrcdir)/layout/xul/base/src \
-I$(topsrcdir)/content/base/src \
-I$(topsrcdir)/netwerk/protocol/viewsource \
$(NULL)

View File

@@ -89,6 +89,7 @@
#include "nsIDocShellTreeItem.h"
#include "nsIChannel.h"
#include "IHistory.h"
#include "nsViewSourceHandler.h"
// we want to explore making the document own the load group
// so we can associate the document URI with the load group.
@@ -1260,8 +1261,11 @@ nsDocShell::LoadURI(nsIURI * aURI,
bool inheritOwner = false;
bool ownerIsExplicit = false;
bool sendReferrer = true;
bool isSrcdoc = false;
nsCOMPtr<nsISHEntry> shEntry;
nsXPIDLString target;
nsAutoString srcdoc;
uint32_t loadType = MAKE_LOAD_TYPE(LOAD_NORMAL, aLoadFlags);
NS_ENSURE_ARG(aURI);
@@ -1288,6 +1292,8 @@ nsDocShell::LoadURI(nsIURI * aURI,
aLoadInfo->GetPostDataStream(getter_AddRefs(postStream));
aLoadInfo->GetHeadersStream(getter_AddRefs(headersStream));
aLoadInfo->GetSendReferrer(&sendReferrer);
aLoadInfo->GetIsSrcdocLoad(&isSrcdoc);
aLoadInfo->GetSrcdocData(srcdoc);
}
#if defined(PR_LOGGING) && defined(DEBUG)
@@ -1508,6 +1514,9 @@ nsDocShell::LoadURI(nsIURI * aURI,
if (aLoadFlags & LOAD_FLAGS_FORCE_ALLOW_COOKIES)
flags |= INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES;
if (isSrcdoc)
flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC;
return InternalLoad(aURI,
referrer,
owner,
@@ -1520,6 +1529,7 @@ nsDocShell::LoadURI(nsIURI * aURI,
loadType,
nullptr, // No SHEntry
aFirstParty,
srcdoc,
nullptr, // No nsIDocShell
nullptr); // No nsIRequest
}
@@ -4567,7 +4577,7 @@ nsDocShell::LoadErrorPage(nsIURI *aURI, const PRUnichar *aURL,
return InternalLoad(errorPageURI, nullptr, nullptr,
INTERNAL_LOAD_FLAGS_INHERIT_OWNER, nullptr, nullptr,
NullString(), nullptr, nullptr, LOAD_ERROR_PAGE,
nullptr, true, nullptr, nullptr);
nullptr, true, NullString(), nullptr,nullptr);
}
@@ -4608,17 +4618,24 @@ nsDocShell::Reload(uint32_t aReloadFlags)
else {
nsCOMPtr<nsIDocument> doc(do_GetInterface(GetAsSupports(this)));
// Do not inherit owner from document
uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
nsAutoString srcdoc;
nsIPrincipal* principal = nullptr;
nsAutoString contentTypeHint;
if (doc) {
principal = doc->NodePrincipal();
doc->GetContentType(contentTypeHint);
}
if (doc->IsSrcdocDocument()) {
doc->GetSrcdocData(srcdoc);
flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC;
}
}
rv = InternalLoad(mCurrentURI,
mReferrerURI,
principal,
INTERNAL_LOAD_FLAGS_NONE, // Do not inherit owner from document
flags,
nullptr, // No window target
NS_LossyConvertUTF16toASCII(contentTypeHint).get(),
NullString(), // No forced download
@@ -4627,6 +4644,7 @@ nsDocShell::Reload(uint32_t aReloadFlags)
loadType, // Load type
nullptr, // No SHEntry
true,
srcdoc, // srcdoc argument for iframe
nullptr, // No nsIDocShell
nullptr); // No nsIRequest
}
@@ -8467,7 +8485,9 @@ public:
nsISupports * aOwner, uint32_t aFlags,
const char* aTypeHint, nsIInputStream * aPostData,
nsIInputStream * aHeadersData, uint32_t aLoadType,
nsISHEntry * aSHEntry, bool aFirstParty) :
nsISHEntry * aSHEntry, bool aFirstParty,
const nsAString &aSrcdoc) :
mSrcdoc(aSrcdoc),
mDocShell(aDocShell),
mURI(aURI),
mReferrer(aReferrer),
@@ -8490,7 +8510,7 @@ public:
nullptr, mTypeHint.get(),
NullString(), mPostData, mHeadersData,
mLoadType, mSHEntry, mFirstParty,
nullptr, nullptr);
mSrcdoc, nullptr, nullptr);
}
private:
@@ -8498,6 +8518,7 @@ private:
// Use IDL strings so .get() returns null by default
nsXPIDLString mWindowTarget;
nsXPIDLCString mTypeHint;
nsString mSrcdoc;
nsRefPtr<nsDocShell> mDocShell;
nsCOMPtr<nsIURI> mURI;
@@ -8541,6 +8562,7 @@ nsDocShell::InternalLoad(nsIURI * aURI,
uint32_t aLoadType,
nsISHEntry * aSHEntry,
bool aFirstParty,
const nsAString &aSrcdoc,
nsIDocShell** aDocShell,
nsIRequest** aRequest)
{
@@ -8779,6 +8801,7 @@ nsDocShell::InternalLoad(nsIURI * aURI,
aLoadType,
aSHEntry,
aFirstParty,
aSrcdoc,
aDocShell,
aRequest);
if (rv == NS_ERROR_NO_CONTENT) {
@@ -8860,7 +8883,7 @@ nsDocShell::InternalLoad(nsIURI * aURI,
nsCOMPtr<nsIRunnable> ev =
new InternalLoadEvent(this, aURI, aReferrer, aOwner, aFlags,
aTypeHint, aPostData, aHeadersData,
aLoadType, aSHEntry, aFirstParty);
aLoadType, aSHEntry, aFirstParty, aSrcdoc);
return NS_DispatchToCurrentThread(ev);
}
@@ -9267,6 +9290,12 @@ nsDocShell::InternalLoad(nsIURI * aURI,
}
}
nsAutoString srcdoc;
if (aFlags & INTERNAL_LOAD_FLAGS_IS_SRCDOC)
srcdoc = aSrcdoc;
else
srcdoc = NullString();
nsCOMPtr<nsIRequest> req;
rv = DoURILoad(aURI, aReferrer,
!(aFlags & INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER),
@@ -9274,7 +9303,8 @@ nsDocShell::InternalLoad(nsIURI * aURI,
aFirstParty, aDocShell, getter_AddRefs(req),
(aFlags & INTERNAL_LOAD_FLAGS_FIRST_LOAD) != 0,
(aFlags & INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER) != 0,
(aFlags & INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES) != 0);
(aFlags & INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES) != 0,
srcdoc);
if (req && aRequest)
NS_ADDREF(*aRequest = req);
@@ -9352,7 +9382,8 @@ nsDocShell::DoURILoad(nsIURI * aURI,
nsIRequest ** aRequest,
bool aIsNewWindowTarget,
bool aBypassClassifier,
bool aForceAllowCookies)
bool aForceAllowCookies,
const nsAString &aSrcdoc)
{
#ifdef MOZ_VISUAL_EVENT_TRACER
nsAutoCString urlSpec;
@@ -9401,28 +9432,52 @@ nsDocShell::DoURILoad(nsIURI * aURI,
// open a channel for the url
nsCOMPtr<nsIChannel> channel;
rv = NS_NewChannel(getter_AddRefs(channel),
aURI,
nullptr,
nullptr,
static_cast<nsIInterfaceRequestor *>(this),
loadFlags,
channelPolicy);
if (NS_FAILED(rv)) {
if (rv == NS_ERROR_UNKNOWN_PROTOCOL) {
// This is a uri with a protocol scheme we don't know how
// to handle. Embedders might still be interested in
// handling the load, though, so we fire a notification
// before throwing the load away.
bool abort = false;
nsresult rv2 = mContentListener->OnStartURIOpen(aURI, &abort);
if (NS_SUCCEEDED(rv2) && abort) {
// Hey, they're handling the load for us! How convenient!
return NS_OK;
bool isSrcdoc = !aSrcdoc.IsVoid();
if (!isSrcdoc) {
rv = NS_NewChannel(getter_AddRefs(channel),
aURI,
nullptr,
nullptr,
static_cast<nsIInterfaceRequestor *>(this),
loadFlags,
channelPolicy);
if (NS_FAILED(rv)) {
if (rv == NS_ERROR_UNKNOWN_PROTOCOL) {
// This is a uri with a protocol scheme we don't know how
// to handle. Embedders might still be interested in
// handling the load, though, so we fire a notification
// before throwing the load away.
bool abort = false;
nsresult rv2 = mContentListener->OnStartURIOpen(aURI, &abort);
if (NS_SUCCEEDED(rv2) && abort) {
// Hey, they're handling the load for us! How convenient!
return NS_OK;
}
}
return rv;
}
}
else {
nsAutoCString scheme;
rv = aURI->GetScheme(scheme);
NS_ENSURE_SUCCESS(rv,rv);
bool isViewSource;
aURI->SchemeIs("view-source",&isViewSource);
if (isViewSource) {
nsViewSourceHandler *vsh = nsViewSourceHandler::GetInstance();
NS_ENSURE_TRUE(vsh,NS_ERROR_FAILURE);
rv = vsh->NewSrcdocChannel(aURI, aSrcdoc,getter_AddRefs(channel));
NS_ENSURE_SUCCESS(rv, rv);
}
else {
rv = NS_NewInputStreamChannel(getter_AddRefs(channel),aURI,
aSrcdoc,
NS_LITERAL_CSTRING("text/html"),
true);
NS_ENSURE_SUCCESS(rv, rv);
}
return rv;
}
nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
@@ -9580,7 +9635,8 @@ nsDocShell::DoURILoad(nsIURI * aURI,
}
nsContentUtils::SetUpChannelOwner(ownerPrincipal, channel, aURI, true,
(mSandboxFlags & SANDBOXED_ORIGIN));
(mSandboxFlags & SANDBOXED_ORIGIN) ||
isSrcdoc);
nsCOMPtr<nsIScriptChannel> scriptChannel = do_QueryInterface(channel);
if (scriptChannel) {
@@ -10638,6 +10694,16 @@ nsDocShell::AddToSessionHistory(nsIURI * aURI, nsIChannel * aChannel,
mHistoryID,
mDynamicallyCreated);
entry->SetReferrerURI(referrerURI);
nsCOMPtr<nsIInputStreamChannel> inStrmChan = do_QueryInterface(aChannel);
if (inStrmChan) {
bool isSrcdocChannel;
inStrmChan->GetIsSrcdocChannel(&isSrcdocChannel);
if (isSrcdocChannel) {
nsAutoString srcdoc;
inStrmChan->GetSrcdocData(srcdoc);
entry->SetSrcdocData(srcdoc);
}
}
/* If cache got a 'no-store', ask SH not to store
* HistoryLayoutState. By default, SH will set this
* flag to true and save HistoryLayoutState.
@@ -10784,10 +10850,24 @@ nsDocShell::LoadHistoryEntry(nsISHEntry * aEntry, uint32_t aLoadType)
return NS_BINDING_ABORTED;
}
// Do not inherit owner from document (security-critical!);
uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
nsAutoString srcdoc;
bool isSrcdoc;
aEntry->GetIsSrcdocEntry(&isSrcdoc);
if (isSrcdoc) {
aEntry->GetSrcdocData(srcdoc);
flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC;
}
else {
srcdoc = NullString();
}
rv = InternalLoad(uri,
referrerURI,
owner,
INTERNAL_LOAD_FLAGS_NONE, // Do not inherit owner from document (security-critical!)
flags,
nullptr, // No window target
contentType.get(), // Type hint
NullString(), // No forced file download
@@ -10796,6 +10876,7 @@ nsDocShell::LoadHistoryEntry(nsISHEntry * aEntry, uint32_t aLoadType)
aLoadType, // Load type
aEntry, // SHEntry
true,
srcdoc,
nullptr, // No nsIDocShell
nullptr); // No nsIRequest
return rv;
@@ -12235,6 +12316,7 @@ nsDocShell::OnLinkClickSync(nsIContent *aContent,
LOAD_LINK, // Load type
nullptr, // No SHEntry
true, // first party site
NullString(), // No srcdoc
aDocShell, // DocShell out-param
aRequest); // Request out-param
if (NS_SUCCEEDED(rv)) {

View File

@@ -289,6 +289,8 @@ protected:
// Actually open a channel and perform a URI load. Note: whatever owner is
// passed to this function will be set on the channel. Callers who wish to
// not have an owner on the channel should just pass null.
// If aSrcdoc is not void, the load will be considered as a srcdoc load,
// and the contents of aSrcdoc will be loaded instead of aURI.
virtual nsresult DoURILoad(nsIURI * aURI,
nsIURI * aReferrer,
bool aSendReferrer,
@@ -302,7 +304,8 @@ protected:
nsIRequest ** aRequest,
bool aIsNewWindowTarget,
bool aBypassClassifier,
bool aForceAllowCookies);
bool aForceAllowCookies,
const nsAString &aSrcdoc);
NS_IMETHOD AddHeadersToChannel(nsIInputStream * aHeadersData,
nsIChannel * aChannel);
virtual nsresult DoChannelLoad(nsIChannel * aChannel,

View File

@@ -16,7 +16,8 @@ nsDocShellLoadInfo::nsDocShellLoadInfo()
: mInheritOwner(false),
mOwnerIsExplicit(false),
mSendReferrer(true),
mLoadType(nsIDocShellLoadInfo::loadNormal)
mLoadType(nsIDocShellLoadInfo::loadNormal),
mIsSrcdocLoad(false)
{
}
@@ -188,6 +189,26 @@ NS_IMETHODIMP nsDocShellLoadInfo::SetSendReferrer(bool aSendReferrer)
return NS_OK;
}
NS_IMETHODIMP nsDocShellLoadInfo::GetIsSrcdocLoad(bool* aIsSrcdocLoad)
{
*aIsSrcdocLoad = mIsSrcdocLoad;
return NS_OK;
}
NS_IMETHODIMP nsDocShellLoadInfo::GetSrcdocData(nsAString &aSrcdocData)
{
aSrcdocData = mSrcdocData;
return NS_OK;
}
NS_IMETHODIMP nsDocShellLoadInfo::SetSrcdocData(const nsAString &aSrcdocData)
{
mSrcdocData = aSrcdocData;
mIsSrcdocLoad = true;
return NS_OK;
}
//*****************************************************************************
// nsDocShellLoadInfo: Helpers
//*****************************************************************************

View File

@@ -40,6 +40,8 @@ protected:
nsString mTarget;
nsCOMPtr<nsIInputStream> mPostDataStream;
nsCOMPtr<nsIInputStream> mHeadersStream;
bool mIsSrcdocLoad;
nsString mSrcdocData;
};
#endif /* nsDocShellLoadInfo_h__ */

View File

@@ -42,7 +42,7 @@ interface nsIVariant;
interface nsIPrivacyTransitionObserver;
interface nsIReflowObserver;
[scriptable, builtinclass, uuid(f453d2ee-bac7-46f9-a553-df918f0cc0d0)]
[scriptable, builtinclass, uuid(cdeb1ed0-7794-4e5f-964e-bb9d753d1686)]
interface nsIDocShell : nsIDocShellTreeItem
{
/**
@@ -106,6 +106,9 @@ interface nsIDocShell : nsIDocShellTreeItem
const long INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER = 0x10;
const long INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES = 0x20;
// Whether the load should be treated as srcdoc load, rather than a URI one.
const long INTERNAL_LOAD_FLAGS_IS_SRCDOC = 0x40;
/**
* Loads the given URI. This method is identical to loadURI(...) except
* that its parameter list is broken out instead of being packaged inside
@@ -128,6 +131,9 @@ interface nsIDocShell : nsIDocShellTreeItem
* @param aLoadFlags - Flags to modify load behaviour. Flags are defined
* in nsIWebNavigation.
* @param aSHEntry - Active Session History entry (if loading from SH)
* @param aSrcdoc When INTERNAL_LOAD_FLAGS_IS_SRCDOC is set, the
* contents of this parameter will be loaded instead
* of aURI.
*/
[noscript]void internalLoad(in nsIURI aURI,
in nsIURI aReferrer,
@@ -141,6 +147,7 @@ interface nsIDocShell : nsIDocShellTreeItem
in unsigned long aLoadFlags,
in nsISHEntry aSHEntry,
in boolean firstParty,
in AString aSrcdoc,
out nsIDocShell aDocShell,
out nsIRequest aRequest);

View File

@@ -17,7 +17,7 @@ interface nsISHEntry;
typedef long nsDocShellInfoLoadType;
[scriptable, uuid(5b041ea4-6655-434c-b3d3-cbbc9441f86a)]
[scriptable, uuid(5df91211-37db-47e9-8f83-2d5b0cb2eb9e)]
interface nsIDocShellLoadInfo : nsISupports
{
/** This is the referrer for the load. */
@@ -82,4 +82,16 @@ interface nsIDocShellLoadInfo : nsISupports
* sent, even if it's available. This attribute defaults to true.
*/
attribute boolean sendReferrer;
/** True if the docshell has been created to load an iframe where the
* srcdoc attribute has been set. Set when srcdocData is specified.
*/
readonly attribute boolean isSrcdocLoad;
/** When set, the load will be interpreted as a srcdoc load, where contents
* of this string will be loaded instead of the URI. Setting srcdocData
* sets isSrcdocLoad to true
*/
attribute AString srcdocData;
};

View File

@@ -29,7 +29,7 @@ class nsSHEntryShared;
[ptr] native nsDocShellEditorDataPtr(nsDocShellEditorData);
[ptr] native nsSHEntryShared(nsSHEntryShared);
[scriptable, uuid(6443FD72-A50F-4B8B-BB82-BB1FA04CB15D)]
[scriptable, uuid(162EA0EB-E577-4B9A-AF9D-A94E8350B029)]
interface nsISHEntry : nsIHistoryEntry
{
/** URI for the document */
@@ -237,6 +237,20 @@ interface nsISHEntry : nsIHistoryEntry
* it's preceeded by a call to adoptBFCacheEntry(aEntry).
*/
boolean sharesDocumentWith(in nsISHEntry aEntry);
/**
* True if this SHEntry corresponds to a document created by a srcdoc iframe.
* Set when a value is assigned to srcdocData.
*/
readonly attribute boolean isSrcdocEntry;
/**
* Contents of the srcdoc attribute in a srcdoc iframe to be loaded instead
* of the URI. Similar to a Data URI, this information is needed to
* recreate the document at a later stage.
* Setting this sets isSrcdocEntry to true
*/
attribute AString srcdocData;
};
[scriptable, uuid(bb66ac35-253b-471f-a317-3ece940f04c5)]

View File

@@ -35,6 +35,7 @@ nsSHEntry::nsSHEntry()
, mScrollPositionY(0)
, mParent(nullptr)
, mURIWasModified(false)
, mIsSrcdocEntry(false)
{
mShared = new nsSHEntryShared();
}
@@ -52,6 +53,8 @@ nsSHEntry::nsSHEntry(const nsSHEntry &other)
, mParent(other.mParent)
, mURIWasModified(other.mURIWasModified)
, mStateData(other.mStateData)
, mIsSrcdocEntry(other.mIsSrcdocEntry)
, mSrcdocData(other.mSrcdocData)
{
}
@@ -491,6 +494,30 @@ nsSHEntry::AbandonBFCacheEntry()
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetIsSrcdocEntry(bool* aIsSrcdocEntry)
{
*aIsSrcdocEntry = mIsSrcdocEntry;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::GetSrcdocData(nsAString &aSrcdocData)
{
aSrcdocData = mSrcdocData;
return NS_OK;
}
NS_IMETHODIMP
nsSHEntry::SetSrcdocData(const nsAString &aSrcdocData)
{
mSrcdocData = aSrcdocData;
mIsSrcdocEntry = true;
return NS_OK;
}
//*****************************************************************************
// nsSHEntry: nsISHContainer
//*****************************************************************************

View File

@@ -62,6 +62,8 @@ private:
nsCOMArray<nsISHEntry> mChildren;
bool mURIWasModified;
nsCOMPtr<nsIStructuredCloneContainer> mStateData;
bool mIsSrcdocEntry;
nsString mSrcdocData;
};
#endif /* nsSHEntry_h */