uriloader/exthandler/nsExternalHelperAppService.h

Wed, 31 Dec 2014 07:53:36 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:53:36 +0100
branch
TOR_BUG_3246
changeset 5
4ab42b5ab56c
permissions
-rw-r--r--

Correct small whitespace inconsistency, lost while renaming variables.

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

mercurial