From 508e44c469c385c182493537e120de0c864b8574 Mon Sep 17 00:00:00 2001 From: "tbogard%aol.net" Date: Sat, 6 Nov 1999 04:51:05 +0000 Subject: [PATCH] Changed the nsIDocShell parent attribute to not create a cycle. Added notes about this. Framed out start of usage for the uriloader. Added code for the new nsDSURIContentListener object to be the callback object for nsIURIContentListener passed to uriloader. --- docshell/base/makefile.win | 1 + docshell/base/nsDSURIContentListener.cpp | 152 +++++++++++++++++++++++ docshell/base/nsDSURIContentListener.h | 57 +++++++++ docshell/base/nsDocShellBase.cpp | 107 ++++++++++++---- docshell/base/nsDocShellBase.h | 17 ++- 5 files changed, 306 insertions(+), 28 deletions(-) create mode 100644 docshell/base/nsDSURIContentListener.cpp create mode 100644 docshell/base/nsDSURIContentListener.h diff --git a/docshell/base/makefile.win b/docshell/base/makefile.win index 4e1bf1f74e0..54a9cc3ad9d 100644 --- a/docshell/base/makefile.win +++ b/docshell/base/makefile.win @@ -36,6 +36,7 @@ LIBRARY_NAME=basedocshell_s CPP_OBJS= \ .\$(OBJDIR)\nsDocShellBase.obj \ + .\$(OBJDIR)\nsDSURIContentListener.obj \ $(NULL) include <$(DEPTH)\config\rules.mak> diff --git a/docshell/base/nsDSURIContentListener.cpp b/docshell/base/nsDSURIContentListener.cpp new file mode 100644 index 00000000000..ac940475823 --- /dev/null +++ b/docshell/base/nsDSURIContentListener.cpp @@ -0,0 +1,152 @@ +/* -*- Mode: C++; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Mozilla browser. + * + * The Initial Developer of the Original Code is Netscape + * Communications, Inc. Portions created by Netscape are + * Copyright (C) 1999, Mozilla. All Rights Reserved. + * + * Contributor(s): + * Travis Bogard + */ + +#include "nsDocShellBase.h" +#include "nsDSURIContentListener.h" + +//***************************************************************************** +//*** nsDSURIContentListener: Object Management +//***************************************************************************** + +nsDSURIContentListener::nsDSURIContentListener() : mDocShell(nsnull) +{ + NS_INIT_REFCNT(); +} + +nsDSURIContentListener::~nsDSURIContentListener() +{ +} + +//***************************************************************************** +// nsDSURIContentListener::nsISupports +//***************************************************************************** + +NS_IMPL_ISUPPORTS1(nsDSURIContentListener, nsIURIContentListener) + +//***************************************************************************** +// nsDSURIContentListener::nsIURIContentListener +//***************************************************************************** + +NS_IMETHODIMP nsDSURIContentListener::GetProtocolHandler(nsIURI* aURI, + nsIProtocolHandler** aProtocolHandler) +{ + NS_ENSURE_ARG_POINTER(aProtocolHandler); + NS_ENSURE_ARG(aURI); + + if(mParentContentListener) + return mParentContentListener->GetProtocolHandler(aURI, aProtocolHandler); + else + *aProtocolHandler = nsnull; + + return NS_OK; +} + +NS_IMETHODIMP nsDSURIContentListener::DoContent(const char* aContentType, + const char* aCommand, const char* aWindowTarget, nsIChannel* aOpenedChannel, + nsIStreamListener** aContentHandler, PRBool* aAbortProcess) +{ + NS_ENSURE_ARG_POINTER(aContentHandler && aAbortProcess); + + /* The URIDispatcher will give the content listener a shot at handling + the content before it tries other means. If the content listener + wants to handle the content then it should return a stream listener + the data should be pushed into. + aContentType --> the content type we need to handle + aCommand --> verb for the action (this comes from layout???) + aWindowTarget --> name of the target window if any + aStreamListener --> the content viewer the content should be displayed in + You should return null for this out parameter if you do + not want to handle this content type. + aAbortProcess --> If you want to handle the content yourself and you don't + want the dispatcher to do anything else, return TRUE for + this parameter. + */ + + if(HandleInCurrentDocShell(aContentType, aCommand, aWindowTarget)) + { + //XXX Start Load here.... + } + else + return mParentContentListener->DoContent(aContentType, aCommand, + aWindowTarget, aOpenedChannel, aContentHandler, aAbortProcess); + + return NS_OK; +} + +NS_IMETHODIMP nsDSURIContentListener::CanHandleContent(const char* aContentType, + const char* aCommand, const char* aWindowTarget, PRBool* aCanHandle) +{ + NS_ENSURE_ARG_POINTER(aCanHandle); + + *aCanHandle = PR_TRUE; // Always say true and let DoContent decide. + return NS_OK; +} + +//***************************************************************************** +// nsDSURIContentListener: Helpers +//***************************************************************************** + +PRBool nsDSURIContentListener::HandleInCurrentDocShell(const char* aContentType, + const char* aCommand, const char* aWindowTarget) +{ + nsAutoString contentType(aContentType); + PRBool fCanHandle; + NS_ENSURE_SUCCESS(mDocShell->CanHandleContentType(contentType.GetUnicode(), + &fCanHandle), PR_FALSE); + + NS_ENSURE_TRUE(fCanHandle, PR_FALSE); + + /* XXX Implement + 1.) Check content type + 2.) See if we can handle the command + 3.) See if the target is for us + */ + + return PR_FALSE; +} + +//***************************************************************************** +// nsDSURIContentListener: Accessors +//***************************************************************************** + +void nsDSURIContentListener::DocShellBase(nsDocShellBase* aDocShellBase) +{ + mDocShell = aDocShellBase; +} + +nsDocShellBase* nsDSURIContentListener::DocShellBase() +{ + return mDocShell; +} + +void nsDSURIContentListener::GetParentContentListener(nsIURIContentListener** + aParentListener) +{ + *aParentListener = mParentContentListener; + NS_IF_ADDREF(*aParentListener); +} + +void nsDSURIContentListener::SetParentContentListener(nsIURIContentListener* + aParentListener) +{ + mParentContentListener = aParentListener; +} \ No newline at end of file diff --git a/docshell/base/nsDSURIContentListener.h b/docshell/base/nsDSURIContentListener.h new file mode 100644 index 00000000000..639ee2ed88b --- /dev/null +++ b/docshell/base/nsDSURIContentListener.h @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the Mozilla browser. + * + * The Initial Developer of the Original Code is Netscape + * Communications, Inc. Portions created by Netscape are + * Copyright (C) 1999, Mozilla. All Rights Reserved. + * + * Contributor(s): + * Travis Bogard + */ + +#ifndef nsDSURIContentListener_h__ +#define nsDSURIContentListener_h__ + +#include "nsCOMPtr.h" +#include "nsString.h" +#include "nsIURIContentListener.h" + +class nsDocShellBase; + +class nsDSURIContentListener : public nsIURIContentListener +{ +public: + nsDSURIContentListener(); + + NS_DECL_ISUPPORTS + + NS_DECL_NSIURICONTENTLISTENER + + void DocShellBase(nsDocShellBase* aDocShellBase); + nsDocShellBase* DocShellBase(); + void GetParentContentListener(nsIURIContentListener** aParentListener); + void SetParentContentListener(nsIURIContentListener* aParentListener); + +protected: + virtual ~nsDSURIContentListener(); + + PRBool HandleInCurrentDocShell(const char* aContentType, + const char* aCommand, const char* aWindowTarget); + +protected: + nsDocShellBase* mDocShell; + nsCOMPtr mParentContentListener; +}; + +#endif /* nsDSURIContentListener_h__ */ diff --git a/docshell/base/nsDocShellBase.cpp b/docshell/base/nsDocShellBase.cpp index d715e1933eb..1a561b47633 100644 --- a/docshell/base/nsDocShellBase.cpp +++ b/docshell/base/nsDocShellBase.cpp @@ -1,4 +1,4 @@ -/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +/* -*- Mode: C++; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file @@ -20,10 +20,12 @@ * Travis Bogard */ +#include "nsIComponentManager.h" #include "nsIDocument.h" #include "nsIDOMDocument.h" #include "nsIDocumentViewer.h" #include "nsIDeviceContext.h" +#include "nsCURILoader.h" #include "nsDocShellBase.h" @@ -31,7 +33,7 @@ //*** nsDocShellBase: Object Management //***************************************************************************** -nsDocShellBase::nsDocShellBase() : mCreated(PR_FALSE) +nsDocShellBase::nsDocShellBase() : mCreated(PR_FALSE), mContentListener(nsnull) { NS_INIT_REFCNT(); mBaseInitInfo = new nsDocShellInitInfo(); @@ -44,6 +46,12 @@ nsDocShellBase::~nsDocShellBase() delete mBaseInitInfo; mBaseInitInfo = nsnull; } + + if(mContentListener) + { + mContentListener->Release(); + mContentListener = nsnull; + } } //***************************************************************************** @@ -65,21 +73,27 @@ NS_IMETHODIMP nsDocShellBase::LoadURI(const PRUnichar* uri, return LoadURIVia(uri, presContext, 0); } -NS_IMETHODIMP nsDocShellBase::LoadURIVia(const PRUnichar* uri, - nsIPresContext* presContext, PRUint32 adapterBinding) +NS_IMETHODIMP nsDocShellBase::LoadURIVia(const PRUnichar* aUri, + nsIPresContext* aPresContext, PRUint32 aAdapterBinding) { - NS_ENSURE_ARG(uri); - //XXX First Check - /* - Loads a given URI through the specified adapter. This will give priority - to loading the requested URI in the object implementing this interface. - If it can't be loaded here however, the URL dispatcher will go through its - normal process of content loading. + NS_ENSURE_ARG(aUri); - @param uri - The URI to load. - @param adapterBinding - The local IP address of the adapter to bind to. - */ - return NS_ERROR_FAILURE; + nsCOMPtr uriLoader; + NS_ENSURE_SUCCESS(nsComponentManager::CreateInstance(NS_URI_LOADER_PROGID, + nsnull, NS_GET_IID(nsIURILoader), getter_AddRefs(uriLoader)), + NS_ERROR_FAILURE); + + nsCOMPtr uri; + NS_ENSURE_SUCCESS(NewURI(aUri, getter_AddRefs(uri)), NS_ERROR_FAILURE); + + NS_ENSURE_SUCCESS(EnsureContentListener(), NS_ERROR_FAILURE); + + /* + Call uriloader passing mContentListener as the nsIURIContentListener + uriLoader->OpenURI(uri, nsnull, nsnull, + */ + + return NS_ERROR_FAILURE; } NS_IMETHODIMP nsDocShellBase::GetDocument(nsIDOMDocument** aDocument) @@ -104,20 +118,18 @@ NS_IMETHODIMP nsDocShellBase::GetDocument(nsIDOMDocument** aDocument) NS_IMETHODIMP nsDocShellBase::SetDocument(nsIDOMDocument* aDocument, nsIPresContext* presContext) { - NS_WARN_IF_FALSE(PR_FALSE, "Subclasses should override this method!!!!"); - return NS_ERROR_NOT_IMPLEMENTED; + NS_WARN_IF_FALSE(PR_FALSE, "Subclasses should override this method!!!!"); + return NS_ERROR_NOT_IMPLEMENTED; } // caller is responsible for calling nsString::Recycle(*aName); NS_IMETHODIMP nsDocShellBase::GetName(PRUnichar** aName) { - NS_ENSURE_ARG_POINTER(aName); - *aName = nsnull; - if (0!=mName.Length()) - { - *aName = mName.ToNewUnicode(); - } - return NS_OK; + NS_ENSURE_ARG_POINTER(aName); + *aName = nsnull; + if(0 != mName.Length()) + *aName = mName.ToNewUnicode(); + return NS_OK; } NS_IMETHODIMP nsDocShellBase::SetName(const PRUnichar* aName) @@ -162,10 +174,34 @@ NS_IMETHODIMP nsDocShellBase::GetParent(nsIDocShell** parent) NS_IMETHODIMP nsDocShellBase::SetParent(nsIDocShell* aParent) { // null aParent is ok - mParent = aParent; // this assignment does an addref + /* + Note this doesn't do an addref on purpose. This is because the parent + is an implied lifetime. We don't want to create a cycle by refcounting + the parent. + */ + mParent = aParent; return NS_OK; } +NS_IMETHODIMP nsDocShellBase::GetParentURIContentListener(nsIURIContentListener** + aParent) +{ + NS_ENSURE_ARG_POINTER(aParent); + NS_ENSURE_SUCCESS(EnsureContentListener(), NS_ERROR_FAILURE); + + mContentListener->GetParentContentListener(aParent); + return NS_OK; +} + +NS_IMETHODIMP nsDocShellBase::SetParentURIContentListener(nsIURIContentListener* + aParent) +{ + NS_ENSURE_SUCCESS(EnsureContentListener(), NS_ERROR_FAILURE); + + mContentListener->SetParentContentListener(aParent); + return NS_OK; +} + NS_IMETHODIMP nsDocShellBase::CanHandleContentType(const PRUnichar* contentType, PRBool* canHandle) { @@ -1079,3 +1115,24 @@ nsresult nsDocShellBase::GetPresShell(nsIPresShell** aPresShell) return NS_OK; } + +nsresult nsDocShellBase::NewURI(const PRUnichar* aUri, nsIURI** aURI) +{ + //XXX Get new URI + return NS_ERROR_FAILURE; +} + +nsresult nsDocShellBase::EnsureContentListener() +{ + if(mContentListener) + return NS_OK; + + mContentListener = new nsDSURIContentListener(); + NS_ENSURE_TRUE(mContentListener, NS_ERROR_OUT_OF_MEMORY); + + mContentListener->AddRef(); + mContentListener->DocShellBase(this); + + return NS_OK; +} + diff --git a/docshell/base/nsDocShellBase.h b/docshell/base/nsDocShellBase.h index 3290ae75cab..e99b089abc2 100644 --- a/docshell/base/nsDocShellBase.h +++ b/docshell/base/nsDocShellBase.h @@ -30,6 +30,7 @@ #include "nsIViewManager.h" #include "nsIScrollableView.h" #include "nsIContentViewer.h" +#include "nsIPref.h" #include "nsIDocShell.h" #include "nsIDocShellEdit.h" @@ -37,7 +38,8 @@ #include "nsIGenericWindow.h" #include "nsIScrollable.h" #include "nsITextScroll.h" -#include "nsIPref.h" + +#include "nsDSURIContentListener.h" class nsDocShellInitInfo { @@ -52,7 +54,7 @@ public: class nsDocShellBase : public nsIDocShell, public nsIDocShellEdit, public nsIDocShellFile, public nsIGenericWindow, public nsIScrollable, - public nsITextScroll + public nsITextScroll { public: NS_DECL_ISUPPORTS @@ -72,15 +74,24 @@ protected: PRInt32* aOffset); nsresult GetRootScrollableView(nsIScrollableView** aOutScrollView); nsresult GetPresShell(nsIPresShell** aPresShell); + nsresult NewURI(const PRUnichar* aUri, nsIURI** aURI); + nsresult EnsureContentListener(); protected: PRBool mCreated; nsString mName; + nsDSURIContentListener* mContentListener; nsDocShellInitInfo* mBaseInitInfo; nsCOMPtr mContentViewer; - nsCOMPtr mParent; nsCOMPtr mParentWidget; nsCOMPtr mPrefs; + + /* Note this can not be nsCOMPtr as that that would cause an addref on the + parent thus a cycle. A weak reference would work, but not required as the + interface states a requirement to zero out the parent when the parent is + releasing the interface.*/ + nsIDocShell* mParent; + }; #endif /* nsDocShellBase_h__ */