зеркало из https://github.com/mozilla/gecko-dev.git
Bug 433616 part 2. Implement loading of external resource documents. r=jst, sr=roc
This commit is contained in:
Родитель
a6aec54eaf
Коммит
72a7d1cba0
|
@ -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,7 +6986,9 @@ nsDocument::PostUnblockOnloadEvent()
|
|||
void
|
||||
nsDocument::DoUnblockOnload()
|
||||
{
|
||||
NS_ASSERTION(mOnloadBlockCount != 0,
|
||||
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");
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
@ -2096,13 +2100,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 {
|
||||
|
@ -2114,7 +2119,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;
|
||||
|
@ -2291,6 +2298,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);
|
||||
|
@ -2679,6 +2703,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)
|
||||
{
|
||||
|
@ -2701,6 +2757,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;
|
||||
|
@ -2732,6 +2791,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();
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче