Back to index

lightning-sunbird  0.9+nobinonly
nsDSURIContentListener.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
00002  *
00003  * ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is the Mozilla browser.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications, Inc.
00020  * Portions created by the Initial Developer are Copyright (C) 1999
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Travis Bogard <travis@netscape.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #include "nsDocShell.h"
00041 #include "nsDSURIContentListener.h"
00042 #include "nsIChannel.h"
00043 #include "nsServiceManagerUtils.h"
00044 #include "nsXPIDLString.h"
00045 #include "nsDocShellCID.h"
00046 #include "nsIWebNavigationInfo.h"
00047 #include "nsIDOMWindowInternal.h"
00048 #include "nsAutoPtr.h"
00049 
00050 //*****************************************************************************
00051 //***    nsDSURIContentListener: Object Management
00052 //*****************************************************************************
00053 
00054 nsDSURIContentListener::nsDSURIContentListener(nsDocShell* aDocShell)
00055     : mDocShell(aDocShell), 
00056       mParentContentListener(nsnull)
00057 {
00058 }
00059 
00060 nsDSURIContentListener::~nsDSURIContentListener()
00061 {
00062 }
00063 
00064 nsresult
00065 nsDSURIContentListener::Init() 
00066 {
00067     nsresult rv;
00068     mNavInfo = do_GetService(NS_WEBNAVIGATION_INFO_CONTRACTID, &rv);
00069     NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to get webnav info");
00070     return rv;
00071 }
00072 
00073 
00074 //*****************************************************************************
00075 // nsDSURIContentListener::nsISupports
00076 //*****************************************************************************   
00077 
00078 NS_IMPL_THREADSAFE_ADDREF(nsDSURIContentListener)
00079 NS_IMPL_THREADSAFE_RELEASE(nsDSURIContentListener)
00080 
00081 NS_INTERFACE_MAP_BEGIN(nsDSURIContentListener)
00082     NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIURIContentListener)
00083     NS_INTERFACE_MAP_ENTRY(nsIURIContentListener)
00084     NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
00085 NS_INTERFACE_MAP_END
00086 
00087 //*****************************************************************************
00088 // nsDSURIContentListener::nsIURIContentListener
00089 //*****************************************************************************   
00090 
00091 NS_IMETHODIMP
00092 nsDSURIContentListener::OnStartURIOpen(nsIURI* aURI, PRBool* aAbortOpen)
00093 {
00094     nsCOMPtr<nsIURIContentListener> parentListener;
00095     GetParentContentListener(getter_AddRefs(parentListener));
00096     if (parentListener)
00097         return parentListener->OnStartURIOpen(aURI, aAbortOpen);
00098 
00099     return NS_OK;
00100 }
00101 
00102 NS_IMETHODIMP 
00103 nsDSURIContentListener::DoContent(const char* aContentType, 
00104                                   PRBool aIsContentPreferred,
00105                                   nsIRequest* request,
00106                                   nsIStreamListener** aContentHandler,
00107                                   PRBool* aAbortProcess)
00108 {
00109     nsresult rv;
00110     NS_ENSURE_ARG_POINTER(aContentHandler);
00111     NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
00112     if(aAbortProcess)
00113         *aAbortProcess = PR_FALSE;
00114 
00115     // determine if the channel has just been retargeted to us...
00116     nsLoadFlags loadFlags = 0;
00117     nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(request);
00118 
00119     if (aOpenedChannel)
00120       aOpenedChannel->GetLoadFlags(&loadFlags);
00121 
00122     if(loadFlags & nsIChannel::LOAD_RETARGETED_DOCUMENT_URI)
00123     {
00124         // XXX: Why does this not stop the content too?
00125         mDocShell->Stop(nsIWebNavigation::STOP_NETWORK);
00126 
00127         mDocShell->SetLoadType(aIsContentPreferred ? LOAD_LINK : LOAD_NORMAL);
00128     }
00129 
00130     rv = mDocShell->CreateContentViewer(aContentType, request, aContentHandler);
00131     if (NS_FAILED(rv)) {
00132        // it's okay if we don't know how to handle the content   
00133         return NS_OK;
00134     }
00135 
00136     if (loadFlags & nsIChannel::LOAD_RETARGETED_DOCUMENT_URI) {
00137         nsCOMPtr<nsIDOMWindowInternal> domWindow = do_GetInterface(NS_STATIC_CAST(nsIDocShell*, mDocShell));
00138         NS_ENSURE_TRUE(domWindow, NS_ERROR_FAILURE);
00139         domWindow->Focus();
00140     }
00141 
00142     return NS_OK;
00143 }
00144 
00145 NS_IMETHODIMP
00146 nsDSURIContentListener::IsPreferred(const char* aContentType,
00147                                     char ** aDesiredContentType,
00148                                     PRBool* aCanHandle)
00149 {
00150     NS_ENSURE_ARG_POINTER(aCanHandle);
00151     NS_ENSURE_ARG_POINTER(aDesiredContentType);
00152 
00153     // the docshell has no idea if it is the preferred content provider or not.
00154     // It needs to ask it's parent if it is the preferred content handler or not...
00155 
00156     nsCOMPtr<nsIURIContentListener> parentListener;
00157     GetParentContentListener(getter_AddRefs(parentListener));
00158     if (parentListener) {
00159         return parentListener->IsPreferred(aContentType,
00160                                                    aDesiredContentType,
00161                                                    aCanHandle);
00162     }
00163     // we used to return false here if we didn't have a parent properly
00164     // registered at the top of the docshell hierarchy to dictate what
00165     // content types this docshell should be a preferred handler for.  But
00166     // this really makes it hard for developers using iframe or browser tags
00167     // because then they need to make sure they implement
00168     // nsIURIContentListener otherwise all link clicks would get sent to
00169     // another window because we said we weren't the preferred handler type.
00170     // I'm going to change the default now...if we can handle the content,
00171     // and someone didn't EXPLICITLY set a nsIURIContentListener at the top
00172     // of our docshell chain, then we'll now always attempt to process the
00173     // content ourselves...
00174     return CanHandleContent(aContentType,
00175                             PR_TRUE,
00176                             aDesiredContentType,
00177                             aCanHandle);
00178 }
00179 
00180 NS_IMETHODIMP
00181 nsDSURIContentListener::CanHandleContent(const char* aContentType,
00182                                          PRBool aIsContentPreferred,
00183                                          char ** aDesiredContentType,
00184                                          PRBool* aCanHandleContent)
00185 {
00186     NS_PRECONDITION(aCanHandleContent, "Null out param?");
00187     NS_ENSURE_ARG_POINTER(aDesiredContentType);
00188 
00189     *aCanHandleContent = PR_FALSE;
00190     *aDesiredContentType = nsnull;
00191 
00192     nsresult rv = NS_OK;
00193     if (aContentType) {
00194         PRUint32 canHandle = nsIWebNavigationInfo::UNSUPPORTED;
00195         rv = mNavInfo->IsTypeSupported(nsDependentCString(aContentType),
00196                                        mDocShell,
00197                                        &canHandle);
00198         *aCanHandleContent = (canHandle != nsIWebNavigationInfo::UNSUPPORTED);
00199     }
00200 
00201     return rv;
00202 }
00203 
00204 NS_IMETHODIMP
00205 nsDSURIContentListener::GetLoadCookie(nsISupports ** aLoadCookie)
00206 {
00207     NS_IF_ADDREF(*aLoadCookie = nsDocShell::GetAsSupports(mDocShell));
00208     return NS_OK;
00209 }
00210 
00211 NS_IMETHODIMP
00212 nsDSURIContentListener::SetLoadCookie(nsISupports * aLoadCookie)
00213 {
00214 #ifdef DEBUG
00215     nsRefPtr<nsDocLoader> cookieAsDocLoader =
00216         nsDocLoader::GetAsDocLoader(aLoadCookie);
00217     NS_ASSERTION(cookieAsDocLoader && cookieAsDocLoader == mDocShell,
00218                  "Invalid load cookie being set!");
00219 #endif
00220     return NS_OK;
00221 }
00222 
00223 NS_IMETHODIMP 
00224 nsDSURIContentListener::GetParentContentListener(nsIURIContentListener**
00225                                                  aParentListener)
00226 {
00227     if (mWeakParentContentListener)
00228     {
00229         nsCOMPtr<nsIURIContentListener> tempListener =
00230             do_QueryReferent(mWeakParentContentListener);
00231         *aParentListener = tempListener;
00232         NS_IF_ADDREF(*aParentListener);
00233     }
00234     else {
00235         *aParentListener = mParentContentListener;
00236         NS_IF_ADDREF(*aParentListener);
00237     }
00238     return NS_OK;
00239 }
00240 
00241 NS_IMETHODIMP
00242 nsDSURIContentListener::SetParentContentListener(nsIURIContentListener* 
00243                                                  aParentListener)
00244 {
00245     if (aParentListener)
00246     {
00247         // Store the parent listener as a weak ref. Parents not supporting
00248         // nsISupportsWeakReference assert but may still be used.
00249         mParentContentListener = nsnull;
00250         mWeakParentContentListener = do_GetWeakReference(aParentListener);
00251         if (!mWeakParentContentListener)
00252         {
00253             mParentContentListener = aParentListener;
00254         }
00255     }
00256     else
00257     {
00258         mWeakParentContentListener = nsnull;
00259         mParentContentListener = nsnull;
00260     }
00261     return NS_OK;
00262 }