mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-12 04:45:45 +00:00
Merge backout of changeset 4e7a2d27d636: relanding part of bug 433616 to test the theory that it was the cause of the regression, and something else caused an equal regression when we backed it out.
This commit is contained in:
commit
04df678063
@ -52,13 +52,13 @@
|
||||
#include "nsCompatibility.h"
|
||||
#include "nsTObserverArray.h"
|
||||
#include "nsNodeInfoManager.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIObserver.h"
|
||||
|
||||
class nsIContent;
|
||||
class nsPresContext;
|
||||
class nsIPresShell;
|
||||
class nsIDocShell;
|
||||
class nsIStreamListener;
|
||||
class nsIStreamObserver;
|
||||
class nsStyleSet;
|
||||
class nsIStyleSheet;
|
||||
class nsIStyleRule;
|
||||
@ -77,7 +77,6 @@ class nsIChannel;
|
||||
class nsIPrincipal;
|
||||
class nsIDOMDocument;
|
||||
class nsIDOMDocumentType;
|
||||
class nsIObserver;
|
||||
class nsScriptLoader;
|
||||
class nsIContentSink;
|
||||
class nsIScriptEventManager;
|
||||
@ -97,8 +96,8 @@ class nsFrameLoader;
|
||||
|
||||
// IID for the nsIDocument interface
|
||||
#define NS_IDOCUMENT_IID \
|
||||
{ 0xd5b1e3c5, 0x85dc, 0x403e, \
|
||||
{ 0xbb, 0x4a, 0x54, 0x66, 0xdc, 0xbe, 0x15, 0x69 } }
|
||||
{ 0x189ebc9e, 0x779b, 0x4c49, \
|
||||
{ 0x90, 0x8b, 0x9a, 0x80, 0x25, 0x9b, 0xaf, 0xa7 } }
|
||||
|
||||
// Flag for AddStyleSheet().
|
||||
#define NS_STYLESHEET_FROM_CATALOG (1 << 0)
|
||||
@ -1004,6 +1003,98 @@ public:
|
||||
virtual void TryCancelFrameLoaderInitialization(nsIDocShell* aShell) = 0;
|
||||
// Returns true if the frame loader of aShell is in the finalization list.
|
||||
virtual PRBool FrameLoaderScheduledToBeFinalized(nsIDocShell* aShell) = 0;
|
||||
|
||||
/**
|
||||
* Check whether this document is a root document that is not an
|
||||
* external resource.
|
||||
*/
|
||||
PRBool IsRootDisplayDocument() const
|
||||
{
|
||||
return !mParentDocument && !mDisplayDocument;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the document for which this document is an external resource. This
|
||||
* will be null if this document is not an external resource. Otherwise,
|
||||
* GetDisplayDocument() will return a non-null document, and
|
||||
* GetDisplayDocument()->GetDisplayDocument() is guaranteed to be null.
|
||||
*/
|
||||
nsIDocument* GetDisplayDocument() const
|
||||
{
|
||||
return mDisplayDocument;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the display document for this document. aDisplayDocument must not be
|
||||
* null.
|
||||
*/
|
||||
void SetDisplayDocument(nsIDocument* aDisplayDocument)
|
||||
{
|
||||
NS_PRECONDITION(!GetPrimaryShell() &&
|
||||
!nsCOMPtr<nsISupports>(GetContainer()) &&
|
||||
!GetWindow() &&
|
||||
!GetScriptGlobalObject(),
|
||||
"Shouldn't set mDisplayDocument on documents that already "
|
||||
"have a presentation or a docshell or a window");
|
||||
NS_PRECONDITION(aDisplayDocument != this, "Should be different document");
|
||||
NS_PRECONDITION(!aDisplayDocument->GetDisplayDocument(),
|
||||
"Display documents should not nest");
|
||||
mDisplayDocument = aDisplayDocument;
|
||||
}
|
||||
|
||||
/**
|
||||
* A class that represents an external resource load that has begun but
|
||||
* doesn't have a document yet. Observers can be registered on this object,
|
||||
* and will be notified after the document is created. Observers registered
|
||||
* after the document has been created will NOT be notified. When observers
|
||||
* are notified, the subject will be the newly-created document, the topic
|
||||
* will be "external-resource-document-created", and the data will be null.
|
||||
* If document creation fails for some reason, observers will still be
|
||||
* notified, with a null document pointer.
|
||||
*/
|
||||
class ExternalResourceLoad : public nsISupports
|
||||
{
|
||||
public:
|
||||
virtual ~ExternalResourceLoad() {}
|
||||
|
||||
void AddObserver(nsIObserver* aObserver) {
|
||||
NS_PRECONDITION(aObserver, "Must have observer");
|
||||
mObservers.AppendElement(aObserver);
|
||||
}
|
||||
|
||||
const nsTArray< nsCOMPtr<nsIObserver> > & Observers() {
|
||||
return mObservers;
|
||||
}
|
||||
protected:
|
||||
nsAutoTArray< nsCOMPtr<nsIObserver>, 8 > mObservers;
|
||||
};
|
||||
|
||||
/**
|
||||
* Request an external resource document for aURI. This will return the
|
||||
* resource document if available. If one is not available yet, it will
|
||||
* start loading as needed, and the pending load object will be returned in
|
||||
* aPendingLoad so that the caller can register an observer to wait for the
|
||||
* load. If this function returns null and doesn't return a pending load,
|
||||
* that means that there is no resource document for this URI and won't be
|
||||
* one in the future.
|
||||
*
|
||||
* @param aURI the URI to get
|
||||
* @param aRequestingNode the node making the request
|
||||
* @param aPendingLoad the pending load for this request, if any
|
||||
*/
|
||||
virtual nsIDocument*
|
||||
RequestExternalResource(nsIURI* aURI,
|
||||
nsINode* aRequestingNode,
|
||||
ExternalResourceLoad** aPendingLoad) = 0;
|
||||
|
||||
/**
|
||||
* Enumerate the external resource documents associated with this document.
|
||||
* The enumerator callback should return PR_TRUE to continue enumerating, or
|
||||
* PR_FALSE to stop.
|
||||
*/
|
||||
virtual void EnumerateExternalResources(nsSubDocEnumFunc aCallback,
|
||||
void* aData) = 0;
|
||||
|
||||
protected:
|
||||
~nsIDocument()
|
||||
{
|
||||
@ -1100,6 +1191,11 @@ protected:
|
||||
nsCOMArray<nsINode> mSubtreeModifiedTargets;
|
||||
PRUint32 mSubtreeModifiedDepth;
|
||||
|
||||
// If we're an external resource document, this will be non-null and will
|
||||
// point to our "display document": the one that all resource lookups should
|
||||
// go to.
|
||||
nsCOMPtr<nsIDocument> mDisplayDocument;
|
||||
|
||||
private:
|
||||
// JSObject cache. Only to be used for performance
|
||||
// optimizations. This will be set once this document is touched
|
||||
|
@ -2911,6 +2911,10 @@ nsContentUtils::IsInChromeDocshell(nsIDocument *aDocument)
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (aDocument->GetDisplayDocument()) {
|
||||
return IsInChromeDocshell(aDocument->GetDisplayDocument());
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupports> docContainer = aDocument->GetContainer();
|
||||
nsCOMPtr<nsIDocShellTreeItem> docShell(do_QueryInterface(docContainer));
|
||||
PRInt32 itemType = nsIDocShellTreeItem::typeContent;
|
||||
|
@ -72,7 +72,28 @@ nsDataDocumentContentPolicy::ShouldLoad(PRUint32 aContentType,
|
||||
doc = do_QueryInterface(domDoc);
|
||||
}
|
||||
}
|
||||
if (aContentType != nsIContentPolicy::TYPE_DTD && doc && doc->IsLoadedAsData()) {
|
||||
|
||||
// DTDs are always OK to load
|
||||
if (!doc || aContentType == nsIContentPolicy::TYPE_DTD) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Nothing else is OK to load for data documents
|
||||
if (doc->IsLoadedAsData()) {
|
||||
*aDecision = nsIContentPolicy::REJECT_TYPE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Allow all loads for non-external-resource documents
|
||||
if (!doc->GetDisplayDocument()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// For external resources, blacklist some load types
|
||||
if (aContentType == nsIContentPolicy::TYPE_OBJECT ||
|
||||
aContentType == nsIContentPolicy::TYPE_DOCUMENT ||
|
||||
aContentType == nsIContentPolicy::TYPE_SUBDOCUMENT ||
|
||||
aContentType == nsIContentPolicy::TYPE_SCRIPT) {
|
||||
*aDecision = nsIContentPolicy::REJECT_TYPE;
|
||||
}
|
||||
|
||||
|
@ -157,11 +157,23 @@ static NS_DEFINE_CID(kDOMEventGroupCID, NS_DOMEVENTGROUP_CID);
|
||||
#include "nsCycleCollector.h"
|
||||
#include "nsCCUncollectableMarker.h"
|
||||
#include "nsIContentPolicy.h"
|
||||
#include "nsContentPolicyUtils.h"
|
||||
#include "nsICategoryManager.h"
|
||||
#include "nsIDocumentLoaderFactory.h"
|
||||
#include "nsIContentViewer.h"
|
||||
#include "nsIXMLContentSink.h"
|
||||
#include "nsIChannelEventSink.h"
|
||||
#include "nsContentErrors.h"
|
||||
#include "nsIXULDocument.h"
|
||||
#include "nsIProgressEventSink.h"
|
||||
#include "nsISecurityEventSink.h"
|
||||
#include "nsIPrompt.h"
|
||||
|
||||
#include "nsFrameLoader.h"
|
||||
|
||||
#include "mozAutoDocUpdate.h"
|
||||
|
||||
|
||||
#ifdef MOZ_LOGGING
|
||||
// so we can get logging even in release builds
|
||||
#define FORCE_PR_LOG 1
|
||||
@ -718,6 +730,433 @@ nsOnloadBlocker::SetLoadFlags(nsLoadFlags aLoadFlags)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// ==================================================================
|
||||
|
||||
nsExternalResourceMap::nsExternalResourceMap()
|
||||
: mHaveShutDown(PR_FALSE)
|
||||
{
|
||||
mMap.Init();
|
||||
mPendingLoads.Init();
|
||||
}
|
||||
|
||||
nsIDocument*
|
||||
nsExternalResourceMap::RequestResource(nsIURI* aURI,
|
||||
nsINode* aRequestingNode,
|
||||
nsDocument* aDisplayDocument,
|
||||
ExternalResourceLoad** aPendingLoad)
|
||||
{
|
||||
// If we ever start allowing non-same-origin loads here, we might need to do
|
||||
// something interesting with aRequestingPrincipal even for the hashtable
|
||||
// gets.
|
||||
NS_PRECONDITION(aURI, "Must have a URI");
|
||||
NS_PRECONDITION(aRequestingNode, "Must have a node");
|
||||
*aPendingLoad = nsnull;
|
||||
if (mHaveShutDown) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
// First, make sure we strip the ref from aURI.
|
||||
nsCOMPtr<nsIURI> clone;
|
||||
aURI->Clone(getter_AddRefs(clone));
|
||||
if (!clone) {
|
||||
return nsnull;
|
||||
}
|
||||
nsCOMPtr<nsIURL> url(do_QueryInterface(clone));
|
||||
if (url) {
|
||||
url->SetRef(EmptyCString());
|
||||
}
|
||||
|
||||
ExternalResource* resource;
|
||||
mMap.Get(clone, &resource);
|
||||
if (resource) {
|
||||
return resource->mDocument;
|
||||
}
|
||||
|
||||
nsRefPtr<PendingLoad> load;
|
||||
mPendingLoads.Get(clone, getter_AddRefs(load));
|
||||
if (load) {
|
||||
NS_ADDREF(*aPendingLoad = load);
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
load = new PendingLoad(aDisplayDocument);
|
||||
if (!load) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (!mPendingLoads.Put(clone, load)) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (NS_FAILED(load->StartLoad(clone, aRequestingNode))) {
|
||||
// Make sure we don't thrash things by trying this load again, since
|
||||
// chances are it failed for good reasons (security check, etc).
|
||||
AddExternalResource(clone, nsnull, nsnull, aDisplayDocument);
|
||||
} else {
|
||||
NS_ADDREF(*aPendingLoad = load);
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
struct
|
||||
nsExternalResourceEnumArgs
|
||||
{
|
||||
nsIDocument::nsSubDocEnumFunc callback;
|
||||
void *data;
|
||||
};
|
||||
|
||||
PR_STATIC_CALLBACK(PLDHashOperator)
|
||||
ExternalResourceEnumerator(nsIURI* aKey,
|
||||
nsExternalResourceMap::ExternalResource* aData,
|
||||
void* aClosure)
|
||||
{
|
||||
nsExternalResourceEnumArgs* args =
|
||||
static_cast<nsExternalResourceEnumArgs*>(aClosure);
|
||||
PRBool next = args->callback(aData->mDocument, args->data);
|
||||
return next ? PL_DHASH_NEXT : PL_DHASH_STOP;
|
||||
}
|
||||
|
||||
void
|
||||
nsExternalResourceMap::EnumerateResources(nsIDocument::nsSubDocEnumFunc aCallback,
|
||||
void* aData)
|
||||
{
|
||||
nsExternalResourceEnumArgs args = { aCallback, aData };
|
||||
mMap.EnumerateRead(ExternalResourceEnumerator, &args);
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(PLDHashOperator)
|
||||
ExternalResourceTraverser(nsIURI* aKey,
|
||||
nsExternalResourceMap::ExternalResource* aData,
|
||||
void* aClosure)
|
||||
{
|
||||
nsCycleCollectionTraversalCallback *cb =
|
||||
static_cast<nsCycleCollectionTraversalCallback*>(aClosure);
|
||||
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
|
||||
"mExternalResourceMap.mMap entry"
|
||||
"->mDocument");
|
||||
cb->NoteXPCOMChild(aData->mDocument);
|
||||
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
|
||||
"mExternalResourceMap.mMap entry"
|
||||
"->mViewer");
|
||||
cb->NoteXPCOMChild(aData->mViewer);
|
||||
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
|
||||
"mExternalResourceMap.mMap entry"
|
||||
"->mLoadGroup");
|
||||
cb->NoteXPCOMChild(aData->mLoadGroup);
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
nsExternalResourceMap::Traverse(nsCycleCollectionTraversalCallback* aCallback) const
|
||||
{
|
||||
// mPendingLoads will get cleared out as the requests complete, so
|
||||
// no need to worry about those here.
|
||||
mMap.EnumerateRead(ExternalResourceTraverser, aCallback);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsExternalResourceMap::AddExternalResource(nsIURI* aURI,
|
||||
nsIDocumentViewer* aViewer,
|
||||
nsILoadGroup* aLoadGroup,
|
||||
nsIDocument* aDisplayDocument)
|
||||
{
|
||||
NS_PRECONDITION(aURI, "Unexpected call");
|
||||
NS_PRECONDITION((aViewer && aLoadGroup) || (!aViewer && !aLoadGroup),
|
||||
"Must have both or neither");
|
||||
|
||||
nsRefPtr<PendingLoad> load;
|
||||
mPendingLoads.Get(aURI, getter_AddRefs(load));
|
||||
mPendingLoads.Remove(aURI);
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
if (aViewer) {
|
||||
aViewer->GetDocument(getter_AddRefs(doc));
|
||||
NS_ASSERTION(doc, "Must have a document");
|
||||
|
||||
nsCOMPtr<nsIXULDocument> xulDoc = do_QueryInterface(doc);
|
||||
if (xulDoc) {
|
||||
// We don't handle XUL stuff here yet.
|
||||
rv = NS_ERROR_NOT_AVAILABLE;
|
||||
} else {
|
||||
doc->SetDisplayDocument(aDisplayDocument);
|
||||
|
||||
rv = aViewer->Init(nsnull, nsRect(0, 0, 0, 0));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = aViewer->Open(nsnull, nsnull);
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
doc = nsnull;
|
||||
aViewer = nsnull;
|
||||
aLoadGroup = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
ExternalResource* newResource = new ExternalResource();
|
||||
if (newResource && !mMap.Put(aURI, newResource)) {
|
||||
delete newResource;
|
||||
newResource = nsnull;
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
if (newResource) {
|
||||
newResource->mDocument = doc;
|
||||
newResource->mViewer = aViewer;
|
||||
newResource->mLoadGroup = aLoadGroup;
|
||||
}
|
||||
|
||||
const nsTArray< nsCOMPtr<nsIObserver> > & obs = load->Observers();
|
||||
for (PRUint32 i = 0; i < obs.Length(); ++i) {
|
||||
obs[i]->Observe(doc, "external-resource-document-created", nsnull);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsExternalResourceMap::PendingLoad,
|
||||
nsIStreamListener,
|
||||
nsIRequestObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsExternalResourceMap::PendingLoad::OnStartRequest(nsIRequest *aRequest,
|
||||
nsISupports *aContext)
|
||||
{
|
||||
nsExternalResourceMap& map = mDisplayDocument->ExternalResourceMap();
|
||||
if (map.HaveShutDown()) {
|
||||
return NS_BINDING_ABORTED;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocumentViewer> viewer;
|
||||
nsCOMPtr<nsILoadGroup> loadGroup;
|
||||
nsresult rv = SetupViewer(aRequest, getter_AddRefs(viewer),
|
||||
getter_AddRefs(loadGroup));
|
||||
|
||||
// Make sure to do this no matter what
|
||||
nsresult rv2 = map.AddExternalResource(mURI, viewer, loadGroup,
|
||||
mDisplayDocument);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
if (NS_FAILED(rv2)) {
|
||||
mTargetListener = nsnull;
|
||||
return rv2;
|
||||
}
|
||||
|
||||
return mTargetListener->OnStartRequest(aRequest, aContext);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsExternalResourceMap::PendingLoad::SetupViewer(nsIRequest* aRequest,
|
||||
nsIDocumentViewer** aViewer,
|
||||
nsILoadGroup** aLoadGroup)
|
||||
{
|
||||
NS_PRECONDITION(!mTargetListener, "Unexpected call to OnStartRequest");
|
||||
*aViewer = nsnull;
|
||||
*aLoadGroup = nsnull;
|
||||
|
||||
nsCOMPtr<nsIChannel> chan(do_QueryInterface(aRequest));
|
||||
NS_ENSURE_TRUE(chan, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aRequest));
|
||||
if (httpChannel) {
|
||||
PRBool requestSucceeded;
|
||||
if (NS_FAILED(httpChannel->GetRequestSucceeded(&requestSucceeded)) ||
|
||||
!requestSucceeded) {
|
||||
// Bail out on this load, since it looks like we have an HTTP error page
|
||||
return NS_BINDING_ABORTED;
|
||||
}
|
||||
}
|
||||
|
||||
nsCAutoString type;
|
||||
chan->GetContentType(type);
|
||||
|
||||
nsCOMPtr<nsILoadGroup> loadGroup;
|
||||
chan->GetLoadGroup(getter_AddRefs(loadGroup));
|
||||
|
||||
// Give this document its own loadgroup
|
||||
nsCOMPtr<nsILoadGroup> newLoadGroup =
|
||||
do_CreateInstance(NS_LOADGROUP_CONTRACTID);
|
||||
NS_ENSURE_TRUE(newLoadGroup, NS_ERROR_OUT_OF_MEMORY);
|
||||
newLoadGroup->SetLoadGroup(loadGroup);
|
||||
|
||||
nsCOMPtr<nsIInterfaceRequestor> callbacks;
|
||||
loadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
|
||||
|
||||
nsCOMPtr<nsIInterfaceRequestor> newCallbacks =
|
||||
new LoadgroupCallbacks(callbacks);
|
||||
newLoadGroup->SetNotificationCallbacks(newCallbacks);
|
||||
|
||||
// This is some serious hackery cribbed from docshell
|
||||
nsCOMPtr<nsICategoryManager> catMan =
|
||||
do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
|
||||
NS_ENSURE_TRUE(catMan, NS_ERROR_NOT_AVAILABLE);
|
||||
nsXPIDLCString contractId;
|
||||
nsresult rv = catMan->GetCategoryEntry("Gecko-Content-Viewers", type.get(),
|
||||
getter_Copies(contractId));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIDocumentLoaderFactory> docLoaderFactory =
|
||||
do_GetService(contractId);
|
||||
NS_ENSURE_TRUE(docLoaderFactory, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
nsCOMPtr<nsIContentViewer> viewer;
|
||||
nsCOMPtr<nsIStreamListener> listener;
|
||||
rv = docLoaderFactory->CreateInstance("external-resource", chan, newLoadGroup,
|
||||
type.get(), nsnull, nsnull,
|
||||
getter_AddRefs(listener),
|
||||
getter_AddRefs(viewer));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDocumentViewer> docViewer = do_QueryInterface(viewer);
|
||||
NS_ENSURE_TRUE(docViewer, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsCOMPtr<nsIParser> parser = do_QueryInterface(listener);
|
||||
if (!parser) {
|
||||
/// We don't want to deal with the various fake documents yet
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
// We can't handle HTML and other weird things here yet.
|
||||
nsIContentSink* sink = parser->GetContentSink();
|
||||
nsCOMPtr<nsIXMLContentSink> xmlSink = do_QueryInterface(sink);
|
||||
if (!xmlSink) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
listener.swap(mTargetListener);
|
||||
docViewer.swap(*aViewer);
|
||||
newLoadGroup.swap(*aLoadGroup);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsExternalResourceMap::PendingLoad::OnDataAvailable(nsIRequest* aRequest,
|
||||
nsISupports* aContext,
|
||||
nsIInputStream* aStream,
|
||||
PRUint32 aOffset,
|
||||
PRUint32 aCount)
|
||||
{
|
||||
NS_PRECONDITION(mTargetListener, "Shouldn't be getting called!");
|
||||
if (mDisplayDocument->ExternalResourceMap().HaveShutDown()) {
|
||||
return NS_BINDING_ABORTED;
|
||||
}
|
||||
return mTargetListener->OnDataAvailable(aRequest, aContext, aStream, aOffset,
|
||||
aCount);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsExternalResourceMap::PendingLoad::OnStopRequest(nsIRequest* aRequest,
|
||||
nsISupports* aContext,
|
||||
nsresult aStatus)
|
||||
{
|
||||
// mTargetListener might be null if SetupViewer or AddExternalResource failed
|
||||
if (mTargetListener) {
|
||||
nsCOMPtr<nsIStreamListener> listener;
|
||||
mTargetListener.swap(listener);
|
||||
return listener->OnStopRequest(aRequest, aContext, aStatus);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsExternalResourceMap::PendingLoad::StartLoad(nsIURI* aURI,
|
||||
nsINode* aRequestingNode)
|
||||
{
|
||||
NS_PRECONDITION(aURI, "Must have a URI");
|
||||
NS_PRECONDITION(aRequestingNode, "Must have a node");
|
||||
|
||||
// Time to start a load. First, the security checks.
|
||||
|
||||
nsIPrincipal* requestingPrincipal = aRequestingNode->NodePrincipal();
|
||||
|
||||
nsresult rv = nsContentUtils::GetSecurityManager()->
|
||||
CheckLoadURIWithPrincipal(requestingPrincipal, aURI,
|
||||
nsIScriptSecurityManager::STANDARD);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = requestingPrincipal->CheckMayLoad(aURI, PR_TRUE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
|
||||
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_OTHER,
|
||||
aURI,
|
||||
requestingPrincipal,
|
||||
aRequestingNode,
|
||||
EmptyCString(), //mime guess
|
||||
nsnull, //extra
|
||||
&shouldLoad,
|
||||
nsContentUtils::GetContentPolicy(),
|
||||
nsContentUtils::GetSecurityManager());
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (NS_CP_REJECTED(shouldLoad)) {
|
||||
// Disallowed by content policy
|
||||
return NS_ERROR_CONTENT_BLOCKED;
|
||||
}
|
||||
|
||||
nsIDocument* doc = aRequestingNode->GetOwnerDoc();
|
||||
if (!doc) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsILoadGroup> loadGroup = doc->GetDocumentLoadGroup();
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
rv = NS_NewChannel(getter_AddRefs(channel), aURI, nsnull, loadGroup);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mURI = aURI;
|
||||
|
||||
nsCOMPtr<nsIInterfaceRequestor> req = nsContentUtils::GetSameOriginChecker();
|
||||
NS_ENSURE_TRUE(req, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
channel->SetNotificationCallbacks(req);
|
||||
return channel->AsyncOpen(this, nsnull);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsExternalResourceMap::LoadgroupCallbacks,
|
||||
nsIInterfaceRequestor)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsExternalResourceMap::LoadgroupCallbacks::GetInterface(const nsIID & aIID,
|
||||
void **aSink)
|
||||
{
|
||||
#define IID_IS(_i) aIID.Equals(NS_GET_IID(_i))
|
||||
if (mCallbacks &&
|
||||
(IID_IS(nsIProgressEventSink) ||
|
||||
IID_IS(nsIChannelEventSink) ||
|
||||
IID_IS(nsISecurityEventSink) ||
|
||||
IID_IS(nsIPrompt) ||
|
||||
IID_IS(nsIAuthPrompt) ||
|
||||
IID_IS(nsIAuthPrompt2) ||
|
||||
IID_IS(nsIApplicationCacheContainer) ||
|
||||
// XXXbz evil hack for cookies for now
|
||||
IID_IS(nsIDOMWindow) ||
|
||||
IID_IS(nsIDocShellTreeItem))) {
|
||||
return mCallbacks->GetInterface(aIID, aSink);
|
||||
}
|
||||
#undef IID_IS
|
||||
|
||||
*aSink = nsnull;
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
nsExternalResourceMap::ExternalResource::~ExternalResource()
|
||||
{
|
||||
if (mViewer) {
|
||||
mViewer->Close(nsnull);
|
||||
mViewer->Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
// ==================================================================
|
||||
// =
|
||||
// ==================================================================
|
||||
@ -1194,7 +1633,8 @@ SubDocTraverser(PLDHashTable *table, PLDHashEntryHdr *hdr, PRUint32 number,
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(PLDHashOperator)
|
||||
RadioGroupsTraverser(const nsAString& aKey, nsAutoPtr<nsRadioGroupStruct>& aData, void* aClosure)
|
||||
RadioGroupsTraverser(const nsAString& aKey, nsRadioGroupStruct* aData,
|
||||
void* aClosure)
|
||||
{
|
||||
nsCycleCollectionTraversalCallback *cb =
|
||||
static_cast<nsCycleCollectionTraversalCallback*>(aClosure);
|
||||
@ -1261,6 +1701,8 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDocument)
|
||||
|
||||
tmp->mIdentifierMap.EnumerateEntries(IdentifierMapEntryTraverse, &cb);
|
||||
|
||||
tmp->mExternalResourceMap.Traverse(&cb);
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mNodeInfo)
|
||||
|
||||
// Traverse the mChildren nsAttrAndChildArray.
|
||||
@ -1276,6 +1718,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mNodeInfoManager,
|
||||
nsNodeInfoManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mSecurityInfo)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDisplayDocument)
|
||||
|
||||
// Traverse all nsDocument nsCOMPtrs.
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParser)
|
||||
@ -1284,7 +1727,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDOMStyleSheets)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mScriptLoader)
|
||||
|
||||
tmp->mRadioGroups.Enumerate(RadioGroupsTraverser, &cb);
|
||||
tmp->mRadioGroups.EnumerateRead(RadioGroupsTraverser, &cb);
|
||||
|
||||
// The boxobject for an element will only exist as long as it's in the
|
||||
// document, so we'll traverse the table here instead of from the element.
|
||||
@ -1326,6 +1769,9 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
|
||||
// from the doc.
|
||||
tmp->DestroyLinkMap();
|
||||
|
||||
// Clear out our external resources
|
||||
tmp->mExternalResourceMap.Shutdown();
|
||||
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
|
||||
// Unlink the mChildren nsAttrAndChildArray.
|
||||
@ -1336,6 +1782,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCachedRootContent)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDisplayDocument)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_USERDATA
|
||||
|
||||
@ -1711,6 +2158,9 @@ nsDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel,
|
||||
|
||||
// styles
|
||||
CSSLoader()->SetEnabled(PR_FALSE); // Do not load/process styles when loading as data
|
||||
} else if (nsCRT::strcmp("external-resource", aCommand) == 0) {
|
||||
// Allow CSS, but not scripts
|
||||
ScriptLoader()->SetEnabled(PR_FALSE);
|
||||
}
|
||||
|
||||
mMayStartLayout = PR_FALSE;
|
||||
@ -4703,6 +5153,29 @@ nsDocument::FrameLoaderScheduledToBeFinalized(nsIDocShell* aShell)
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsIDocument*
|
||||
nsDocument::RequestExternalResource(nsIURI* aURI,
|
||||
nsINode* aRequestingNode,
|
||||
ExternalResourceLoad** aPendingLoad)
|
||||
{
|
||||
NS_PRECONDITION(aURI, "Must have a URI");
|
||||
NS_PRECONDITION(aRequestingNode, "Must have a node");
|
||||
if (mDisplayDocument) {
|
||||
return mDisplayDocument->RequestExternalResource(aURI,
|
||||
aRequestingNode,
|
||||
aPendingLoad);
|
||||
}
|
||||
|
||||
return mExternalResourceMap.RequestResource(aURI, aRequestingNode,
|
||||
this, aPendingLoad);
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::EnumerateExternalResources(nsSubDocEnumFunc aCallback, void* aData)
|
||||
{
|
||||
mExternalResourceMap.EnumerateResources(aCallback, aData);
|
||||
}
|
||||
|
||||
struct DirTable {
|
||||
const char* mName;
|
||||
PRUint8 mValue;
|
||||
@ -5860,20 +6333,20 @@ PRBool
|
||||
nsDocument::IsScriptEnabled()
|
||||
{
|
||||
nsCOMPtr<nsIScriptSecurityManager> sm(do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID));
|
||||
NS_ENSURE_TRUE(sm, PR_TRUE);
|
||||
NS_ENSURE_TRUE(sm, PR_FALSE);
|
||||
|
||||
nsIScriptGlobalObject* globalObject = GetScriptGlobalObject();
|
||||
NS_ENSURE_TRUE(globalObject, PR_TRUE);
|
||||
NS_ENSURE_TRUE(globalObject, PR_FALSE);
|
||||
|
||||
nsIScriptContext *scriptContext = globalObject->GetContext();
|
||||
NS_ENSURE_TRUE(scriptContext, PR_TRUE);
|
||||
NS_ENSURE_TRUE(scriptContext, PR_FALSE);
|
||||
|
||||
JSContext* cx = (JSContext *) scriptContext->GetNativeContext();
|
||||
NS_ENSURE_TRUE(cx, PR_TRUE);
|
||||
NS_ENSURE_TRUE(cx, PR_FALSE);
|
||||
|
||||
PRBool enabled;
|
||||
nsresult rv = sm->CanExecuteScripts(cx, NodePrincipal(), &enabled);
|
||||
NS_ENSURE_SUCCESS(rv, PR_TRUE);
|
||||
NS_ENSURE_SUCCESS(rv, PR_FALSE);
|
||||
return enabled;
|
||||
}
|
||||
|
||||
@ -6396,6 +6869,11 @@ nsDocument::Destroy()
|
||||
|
||||
nsContentList::OnDocumentDestroy(this);
|
||||
|
||||
// Shut down our external resource map. We might not need this for
|
||||
// leak-fixing if we fix DocumentViewerImpl to do cycle-collection, but
|
||||
// tearing down all those frame trees right now is the right thing to do.
|
||||
mExternalResourceMap.Shutdown();
|
||||
|
||||
// XXX We really should let cycle collection do this, but that currently still
|
||||
// leaks (see https://bugzilla.mozilla.org/show_bug.cgi?id=406684).
|
||||
// When we start relying on cycle collection again we should remove the
|
||||
@ -6437,6 +6915,11 @@ nsDocument::GetLayoutHistoryState() const
|
||||
void
|
||||
nsDocument::BlockOnload()
|
||||
{
|
||||
if (mDisplayDocument) {
|
||||
mDisplayDocument->BlockOnload();
|
||||
return;
|
||||
}
|
||||
|
||||
// If mScriptGlobalObject is null, we shouldn't be messing with the loadgroup
|
||||
// -- it's not ours.
|
||||
if (mOnloadBlockCount == 0 && mScriptGlobalObject) {
|
||||
@ -6451,6 +6934,11 @@ nsDocument::BlockOnload()
|
||||
void
|
||||
nsDocument::UnblockOnload(PRBool aFireSync)
|
||||
{
|
||||
if (mDisplayDocument) {
|
||||
mDisplayDocument->UnblockOnload(aFireSync);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mOnloadBlockCount == 0) {
|
||||
NS_NOTREACHED("More UnblockOnload() calls than BlockOnload() calls; dropping call");
|
||||
return;
|
||||
@ -6498,12 +6986,14 @@ nsDocument::PostUnblockOnloadEvent()
|
||||
void
|
||||
nsDocument::DoUnblockOnload()
|
||||
{
|
||||
NS_ASSERTION(mOnloadBlockCount != 0,
|
||||
"Shouldn't have a count of zero here, since we stabilized in "
|
||||
"PostUnblockOnloadEvent");
|
||||
NS_PRECONDITION(!mDisplayDocument,
|
||||
"Shouldn't get here for resource document");
|
||||
NS_PRECONDITION(mOnloadBlockCount != 0,
|
||||
"Shouldn't have a count of zero here, since we stabilized in "
|
||||
"PostUnblockOnloadEvent");
|
||||
|
||||
--mOnloadBlockCount;
|
||||
|
||||
|
||||
if (mOnloadBlockCount != 0) {
|
||||
// We blocked again after the last unblock. Nothing to do here. We'll
|
||||
// post a new event when we unblock again.
|
||||
|
@ -108,6 +108,8 @@
|
||||
#include "nsPresShellIterator.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsIDocumentViewer.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
|
||||
#define XML_DECLARATION_BITS_DECLARATION_EXISTS (1 << 0)
|
||||
#define XML_DECLARATION_BITS_ENCODING_EXISTS (1 << 1)
|
||||
@ -383,6 +385,117 @@ private:
|
||||
~nsOnloadBlocker() {}
|
||||
};
|
||||
|
||||
class nsExternalResourceMap
|
||||
{
|
||||
public:
|
||||
typedef nsIDocument::ExternalResourceLoad ExternalResourceLoad;
|
||||
nsExternalResourceMap();
|
||||
|
||||
/**
|
||||
* Request an external resource document. This does exactly what
|
||||
* nsIDocument::RequestExternalResource is documented to do.
|
||||
*/
|
||||
nsIDocument* RequestResource(nsIURI* aURI,
|
||||
nsINode* aRequestingNode,
|
||||
nsDocument* aDisplayDocument,
|
||||
ExternalResourceLoad** aPendingLoad);
|
||||
|
||||
/**
|
||||
* Enumerate the resource documents. See
|
||||
* nsIDocument::EnumerateExternalResources.
|
||||
*/
|
||||
void EnumerateResources(nsIDocument::nsSubDocEnumFunc aCallback, void* aData);
|
||||
|
||||
/**
|
||||
* Traverse ourselves for cycle-collection
|
||||
*/
|
||||
void Traverse(nsCycleCollectionTraversalCallback* aCallback) const;
|
||||
|
||||
/**
|
||||
* Shut ourselves down (used for cycle-collection unlink), as well
|
||||
* as for document destruction.
|
||||
*/
|
||||
void Shutdown()
|
||||
{
|
||||
mPendingLoads.Clear();
|
||||
mMap.Clear();
|
||||
mHaveShutDown = PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool HaveShutDown() const
|
||||
{
|
||||
return mHaveShutDown;
|
||||
}
|
||||
|
||||
// Needs to be public so we can traverse them sanely
|
||||
struct ExternalResource
|
||||
{
|
||||
~ExternalResource();
|
||||
nsCOMPtr<nsIDocument> mDocument;
|
||||
nsCOMPtr<nsIContentViewer> mViewer;
|
||||
nsCOMPtr<nsILoadGroup> mLoadGroup;
|
||||
};
|
||||
|
||||
protected:
|
||||
class PendingLoad : public ExternalResourceLoad,
|
||||
public nsIStreamListener
|
||||
{
|
||||
public:
|
||||
PendingLoad(nsDocument* aDisplayDocument) :
|
||||
mDisplayDocument(aDisplayDocument)
|
||||
{}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
|
||||
/**
|
||||
* Start aURI loading. This will perform the necessary security checks and
|
||||
* so forth.
|
||||
*/
|
||||
nsresult StartLoad(nsIURI* aURI, nsINode* aRequestingNode);
|
||||
|
||||
/**
|
||||
* Set up an nsIDocumentViewer based on aRequest. This is guaranteed to
|
||||
* put null in *aViewer and *aLoadGroup on all failures.
|
||||
*/
|
||||
nsresult SetupViewer(nsIRequest* aRequest, nsIDocumentViewer** aViewer,
|
||||
nsILoadGroup** aLoadGroup);
|
||||
|
||||
private:
|
||||
nsRefPtr<nsDocument> mDisplayDocument;
|
||||
nsCOMPtr<nsIStreamListener> mTargetListener;
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
};
|
||||
friend class PendingLoad;
|
||||
|
||||
class LoadgroupCallbacks : public nsIInterfaceRequestor
|
||||
{
|
||||
public:
|
||||
LoadgroupCallbacks(nsIInterfaceRequestor* aOtherCallbacks)
|
||||
: mCallbacks(aOtherCallbacks)
|
||||
{}
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
private:
|
||||
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
|
||||
};
|
||||
|
||||
/**
|
||||
* Add an ExternalResource for aURI. aViewer and aLoadGroup might be null
|
||||
* when this is called if the URI didn't result in an XML document. This
|
||||
* function makes sure to remove the pending load for aURI, if any, from our
|
||||
* hashtable, and to notify its observers, if any.
|
||||
*/
|
||||
nsresult AddExternalResource(nsIURI* aURI, nsIDocumentViewer* aViewer,
|
||||
nsILoadGroup* aLoadGroup,
|
||||
nsIDocument* aDisplayDocument);
|
||||
|
||||
nsClassHashtable<nsURIHashKey, ExternalResource> mMap;
|
||||
nsRefPtrHashtable<nsURIHashKey, PendingLoad> mPendingLoads;
|
||||
PRPackedBool mHaveShutDown;
|
||||
};
|
||||
|
||||
// Base class for our document implementations.
|
||||
//
|
||||
// Note that this class *implements* nsIDOMXMLDocument, but it's not
|
||||
@ -802,6 +915,12 @@ public:
|
||||
virtual NS_HIDDEN_(nsresult) FinalizeFrameLoader(nsFrameLoader* aLoader);
|
||||
virtual NS_HIDDEN_(void) TryCancelFrameLoaderInitialization(nsIDocShell* aShell);
|
||||
virtual NS_HIDDEN_(PRBool) FrameLoaderScheduledToBeFinalized(nsIDocShell* aShell);
|
||||
virtual NS_HIDDEN_(nsIDocument*)
|
||||
RequestExternalResource(nsIURI* aURI,
|
||||
nsINode* aRequestingNode,
|
||||
ExternalResourceLoad** aPendingLoad);
|
||||
virtual NS_HIDDEN_(void)
|
||||
EnumerateExternalResources(nsSubDocEnumFunc aCallback, void* aData);
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsDocument, nsIDocument)
|
||||
|
||||
@ -815,6 +934,11 @@ public:
|
||||
|
||||
void DoNotifyPossibleTitleChange();
|
||||
|
||||
nsExternalResourceMap& ExternalResourceMap()
|
||||
{
|
||||
return mExternalResourceMap;
|
||||
}
|
||||
|
||||
void SetLoadedAsData(PRBool aLoadedAsData) { mLoadedAsData = aLoadedAsData; }
|
||||
|
||||
nsresult CloneDocHelper(nsDocument* clone) const;
|
||||
@ -1087,6 +1211,8 @@ private:
|
||||
nsTArray<nsRefPtr<nsFrameLoader> > mFinalizableFrameLoaders;
|
||||
|
||||
nsRevocableEventPtr<nsRunnableMethod<nsDocument> > mPendingTitleChangeEvent;
|
||||
|
||||
nsExternalResourceMap mExternalResourceMap;
|
||||
};
|
||||
|
||||
#endif /* nsDocument_h___ */
|
||||
|
@ -727,6 +727,11 @@ nsFrameLoader::EnsureDocShell()
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (doc->GetDisplayDocument()) {
|
||||
// Don't allow subframe loads in external reference documents
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWebNavigation> parentAsWebNav =
|
||||
do_GetInterface(doc->GetScriptGlobalObject());
|
||||
|
||||
|
@ -54,6 +54,7 @@ REQUIRES = \
|
||||
thebes \
|
||||
dom \
|
||||
webshell \
|
||||
docshell \
|
||||
htmlparser \
|
||||
necko \
|
||||
pref \
|
||||
|
@ -2488,7 +2488,7 @@ nsXULElement::HideWindowChrome(PRBool aShouldHide)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
// only top level chrome documents can hide the window chrome
|
||||
if (doc->GetParentDocument())
|
||||
if (!doc->IsRootDisplayDocument())
|
||||
return NS_OK;
|
||||
|
||||
nsIPresShell *shell = doc->GetPrimaryShell();
|
||||
@ -2522,7 +2522,7 @@ nsXULElement::SetTitlebarColor(nscolor aColor, PRBool aActive)
|
||||
}
|
||||
|
||||
// only top level chrome documents can set the titlebar color
|
||||
if (!doc->GetParentDocument()) {
|
||||
if (doc->IsRootDisplayDocument()) {
|
||||
nsCOMPtr<nsISupports> container = doc->GetContainer();
|
||||
nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(container);
|
||||
if (baseWindow) {
|
||||
|
@ -817,7 +817,11 @@ DocumentViewerImpl::InitInternal(nsIWidget* aParentWidget,
|
||||
|
||||
PRBool makeCX = PR_FALSE;
|
||||
if (aDoCreation) {
|
||||
if (aParentWidget && !mPresContext) {
|
||||
// XXXbz this is a nasty hack to do with the fact that we create
|
||||
// presentations both in Init() and in Show()... Ideally we would only do
|
||||
// it in one place (Show()) and require that callers call init(), open(),
|
||||
// show() in that order or something.
|
||||
if ((aParentWidget || mDocument->GetDisplayDocument()) && !mPresContext) {
|
||||
// Create presentation context
|
||||
if (mIsPageMode) {
|
||||
//Presentation context already created in SetPageMode which is calling this method
|
||||
@ -1241,12 +1245,12 @@ DocumentViewerImpl::Open(nsISupports *aState, nsISHEntry *aSHEntry)
|
||||
nsRect bounds;
|
||||
mWindow->GetBounds(bounds);
|
||||
|
||||
nsresult rv = InitInternal(mParentWidget, aState, bounds, PR_FALSE, PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (mDocument)
|
||||
mDocument->SetContainer(nsCOMPtr<nsISupports>(do_QueryReferent(mContainer)));
|
||||
|
||||
nsresult rv = InitInternal(mParentWidget, aState, bounds, PR_FALSE, PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (mPresShell)
|
||||
mPresShell->SetForwardingContainer(nsnull);
|
||||
|
||||
@ -2101,13 +2105,14 @@ DocumentViewerImpl::CreateStyleSet(nsIDocument* aDocument,
|
||||
// The document will fill in the document sheets when we create the presshell
|
||||
|
||||
// Handle the user sheets.
|
||||
PRInt32 shellType = nsIDocShellTreeItem::typeContent;;
|
||||
nsCOMPtr<nsIDocShellTreeItem> docShell(do_QueryReferent(mContainer));
|
||||
if (docShell) {
|
||||
docShell->GetItemType(&shellType);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
nsCOMPtr<nsISupports> debugDocContainer = aDocument->GetContainer();
|
||||
nsCOMPtr<nsIDocShellTreeItem> debugDocShell(do_QueryReferent(mContainer));
|
||||
NS_ASSERTION(SameCOMIdentity(debugDocContainer, debugDocShell),
|
||||
"Unexpected containers");
|
||||
#endif
|
||||
nsICSSStyleSheet* sheet = nsnull;
|
||||
if (shellType == nsIDocShellTreeItem::typeChrome) {
|
||||
if (nsContentUtils::IsInChromeDocshell(aDocument)) {
|
||||
sheet = nsLayoutStylesheetCache::UserChromeSheet();
|
||||
}
|
||||
else {
|
||||
@ -2119,7 +2124,9 @@ DocumentViewerImpl::CreateStyleSet(nsIDocument* aDocument,
|
||||
|
||||
// Append chrome sheets (scrollbars + forms).
|
||||
PRBool shouldOverride = PR_FALSE;
|
||||
nsCOMPtr<nsIDocShell> ds(do_QueryInterface(docShell));
|
||||
// We don't want a docshell here for external resource docs, so just
|
||||
// look at mContainer.
|
||||
nsCOMPtr<nsIDocShell> ds(do_QueryReferent(mContainer));
|
||||
nsCOMPtr<nsIDOMEventTarget> chromeHandler;
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsCOMPtr<nsICSSStyleSheet> csssheet;
|
||||
@ -2296,6 +2303,23 @@ DocumentViewerImpl::CreateDeviceContext(nsIWidget* aWidget)
|
||||
{
|
||||
NS_PRECONDITION(!mPresShell && !mPresContext && !mWindow,
|
||||
"This will screw up our existing presentation");
|
||||
NS_PRECONDITION(mDocument, "Gotta have a document here");
|
||||
|
||||
nsIDocument* doc = mDocument->GetDisplayDocument();
|
||||
if (doc) {
|
||||
NS_ASSERTION(!aWidget, "Shouldn't have a widget here");
|
||||
|
||||
// We want to use our display document's device context if possible
|
||||
nsIPresShell* shell = doc->GetPrimaryShell();
|
||||
if (shell) {
|
||||
nsPresContext* ctx = shell->GetPresContext();
|
||||
if (ctx) {
|
||||
mDeviceContext = ctx->DeviceContext();
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create a device context even if we already have one, since our widget
|
||||
// might have changed.
|
||||
mDeviceContext = do_CreateInstance(kDeviceContextCID);
|
||||
@ -2684,6 +2708,38 @@ SetChildFullZoom(nsIMarkupDocumentViewer* aChild, void* aClosure)
|
||||
aChild->SetFullZoom(ZoomInfo->mZoom);
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(PRBool)
|
||||
SetExtResourceTextZoom(nsIDocument* aDocument, void* aClosure)
|
||||
{
|
||||
// Would it be better to enumerate external resource viewers instead?
|
||||
nsIPresShell* shell = aDocument->GetPrimaryShell();
|
||||
if (shell) {
|
||||
nsPresContext* ctxt = shell->GetPresContext();
|
||||
if (ctxt) {
|
||||
struct ZoomInfo* ZoomInfo = static_cast<struct ZoomInfo*>(aClosure);
|
||||
ctxt->SetTextZoom(ZoomInfo->mZoom);
|
||||
}
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(PRBool)
|
||||
SetExtResourceFullZoom(nsIDocument* aDocument, void* aClosure)
|
||||
{
|
||||
// Would it be better to enumerate external resource viewers instead?
|
||||
nsIPresShell* shell = aDocument->GetPrimaryShell();
|
||||
if (shell) {
|
||||
nsPresContext* ctxt = shell->GetPresContext();
|
||||
if (ctxt) {
|
||||
struct ZoomInfo* ZoomInfo = static_cast<struct ZoomInfo*>(aClosure);
|
||||
ctxt->SetFullZoom(ZoomInfo->mZoom);
|
||||
}
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentViewerImpl::SetTextZoom(float aTextZoom)
|
||||
{
|
||||
@ -2706,6 +2762,9 @@ DocumentViewerImpl::SetTextZoom(float aTextZoom)
|
||||
pc->SetTextZoom(aTextZoom);
|
||||
}
|
||||
|
||||
// And do the external resources
|
||||
mDocument->EnumerateExternalResources(SetExtResourceTextZoom, &ZoomInfo);
|
||||
|
||||
batch.EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
|
||||
|
||||
return NS_OK;
|
||||
@ -2737,6 +2796,9 @@ DocumentViewerImpl::SetFullZoom(float aFullZoom)
|
||||
pc->SetFullZoom(aFullZoom);
|
||||
}
|
||||
|
||||
// And do the external resources
|
||||
mDocument->EnumerateExternalResources(SetExtResourceFullZoom, &ZoomInfo);
|
||||
|
||||
batch.EndUpdateViewBatch(NS_VMREFRESH_NO_SYNC);
|
||||
|
||||
return NS_OK;
|
||||
|
@ -555,9 +555,11 @@ nsSubDocumentFrame::Reflow(nsPresContext* aPresContext,
|
||||
innerSize.height -= aReflowState.mComputedBorderPadding.TopBottom();
|
||||
}
|
||||
|
||||
nsIViewManager* vm = mInnerView->GetViewManager();
|
||||
vm->MoveViewTo(mInnerView, offset.x, offset.y);
|
||||
vm->ResizeView(mInnerView, nsRect(nsPoint(0, 0), innerSize), PR_TRUE);
|
||||
if (mInnerView) {
|
||||
nsIViewManager* vm = mInnerView->GetViewManager();
|
||||
vm->MoveViewTo(mInnerView, offset.x, offset.y);
|
||||
vm->ResizeView(mInnerView, nsRect(nsPoint(0, 0), innerSize), PR_TRUE);
|
||||
}
|
||||
|
||||
// Determine if we need to repaint our border, background or outline
|
||||
CheckInvalidateSizeChange(aDesiredSize);
|
||||
|
@ -609,7 +609,9 @@ nsObjectFrame::Init(nsIContent* aContent,
|
||||
nsIFrame* aParent,
|
||||
nsIFrame* aPrevInFlow)
|
||||
{
|
||||
mPreventInstantiation = PR_FALSE;
|
||||
NS_PRECONDITION(aContent, "How did that happen?");
|
||||
mPreventInstantiation =
|
||||
(aContent->GetCurrentDoc()->GetDisplayDocument() != nsnull);
|
||||
|
||||
PR_LOG(nsObjectFrameLM, PR_LOG_DEBUG,
|
||||
("Initializing nsObjectFrame %p for content %p\n", this, aContent));
|
||||
@ -620,7 +622,9 @@ nsObjectFrame::Init(nsIContent* aContent,
|
||||
void
|
||||
nsObjectFrame::Destroy()
|
||||
{
|
||||
NS_ASSERTION(!mPreventInstantiation, "about to crash due to bug 136927");
|
||||
NS_ASSERTION(!mPreventInstantiation ||
|
||||
mContent && mContent->GetCurrentDoc()->GetDisplayDocument(),
|
||||
"about to crash due to bug 136927");
|
||||
|
||||
// we need to finish with the plugin before native window is destroyed
|
||||
// doing this in the destructor is too late.
|
||||
@ -1718,6 +1722,7 @@ nsObjectFrame::Instantiate(const char* aMimeType, nsIURI* aURI)
|
||||
return rv;
|
||||
mInstanceOwner->SetPluginHost(pluginHost);
|
||||
|
||||
NS_ASSERTION(!mPreventInstantiation, "Say what?");
|
||||
mPreventInstantiation = PR_TRUE;
|
||||
|
||||
rv = InstantiatePlugin(pluginHost, aMimeType, aURI);
|
||||
|
Loading…
Reference in New Issue
Block a user