LCOV - code coverage report
Current view: top level - docshell/base - nsDSURIContentListener.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 71 108 65.7 %
Date: 2017-07-14 16:53:18 Functions: 10 15 66.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "nsDocShell.h"
       8             : #include "nsDSURIContentListener.h"
       9             : #include "nsIChannel.h"
      10             : #include "nsServiceManagerUtils.h"
      11             : #include "nsDocShellCID.h"
      12             : #include "nsIWebNavigationInfo.h"
      13             : #include "nsIDocument.h"
      14             : #include "nsIDOMWindow.h"
      15             : #include "nsIHttpChannel.h"
      16             : #include "nsError.h"
      17             : #include "nsDocShellLoadTypes.h"
      18             : #include "nsIMultiPartChannel.h"
      19             : 
      20             : using namespace mozilla;
      21             : 
      22           5 : nsDSURIContentListener::nsDSURIContentListener(nsDocShell* aDocShell)
      23             :   : mDocShell(aDocShell)
      24             :   , mExistingJPEGRequest(nullptr)
      25           5 :   , mParentContentListener(nullptr)
      26             : {
      27           5 : }
      28             : 
      29           0 : nsDSURIContentListener::~nsDSURIContentListener()
      30             : {
      31           0 : }
      32             : 
      33             : nsresult
      34           5 : nsDSURIContentListener::Init()
      35             : {
      36             :   nsresult rv;
      37           5 :   mNavInfo = do_GetService(NS_WEBNAVIGATION_INFO_CONTRACTID, &rv);
      38           5 :   NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to get webnav info");
      39           5 :   return rv;
      40             : }
      41             : 
      42          51 : NS_IMPL_ADDREF(nsDSURIContentListener)
      43          46 : NS_IMPL_RELEASE(nsDSURIContentListener)
      44             : 
      45          26 : NS_INTERFACE_MAP_BEGIN(nsDSURIContentListener)
      46          26 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIURIContentListener)
      47          26 :   NS_INTERFACE_MAP_ENTRY(nsIURIContentListener)
      48           2 :   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
      49           0 : NS_INTERFACE_MAP_END
      50             : 
      51             : NS_IMETHODIMP
      52           8 : nsDSURIContentListener::OnStartURIOpen(nsIURI* aURI, bool* aAbortOpen)
      53             : {
      54             :   // If mDocShell is null here, that means someone's starting a load in our
      55             :   // docshell after it's already been destroyed.  Don't let that happen.
      56           8 :   if (!mDocShell) {
      57           0 :     *aAbortOpen = true;
      58           0 :     return NS_OK;
      59             :   }
      60             : 
      61          16 :   nsCOMPtr<nsIURIContentListener> parentListener;
      62           8 :   GetParentContentListener(getter_AddRefs(parentListener));
      63           8 :   if (parentListener) {
      64           2 :     return parentListener->OnStartURIOpen(aURI, aAbortOpen);
      65             :   }
      66             : 
      67           6 :   return NS_OK;
      68             : }
      69             : 
      70             : NS_IMETHODIMP
      71           4 : nsDSURIContentListener::DoContent(const nsACString& aContentType,
      72             :                                   bool aIsContentPreferred,
      73             :                                   nsIRequest* aRequest,
      74             :                                   nsIStreamListener** aContentHandler,
      75             :                                   bool* aAbortProcess)
      76             : {
      77             :   nsresult rv;
      78           4 :   NS_ENSURE_ARG_POINTER(aContentHandler);
      79           4 :   NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
      80             : 
      81           4 :   *aAbortProcess = false;
      82             : 
      83             :   // determine if the channel has just been retargeted to us...
      84           4 :   nsLoadFlags loadFlags = 0;
      85           8 :   nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(aRequest);
      86             : 
      87           4 :   if (aOpenedChannel) {
      88           4 :     aOpenedChannel->GetLoadFlags(&loadFlags);
      89             :   }
      90             : 
      91           4 :   if (loadFlags & nsIChannel::LOAD_RETARGETED_DOCUMENT_URI) {
      92             :     // XXX: Why does this not stop the content too?
      93           0 :     mDocShell->Stop(nsIWebNavigation::STOP_NETWORK);
      94             : 
      95           0 :     mDocShell->SetLoadType(aIsContentPreferred ? LOAD_LINK : LOAD_NORMAL);
      96             :   }
      97             : 
      98             :   // In case of multipart jpeg request (mjpeg) we don't really want to
      99             :   // create new viewer since the one we already have is capable of
     100             :   // rendering multipart jpeg correctly (see bug 625012)
     101           8 :   nsCOMPtr<nsIChannel> baseChannel;
     102           8 :   if (nsCOMPtr<nsIMultiPartChannel> mpchan = do_QueryInterface(aRequest)) {
     103           0 :     mpchan->GetBaseChannel(getter_AddRefs(baseChannel));
     104             :   }
     105             : 
     106           4 :   bool reuseCV = baseChannel && baseChannel == mExistingJPEGRequest &&
     107           4 :                  aContentType.EqualsLiteral("image/jpeg");
     108             : 
     109           4 :   if (mExistingJPEGStreamListener && reuseCV) {
     110           0 :     RefPtr<nsIStreamListener> copy(mExistingJPEGStreamListener);
     111           0 :     copy.forget(aContentHandler);
     112           0 :     rv = NS_OK;
     113             :   } else {
     114           4 :     rv = mDocShell->CreateContentViewer(aContentType, aRequest, aContentHandler);
     115           4 :     if (NS_SUCCEEDED(rv) && reuseCV) {
     116           0 :       mExistingJPEGStreamListener = *aContentHandler;
     117             :     } else {
     118           4 :       mExistingJPEGStreamListener = nullptr;
     119             :     }
     120           4 :     mExistingJPEGRequest = baseChannel;
     121             :   }
     122             : 
     123           4 :   if (rv == NS_ERROR_REMOTE_XUL || rv == NS_ERROR_DOCSHELL_DYING) {
     124           0 :     aRequest->Cancel(rv);
     125           0 :     *aAbortProcess = true;
     126           0 :     return NS_OK;
     127             :   }
     128             : 
     129           4 :   if (NS_FAILED(rv)) {
     130             :     // we don't know how to handle the content
     131           0 :     *aContentHandler = nullptr;
     132           0 :     return rv;
     133             :   }
     134             : 
     135           4 :   if (loadFlags & nsIChannel::LOAD_RETARGETED_DOCUMENT_URI) {
     136             :     nsCOMPtr<nsPIDOMWindowOuter> domWindow =
     137           0 :       mDocShell ? mDocShell->GetWindow() : nullptr;
     138           0 :     NS_ENSURE_TRUE(domWindow, NS_ERROR_FAILURE);
     139           0 :     domWindow->Focus();
     140             :   }
     141             : 
     142           4 :   return NS_OK;
     143             : }
     144             : 
     145             : NS_IMETHODIMP
     146           0 : nsDSURIContentListener::IsPreferred(const char* aContentType,
     147             :                                     char** aDesiredContentType,
     148             :                                     bool* aCanHandle)
     149             : {
     150           0 :   NS_ENSURE_ARG_POINTER(aCanHandle);
     151           0 :   NS_ENSURE_ARG_POINTER(aDesiredContentType);
     152             : 
     153             :   // the docshell has no idea if it is the preferred content provider or not.
     154             :   // It needs to ask its parent if it is the preferred content handler or not...
     155             : 
     156           0 :   nsCOMPtr<nsIURIContentListener> parentListener;
     157           0 :   GetParentContentListener(getter_AddRefs(parentListener));
     158           0 :   if (parentListener) {
     159           0 :     return parentListener->IsPreferred(aContentType,
     160             :                                        aDesiredContentType,
     161           0 :                                        aCanHandle);
     162             :   }
     163             :   // we used to return false here if we didn't have a parent properly registered
     164             :   // at the top of the docshell hierarchy to dictate what content types this
     165             :   // docshell should be a preferred handler for. But this really makes it hard
     166             :   // for developers using iframe or browser tags because then they need to make
     167             :   // sure they implement nsIURIContentListener otherwise all link clicks would
     168             :   // get sent to another window because we said we weren't the preferred handler
     169             :   // type. I'm going to change the default now... if we can handle the content,
     170             :   // and someone didn't EXPLICITLY set a nsIURIContentListener at the top of our
     171             :   // docshell chain, then we'll now always attempt to process the content
     172             :   // ourselves...
     173           0 :   return CanHandleContent(aContentType, true, aDesiredContentType, aCanHandle);
     174             : }
     175             : 
     176             : NS_IMETHODIMP
     177           4 : nsDSURIContentListener::CanHandleContent(const char* aContentType,
     178             :                                          bool aIsContentPreferred,
     179             :                                          char** aDesiredContentType,
     180             :                                          bool* aCanHandleContent)
     181             : {
     182           4 :   NS_PRECONDITION(aCanHandleContent, "Null out param?");
     183           4 :   NS_ENSURE_ARG_POINTER(aDesiredContentType);
     184             : 
     185           4 :   *aCanHandleContent = false;
     186           4 :   *aDesiredContentType = nullptr;
     187             : 
     188           4 :   nsresult rv = NS_OK;
     189           4 :   if (aContentType) {
     190           4 :     uint32_t canHandle = nsIWebNavigationInfo::UNSUPPORTED;
     191          16 :     rv = mNavInfo->IsTypeSupported(nsDependentCString(aContentType),
     192           8 :                                    mDocShell,
     193           8 :                                    &canHandle);
     194           4 :     *aCanHandleContent = (canHandle != nsIWebNavigationInfo::UNSUPPORTED);
     195             :   }
     196             : 
     197           4 :   return rv;
     198             : }
     199             : 
     200             : NS_IMETHODIMP
     201           0 : nsDSURIContentListener::GetLoadCookie(nsISupports** aLoadCookie)
     202             : {
     203           0 :   NS_IF_ADDREF(*aLoadCookie = nsDocShell::GetAsSupports(mDocShell));
     204           0 :   return NS_OK;
     205             : }
     206             : 
     207             : NS_IMETHODIMP
     208           0 : nsDSURIContentListener::SetLoadCookie(nsISupports* aLoadCookie)
     209             : {
     210             : #ifdef DEBUG
     211             :   RefPtr<nsDocLoader> cookieAsDocLoader =
     212           0 :     nsDocLoader::GetAsDocLoader(aLoadCookie);
     213           0 :   NS_ASSERTION(cookieAsDocLoader && cookieAsDocLoader == mDocShell,
     214             :                "Invalid load cookie being set!");
     215             : #endif
     216           0 :   return NS_OK;
     217             : }
     218             : 
     219             : NS_IMETHODIMP
     220           8 : nsDSURIContentListener::GetParentContentListener(
     221             :     nsIURIContentListener** aParentListener)
     222             : {
     223           8 :   if (mWeakParentContentListener) {
     224             :     nsCOMPtr<nsIURIContentListener> tempListener =
     225           4 :       do_QueryReferent(mWeakParentContentListener);
     226           2 :     *aParentListener = tempListener;
     227           2 :     NS_IF_ADDREF(*aParentListener);
     228             :   } else {
     229           6 :     *aParentListener = mParentContentListener;
     230           6 :     NS_IF_ADDREF(*aParentListener);
     231             :   }
     232           8 :   return NS_OK;
     233             : }
     234             : 
     235             : NS_IMETHODIMP
     236           3 : nsDSURIContentListener::SetParentContentListener(
     237             :     nsIURIContentListener* aParentListener)
     238             : {
     239           3 :   if (aParentListener) {
     240             :     // Store the parent listener as a weak ref. Parents not supporting
     241             :     // nsISupportsWeakReference assert but may still be used.
     242           2 :     mParentContentListener = nullptr;
     243           2 :     mWeakParentContentListener = do_GetWeakReference(aParentListener);
     244           2 :     if (!mWeakParentContentListener) {
     245           0 :       mParentContentListener = aParentListener;
     246             :     }
     247             :   } else {
     248           1 :     mWeakParentContentListener = nullptr;
     249           1 :     mParentContentListener = nullptr;
     250             :   }
     251           3 :   return NS_OK;
     252             : }

Generated by: LCOV version 1.13