LCOV - code coverage report
Current view: top level - uriloader/exthandler - nsExternalHelperAppService.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 6 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 2 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #ifndef nsExternalHelperAppService_h__
       7             : #define nsExternalHelperAppService_h__
       8             : 
       9             : #include "mozilla/Logging.h"
      10             : #include "prtime.h"
      11             : 
      12             : #include "nsIExternalHelperAppService.h"
      13             : #include "nsIExternalProtocolService.h"
      14             : #include "nsIWebProgressListener2.h"
      15             : #include "nsIHelperAppLauncherDialog.h"
      16             : 
      17             : #include "nsIMIMEInfo.h"
      18             : #include "nsIMIMEService.h"
      19             : #include "nsIStreamListener.h"
      20             : #include "nsIFile.h"
      21             : #include "nsIFileStreams.h"
      22             : #include "nsIOutputStream.h"
      23             : #include "nsString.h"
      24             : #include "nsIInterfaceRequestor.h"
      25             : #include "nsIInterfaceRequestorUtils.h"
      26             : #include "nsIChannel.h"
      27             : #include "nsITimer.h"
      28             : #include "nsIBackgroundFileSaver.h"
      29             : 
      30             : #include "nsIHandlerService.h"
      31             : #include "nsCOMPtr.h"
      32             : #include "nsIObserver.h"
      33             : #include "nsCOMArray.h"
      34             : #include "nsWeakReference.h"
      35             : #include "nsIPrompt.h"
      36             : #include "nsAutoPtr.h"
      37             : #include "mozilla/Attributes.h"
      38             : 
      39             : class nsExternalAppHandler;
      40             : class nsIMIMEInfo;
      41             : class nsITransfer;
      42             : class nsPIDOMWindowOuter;
      43             : 
      44             : /**
      45             :  * The helper app service. Responsible for handling content that Mozilla
      46             :  * itself can not handle
      47             :  */
      48             : class nsExternalHelperAppService
      49             : : public nsIExternalHelperAppService,
      50             :   public nsPIExternalAppLauncher,
      51             :   public nsIExternalProtocolService,
      52             :   public nsIMIMEService,
      53             :   public nsIObserver,
      54             :   public nsSupportsWeakReference
      55             : {
      56             : public:
      57             :   NS_DECL_ISUPPORTS
      58             :   NS_DECL_NSIEXTERNALHELPERAPPSERVICE
      59             :   NS_DECL_NSPIEXTERNALAPPLAUNCHER
      60             :   NS_DECL_NSIEXTERNALPROTOCOLSERVICE
      61             :   NS_DECL_NSIMIMESERVICE
      62             :   NS_DECL_NSIOBSERVER
      63             : 
      64             :   nsExternalHelperAppService();
      65             : 
      66             :   /**
      67             :    * Initializes internal state. Will be called automatically when
      68             :    * this service is first instantiated.
      69             :    */
      70             :   MOZ_MUST_USE nsresult Init();
      71             :  
      72             :   /**
      73             :    * Given a mimetype and an extension, looks up a mime info from the OS.
      74             :    * The mime type is given preference. This function follows the same rules
      75             :    * as nsIMIMEService::GetFromTypeAndExtension.
      76             :    * This is supposed to be overridden by the platform-specific
      77             :    * nsOSHelperAppService!
      78             :    * @param aFileExt The file extension; may be empty. UTF-8 encoded.
      79             :    * @param [out] aFound
      80             :    *        Should be set to true if the os has a mapping, to
      81             :    *        false otherwise. Must not be null.
      82             :    * @return A MIMEInfo. This function must return a MIMEInfo object if it
      83             :    *         can allocate one.  The only justifiable reason for not
      84             :    *         returning one is an out-of-memory error.
      85             :    *         If null, the value of aFound is unspecified.
      86             :    */
      87             :   virtual already_AddRefed<nsIMIMEInfo> GetMIMEInfoFromOS(const nsACString& aMIMEType,
      88             :                                                           const nsACString& aFileExt,
      89             :                                                           bool       * aFound) = 0;
      90             : 
      91             :   /**
      92             :    * Given a string identifying an application, create an nsIFile representing
      93             :    * it. This function should look in $PATH for the application.
      94             :    * The base class implementation will first try to interpret platformAppPath
      95             :    * as an absolute path, and if that fails it will look for a file next to the
      96             :    * mozilla executable. Subclasses can override this method if they want a
      97             :    * different behaviour.
      98             :    * @param platformAppPath A platform specific path to an application that we
      99             :    *                        got out of the rdf data source. This can be a mac
     100             :    *                        file spec, a unix path or a windows path depending
     101             :    *                        on the platform
     102             :    * @param aFile           [out] An nsIFile representation of that platform
     103             :    *                        application path.
     104             :    */
     105             :   virtual nsresult GetFileTokenForPath(const char16_t * platformAppPath,
     106             :                                        nsIFile ** aFile);
     107             : 
     108             :   virtual nsresult OSProtocolHandlerExists(const char *aScheme,
     109             :                                                        bool *aExists) = 0;
     110             : 
     111             :   /**
     112             :    * Given an extension, get a MIME type string. If not overridden by
     113             :    * the OS-specific nsOSHelperAppService, will call into GetMIMEInfoFromOS
     114             :    * with an empty mimetype.
     115             :    * @return true if we successfully found a mimetype.
     116             :    */
     117             :   virtual bool GetMIMETypeFromOSForExtension(const nsACString& aExtension,
     118             :                                              nsACString& aMIMEType);
     119             : 
     120             : protected:
     121             :   virtual ~nsExternalHelperAppService();
     122             : 
     123             :   /**
     124             :    * Searches the "extra" array of MIMEInfo objects for an object
     125             :    * with a specific type. If found, it will modify the passed-in
     126             :    * MIMEInfo. Otherwise, it will return an error and the MIMEInfo
     127             :    * will be untouched.
     128             :    * @param aContentType The type to search for.
     129             :    * @param aMIMEInfo    [inout] The mime info, if found
     130             :    */
     131             :   nsresult FillMIMEInfoForMimeTypeFromExtras(
     132             :     const nsACString& aContentType, nsIMIMEInfo * aMIMEInfo);
     133             :   /**
     134             :    * Searches the "extra" array of MIMEInfo objects for an object
     135             :    * with a specific extension.
     136             :    *
     137             :    * Does not change the MIME Type of the MIME Info.
     138             :    *
     139             :    * @see FillMIMEInfoForMimeTypeFromExtras
     140             :    */
     141             :   nsresult FillMIMEInfoForExtensionFromExtras(
     142             :     const nsACString& aExtension, nsIMIMEInfo * aMIMEInfo);
     143             : 
     144             :   /**
     145             :    * Searches the "extra" array for a MIME type, and gets its extension.
     146             :    * @param aExtension The extension to search for
     147             :    * @param aMIMEType [out] The found MIME type.
     148             :    * @return true if the extension was found, false otherwise.
     149             :    */
     150             :   bool GetTypeFromExtras(const nsACString& aExtension,
     151             :                                        nsACString& aMIMEType);
     152             : 
     153             :   /**
     154             :    * Logging Module. Usage: set MOZ_LOG=HelperAppService:level, where level
     155             :    * should be 2 for errors, 3 for debug messages from the cross- platform
     156             :    * nsExternalHelperAppService, and 4 for os-specific debug messages.
     157             :    */
     158             :   static mozilla::LazyLogModule mLog;
     159             : 
     160             :   // friend, so that it can access the nspr log module.
     161             :   friend class nsExternalAppHandler;
     162             : 
     163             :   /**
     164             :    * Helper function for ExpungeTemporaryFiles and ExpungeTemporaryPrivateFiles
     165             :    */
     166             :   static void ExpungeTemporaryFilesHelper(nsCOMArray<nsIFile> &fileList);
     167             :   /**
     168             :    * Helper function for DeleteTemporaryFileOnExit and DeleteTemporaryPrivateFileWhenPossible
     169             :    */
     170             :   static nsresult DeleteTemporaryFileHelper(nsIFile* aTemporaryFile,
     171             :                                             nsCOMArray<nsIFile> &aFileList);
     172             :   /**
     173             :    * Functions related to the tempory file cleanup service provided by
     174             :    * nsExternalHelperAppService
     175             :    */
     176             :   void ExpungeTemporaryFiles();
     177             :   /**
     178             :    * Functions related to the tempory file cleanup service provided by
     179             :    * nsExternalHelperAppService (for the temporary files added during
     180             :    * the private browsing mode)
     181             :    */
     182             :   void ExpungeTemporaryPrivateFiles();
     183             : 
     184             :   /**
     185             :    * Array for the files that should be deleted
     186             :    */
     187             :   nsCOMArray<nsIFile> mTemporaryFilesList;
     188             :   /**
     189             :    * Array for the files that should be deleted (for the temporary files
     190             :    * added during the private browsing mode)
     191             :    */
     192             :   nsCOMArray<nsIFile> mTemporaryPrivateFilesList;
     193             : 
     194             : private:
     195             :   nsresult DoContentContentProcessHelper(const nsACString& aMimeContentType,
     196             :                                          nsIRequest *aRequest,
     197             :                                          nsIInterfaceRequestor *aContentContext,
     198             :                                          bool aForceSave,
     199             :                                          nsIInterfaceRequestor *aWindowContext,
     200             :                                          nsIStreamListener ** aStreamListener);
     201             : };
     202             : 
     203             : /**
     204             :  * An external app handler is just a small little class that presents itself as
     205             :  * a nsIStreamListener. It saves the incoming data into a temp file. The handler
     206             :  * is bound to an application when it is created. When it receives an
     207             :  * OnStopRequest it launches the application using the temp file it has
     208             :  * stored the data into.  We create a handler every time we have to process
     209             :  * data using a helper app.
     210             :  */
     211             : class nsExternalAppHandler final : public nsIStreamListener,
     212             :                                    public nsIHelperAppLauncher,
     213             :                                    public nsITimerCallback,
     214             :                                    public nsIBackgroundFileSaverObserver
     215             : {
     216             : public:
     217             :   NS_DECL_THREADSAFE_ISUPPORTS
     218             :   NS_DECL_NSISTREAMLISTENER
     219             :   NS_DECL_NSIREQUESTOBSERVER
     220             :   NS_DECL_NSIHELPERAPPLAUNCHER
     221             :   NS_DECL_NSICANCELABLE
     222             :   NS_DECL_NSITIMERCALLBACK
     223             :   NS_DECL_NSIBACKGROUNDFILESAVEROBSERVER
     224             : 
     225             :   /**
     226             :    * @param aMIMEInfo       MIMEInfo object, representing the type of the
     227             :    *                        content that should be handled
     228             :    * @param aFileExtension  The extension we need to append to our temp file,
     229             :    *                        INCLUDING the ".". e.g. .mp3
     230             :    * @param aContentContext dom Window context, as passed to DoContent.
     231             :    * @param aWindowContext  Top level window context used in dialog parenting,
     232             :    *                        as passed to DoContent. This parameter may be null,
     233             :    *                        in which case dialogs will be parented to
     234             :    *                        aContentContext.
     235             :    * @param mExtProtSvc     nsExternalHelperAppService on creation
     236             :    * @param aFileName       The filename to use
     237             :    * @param aReason         A constant from nsIHelperAppLauncherDialog indicating
     238             :    *                        why the request is handled by a helper app.
     239             :    */
     240             :   nsExternalAppHandler(nsIMIMEInfo * aMIMEInfo, const nsACString& aFileExtension,
     241             :                        nsIInterfaceRequestor * aContentContext,
     242             :                        nsIInterfaceRequestor * aWindowContext,
     243             :                        nsExternalHelperAppService * aExtProtSvc,
     244             :                        const nsAString& aFilename,
     245             :                        uint32_t aReason, bool aForceSave);
     246             : 
     247             :   /**
     248             :    * Clean up after the request was diverted to the parent process.
     249             :    */
     250             :   void DidDivertRequest(nsIRequest *request);
     251             : 
     252             :   /**
     253             :    * Apply content conversions if needed.
     254             :    */
     255             :   void MaybeApplyDecodingForExtension(nsIRequest *request);
     256             : 
     257             :   /**
     258             :    * Get the dialog parent. Public for ExternalHelperAppChild::OnStartRequest.
     259             :    */
     260           0 :   nsIInterfaceRequestor* GetDialogParent() {
     261           0 :     return mWindowContext ? mWindowContext : mContentContext;
     262             :   }
     263             : 
     264           0 :   void SetContentContext(nsIInterfaceRequestor* context) {
     265           0 :     MOZ_ASSERT(!mWindowContext);
     266           0 :     mContentContext = context;
     267           0 :   }
     268             : 
     269             : protected:
     270             :   ~nsExternalAppHandler();
     271             : 
     272             :   nsCOMPtr<nsIFile> mTempFile;
     273             :   nsCOMPtr<nsIURI> mSourceUrl;
     274             :   nsString mTempFileExtension;
     275             :   nsString mTempLeafName;
     276             : 
     277             :   /**
     278             :    * The MIME Info for this load. Will never be null.
     279             :    */
     280             :   nsCOMPtr<nsIMIMEInfo> mMimeInfo;
     281             : 
     282             :   /**
     283             :    * The dom window associated with this request to handle content.
     284             :    */
     285             :   nsCOMPtr<nsIInterfaceRequestor> mContentContext;
     286             : 
     287             :   /**
     288             :    * If set, the parent window helper app dialogs and file pickers
     289             :    * should use in parenting. If null, we use mContentContext.
     290             :    */
     291             :   nsCOMPtr<nsIInterfaceRequestor> mWindowContext;
     292             : 
     293             :   /**
     294             :    * Used to close the window on a timer, to avoid any exceptions that are
     295             :    * thrown if we try to close the window before it's fully loaded.
     296             :    */
     297             :   nsCOMPtr<nsPIDOMWindowOuter> mWindowToClose;
     298             :   nsCOMPtr<nsITimer> mTimer;
     299             : 
     300             :   /**
     301             :    * The following field is set if we were processing an http channel that had
     302             :    * a content disposition header which specified the SUGGESTED file name we
     303             :    * should present to the user in the save to disk dialog. 
     304             :    */
     305             :   nsString mSuggestedFileName;
     306             : 
     307             :   /**
     308             :    * If set, this handler should forcibly save the file to disk regardless of
     309             :    * MIME info settings or anything else, without ever popping up the 
     310             :    * unknown content type handling dialog.
     311             :    */
     312             :   bool mForceSave;
     313             :   
     314             :   /**
     315             :    * The canceled flag is set if the user canceled the launching of this
     316             :    * application before we finished saving the data to a temp file.
     317             :    */
     318             :   bool mCanceled;
     319             : 
     320             :   /**
     321             :    * This is set based on whether the channel indicates that a new window
     322             :    * was opened specifically for this download.  If so, then we
     323             :    * close it.
     324             :    */
     325             :   bool mShouldCloseWindow;
     326             : 
     327             :   /**
     328             :    * True if a stop request has been issued.
     329             :    */
     330             :   bool mStopRequestIssued; 
     331             : 
     332             :   bool mIsFileChannel;
     333             : 
     334             :   /**
     335             :    * One of the REASON_ constants from nsIHelperAppLauncherDialog. Indicates the
     336             :    * reason the dialog was shown (unknown content type, server requested it,
     337             :    * etc).
     338             :    */
     339             :   uint32_t mReason;
     340             : 
     341             :   /**
     342             :    * Track the executable-ness of the temporary file.
     343             :    */
     344             :   bool mTempFileIsExecutable;
     345             : 
     346             :   PRTime mTimeDownloadStarted;
     347             :   int64_t mContentLength;
     348             :   int64_t mProgress; /**< Number of bytes received (for sending progress notifications). */
     349             : 
     350             :   /**
     351             :    * When we are told to save the temp file to disk (in a more permament
     352             :    * location) before we are done writing the content to a temp file, then
     353             :    * we need to remember the final destination until we are ready to use it.
     354             :    */
     355             :   nsCOMPtr<nsIFile> mFinalFileDestination;
     356             : 
     357             :   uint32_t mBufferSize;
     358             : 
     359             :   /**
     360             :    * This object handles saving the data received from the network to a
     361             :    * temporary location first, and then move the file to its final location,
     362             :    * doing all the input/output on a background thread.
     363             :    */
     364             :   nsCOMPtr<nsIBackgroundFileSaver> mSaver;
     365             : 
     366             :   /**
     367             :    * Stores the SHA-256 hash associated with the file that we downloaded.
     368             :    */
     369             :   nsAutoCString mHash;
     370             :   /**
     371             :    * Stores the signature information of the downloaded file in an nsIArray of
     372             :    * nsIX509CertList of nsIX509Cert. If the file is unsigned this will be
     373             :    * empty.
     374             :    */
     375             :   nsCOMPtr<nsIArray> mSignatureInfo;
     376             :   /**
     377             :    * Stores the redirect information associated with the channel.
     378             :    */
     379             :   nsCOMPtr<nsIArray> mRedirects;
     380             :   /**
     381             :    * Creates the temporary file for the download and an output stream for it.
     382             :    * Upon successful return, both mTempFile and mSaver will be valid.
     383             :    */
     384             :   nsresult SetUpTempFile(nsIChannel * aChannel);
     385             :   /**
     386             :    * When we download a helper app, we are going to retarget all load
     387             :    * notifications into our own docloader and load group instead of
     388             :    * using the window which initiated the load....RetargetLoadNotifications
     389             :    * contains that information...
     390             :    */
     391             :   void RetargetLoadNotifications(nsIRequest *request);
     392             :   /**
     393             :    * Once the user tells us how they want to dispose of the content
     394             :    * create an nsITransfer so they know what's going on. If this fails, the
     395             :    * caller MUST call Cancel.
     396             :    */
     397             :   nsresult CreateTransfer();
     398             : 
     399             :   /**
     400             :    * If we fail to create the necessary temporary file to initiate a transfer
     401             :    * we will report the failure by creating a failed nsITransfer.
     402             :    */
     403             :   nsresult CreateFailedTransfer(bool aIsPrivateBrowsing);
     404             : 
     405             :   /*
     406             :    * The following two functions are part of the split of SaveToDisk
     407             :    * to make it async, and works as following:
     408             :    *
     409             :    *    SaveToDisk    ------->   RequestSaveDestination
     410             :    *                                     .
     411             :    *                                     .
     412             :    *                                     v
     413             :    *    ContinueSave  <-------   SaveDestinationAvailable
     414             :    */
     415             : 
     416             :   /**
     417             :    * This is called by SaveToDisk to decide what's the final
     418             :    * file destination chosen by the user or by auto-download settings.
     419             :    */
     420             :   void RequestSaveDestination(const nsString& aDefaultFile,
     421             :                               const nsString& aDefaultFileExt);
     422             : 
     423             :   /**
     424             :    * When SaveToDisk is called, it possibly delegates to RequestSaveDestination
     425             :    * to decide the file destination. ContinueSave must then be called when
     426             :    * the final destination is finally known.
     427             :    * @param  aFile  The file that was chosen as the final destination.
     428             :    *                Must not be null.
     429             :    */
     430             :   nsresult ContinueSave(nsIFile* aFile);
     431             : 
     432             :   /**
     433             :    * After we're done prompting the user for any information, if the original
     434             :    * channel had a refresh url associated with it (which might point to a
     435             :    * "thank you for downloading" kind of page, then process that....It is safe
     436             :    * to invoke this method multiple times. We'll clear mOriginalChannel after
     437             :    * it's called and this ensures we won't call it again....
     438             :    */
     439             :   void ProcessAnyRefreshTags();
     440             : 
     441             :   /**
     442             :    * Notify our nsITransfer object that we are done with the download.  This is
     443             :    * always called after the target file has been closed.
     444             :    *
     445             :    * @param aStatus
     446             :    *        NS_OK for success, or a failure code if the download failed.
     447             :    *        A partially downloaded file may still be available in this case.
     448             :    */
     449             :   void NotifyTransfer(nsresult aStatus);
     450             : 
     451             :   /**
     452             :    * Helper routine that searches a pref string for a given mime type
     453             :    */
     454             :   bool GetNeverAskFlagFromPref(const char * prefName, const char * aContentType);
     455             : 
     456             :   /**
     457             :    * Helper routine to ensure mSuggestedFileName is "correct";
     458             :    * this ensures that mTempFileExtension only contains an extension when it
     459             :    * is different from mSuggestedFileName's extension.
     460             :    */
     461             :   void EnsureSuggestedFileName();
     462             : 
     463             :   typedef enum { kReadError, kWriteError, kLaunchError } ErrorType;
     464             :   /**
     465             :    * Utility function to send proper error notification to web progress listener
     466             :    */
     467             :   void SendStatusChange(ErrorType type, nsresult aStatus, nsIRequest *aRequest, const nsString& path);
     468             : 
     469             :   /**
     470             :    * Closes the window context if it does not have a refresh header
     471             :    * and it never displayed content before the external helper app
     472             :    * service was invoked.
     473             :    */
     474             :   nsresult MaybeCloseWindow();
     475             : 
     476             :   /**
     477             :    * Set in nsHelperDlgApp.js. This is always null after the user has chosen an
     478             :    * action.
     479             :    */
     480             :   nsCOMPtr<nsIWebProgressListener2> mDialogProgressListener;
     481             :   /**
     482             :    * Set once the user has chosen an action. This is null after the download
     483             :    * has been canceled or completes.
     484             :    */
     485             :   nsCOMPtr<nsITransfer> mTransfer;
     486             : 
     487             :   nsCOMPtr<nsIChannel> mOriginalChannel; /**< in the case of a redirect, this will be the pre-redirect channel. */
     488             :   nsCOMPtr<nsIHelperAppLauncherDialog> mDialog;
     489             : 
     490             :   /**
     491             :    * Keep request alive in case when helper non-modal dialog shown.
     492             :    * Thus in OnStopRequest the mRequest will not be set to null (it will be set to null further).
     493             :    */
     494             :   bool mKeepRequestAlive;
     495             : 
     496             :   /**
     497             :    * The request that's being loaded. Initialized in OnStartRequest.
     498             :    * Nulled out in OnStopRequest or once we know what we're doing
     499             :    * with the data, whichever happens later.
     500             :    */
     501             :   nsCOMPtr<nsIRequest> mRequest;
     502             : 
     503             :   RefPtr<nsExternalHelperAppService> mExtProtSvc;
     504             : };
     505             : 
     506             : #endif // nsExternalHelperAppService_h__

Generated by: LCOV version 1.13