1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is the Mozilla browser.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications, Inc.
19 * Portions created by the Initial Developer are Copyright (C) 1999
20 * the Initial Developer. All Rights Reserved.
23 * Scott MacGregor <mscott@netscape.com>
24 * Christian Biesinger <cbiesinger@web.de>
25 * Dan Mosedale <dmose@mozilla.org>
26 * Myk Melez <myk@mozilla.org>
27 * Ehsan Akhgari <ehsan.akhgari@gmail.com>
29 * Alternatively, the contents of this file may be used under the terms of
30 * either of the GNU General Public License Version 2 or later (the "GPL"),
31 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
32 * in which case the provisions of the GPL or the LGPL are applicable instead
33 * of those above. If you wish to allow use of your version of this file only
34 * under the terms of either the GPL or the LGPL, and not to allow others to
35 * use your version of this file under the terms of the MPL, indicate your
36 * decision by deleting the provisions above and replace them with the notice
37 * and other provisions required by the GPL or the LGPL. If you do not delete
38 * the provisions above, a recipient may use your version of this file under
39 * the terms of any one of the MPL, the GPL or the LGPL.
41 * ***** END LICENSE BLOCK ***** */
43 #ifndef nsExternalHelperAppService_h__
44 #define nsExternalHelperAppService_h__
54 #include "nsIExternalHelperAppService.h"
55 #include "nsIExternalProtocolService.h"
56 #include "nsIWebProgressListener2.h"
57 #include "nsIHelperAppLauncherDialog.h"
59 #include "nsIMIMEInfo.h"
60 #include "nsMIMEInfoImpl.h"
61 #include "nsIMIMEService.h"
62 #include "nsIStreamListener.h"
64 #include "nsIFileStreams.h"
65 #include "nsIOutputStream.h"
67 #include "nsIInterfaceRequestor.h"
68 #include "nsIInterfaceRequestorUtils.h"
69 #include "nsILocalFile.h"
70 #include "nsIChannel.h"
73 #include "nsIHandlerService.h"
75 #include "nsIObserver.h"
76 #include "nsCOMArray.h"
77 #include "nsWeakReference.h"
78 #include "nsIPrompt.h"
80 class nsExternalAppHandler
;
83 class nsIDOMWindowInternal
;
86 * The helper app service. Responsible for handling content that Mozilla
87 * itself can not handle
89 class nsExternalHelperAppService
90 : public nsIExternalHelperAppService
,
91 public nsPIExternalAppLauncher
,
92 public nsIExternalProtocolService
,
93 public nsIMIMEService
,
95 public nsSupportsWeakReference
99 NS_DECL_NSIEXTERNALHELPERAPPSERVICE
100 NS_DECL_NSPIEXTERNALAPPLAUNCHER
101 NS_DECL_NSIEXTERNALPROTOCOLSERVICE
102 NS_DECL_NSIMIMESERVICE
105 nsExternalHelperAppService();
106 virtual ~nsExternalHelperAppService();
109 * Initializes internal state. Will be called automatically when
110 * this service is first instantiated.
112 NS_HIDDEN_(nsresult
) Init();
115 * Given a mimetype and an extension, looks up a mime info from the OS.
116 * The mime type is given preference. This function follows the same rules
117 * as nsIMIMEService::GetFromTypeAndExtension.
118 * This is supposed to be overridden by the platform-specific
119 * nsOSHelperAppService!
120 * @param aFileExt The file extension; may be empty. UTF-8 encoded.
121 * @param [out] aFound
122 * Should be set to PR_TRUE if the os has a mapping, to
123 * PR_FALSE otherwise. Must not be null.
124 * @return A MIMEInfo. This function must return a MIMEInfo object if it
125 * can allocate one. The only justifiable reason for not
126 * returning one is an out-of-memory error.
127 * If null, the value of aFound is unspecified.
129 virtual already_AddRefed
<nsIMIMEInfo
> GetMIMEInfoFromOS(const nsACString
& aMIMEType
,
130 const nsACString
& aFileExt
,
131 PRBool
* aFound
) = 0;
134 * Given a string identifying an application, create an nsIFile representing
135 * it. This function should look in $PATH for the application.
136 * The base class implementation will first try to interpret platformAppPath
137 * as an absolute path, and if that fails it will look for a file next to the
138 * mozilla executable. Subclasses can override this method if they want a
139 * different behaviour.
140 * @param platformAppPath A platform specific path to an application that we
141 * got out of the rdf data source. This can be a mac
142 * file spec, a unix path or a windows path depending
144 * @param aFile [out] An nsIFile representation of that platform
147 virtual nsresult
GetFileTokenForPath(const PRUnichar
* platformAppPath
,
150 virtual NS_HIDDEN_(nsresult
) OSProtocolHandlerExists(const char *aScheme
,
151 PRBool
*aExists
) = 0;
154 * Simple accessor to let nsExternalAppHandler know if we are currently
155 * inside the private browsing mode.
157 PRBool
InPrivateBrowsing() const { return mInPrivateBrowsing
; }
161 * Searches the "extra" array of MIMEInfo objects for an object
162 * with a specific type. If found, it will modify the passed-in
163 * MIMEInfo. Otherwise, it will return an error and the MIMEInfo
165 * @param aContentType The type to search for.
166 * @param aMIMEInfo [inout] The mime info, if found
168 NS_HIDDEN_(nsresult
) FillMIMEInfoForMimeTypeFromExtras(
169 const nsACString
& aContentType
, nsIMIMEInfo
* aMIMEInfo
);
171 * Searches the "extra" array of MIMEInfo objects for an object
172 * with a specific extension.
174 * Does not change the MIME Type of the MIME Info.
176 * @see FillMIMEInfoForMimeTypeFromExtras
178 NS_HIDDEN_(nsresult
) FillMIMEInfoForExtensionFromExtras(
179 const nsACString
& aExtension
, nsIMIMEInfo
* aMIMEInfo
);
182 * Searches the "extra" array for a MIME type, and gets its extension.
183 * @param aExtension The extension to search for
184 * @param aMIMEType [out] The found MIME type.
185 * @return PR_TRUE if the extension was found, PR_FALSE otherwise.
187 NS_HIDDEN_(PRBool
) GetTypeFromExtras(const nsACString
& aExtension
,
188 nsACString
& aMIMEType
);
191 * Fixes the file permissions to be correct. Base class has a no-op
192 * implementation, subclasses can use this to correctly inherit ACLs from the
193 * parent directory, to make the permissions obey the umask, etc.
195 virtual void FixFilePermissions(nsILocalFile
* aFile
);
199 * NSPR Logging Module. Usage: set NSPR_LOG_MODULES=HelperAppService:level,
200 * where level should be 2 for errors, 3 for debug messages from the cross-
201 * platform nsExternalHelperAppService, and 4 for os-specific debug messages.
203 static PRLogModuleInfo
* mLog
;
206 // friend, so that it can access the nspr log module and FixFilePermissions
207 friend class nsExternalAppHandler
;
208 friend class nsExternalLoadRequest
;
211 * Helper function for ExpungeTemporaryFiles and ExpungeTemporaryPrivateFiles
213 static void ExpungeTemporaryFilesHelper(nsCOMArray
<nsILocalFile
> &fileList
);
215 * Functions related to the tempory file cleanup service provided by
216 * nsExternalHelperAppService
218 void ExpungeTemporaryFiles();
220 * Functions related to the tempory file cleanup service provided by
221 * nsExternalHelperAppService (for the temporary files added during
222 * the private browsing mode)
224 void ExpungeTemporaryPrivateFiles();
226 * Array for the files that should be deleted
228 nsCOMArray
<nsILocalFile
> mTemporaryFilesList
;
230 * Array for the files that should be deleted (for the temporary files
231 * added during the private browsing mode)
233 nsCOMArray
<nsILocalFile
> mTemporaryPrivateFilesList
;
235 * Whether we are in private browsing mode
237 PRBool mInPrivateBrowsing
;
241 * We need to read the data out of the incoming stream into a buffer which we
242 * can then use to write the data into the output stream representing the
245 #define DATA_BUFFER_SIZE (4096*2)
248 * An external app handler is just a small little class that presents itself as
249 * a nsIStreamListener. It saves the incoming data into a temp file. The handler
250 * is bound to an application when it is created. When it receives an
251 * OnStopRequest it launches the application using the temp file it has
252 * stored the data into. We create a handler every time we have to process
253 * data using a helper app.
255 class nsExternalAppHandler
: public nsIStreamListener
,
256 public nsIHelperAppLauncher
,
257 public nsITimerCallback
261 NS_DECL_NSISTREAMLISTENER
262 NS_DECL_NSIREQUESTOBSERVER
263 NS_DECL_NSIHELPERAPPLAUNCHER
264 NS_DECL_NSICANCELABLE
265 NS_DECL_NSITIMERCALLBACK
268 * @param aMIMEInfo MIMEInfo object, representing the type of the
269 * content that should be handled
270 * @param aFileExtension The extension we need to append to our temp file,
271 * INCLUDING the ".". e.g. .mp3
272 * @param aWindowContext Window context, as passed to DoContent
273 * @param aFileName The filename to use
274 * @param aReason A constant from nsIHelperAppLauncherDialog indicating
275 * why the request is handled by a helper app.
277 nsExternalAppHandler(nsIMIMEInfo
* aMIMEInfo
, const nsCSubstring
& aFileExtension
,
278 nsIInterfaceRequestor
* aWindowContext
,
279 const nsAString
& aFilename
,
280 PRUint32 aReason
, PRBool aForceSave
);
282 ~nsExternalAppHandler();
285 nsCOMPtr
<nsIFile
> mTempFile
;
286 nsCOMPtr
<nsIURI
> mSourceUrl
;
287 nsString mTempFileExtension
;
289 * The MIME Info for this load. Will never be null.
291 nsCOMPtr
<nsIMIMEInfo
> mMimeInfo
;
292 nsCOMPtr
<nsIOutputStream
> mOutStream
; /**< output stream to the temp file */
293 nsCOMPtr
<nsIInterfaceRequestor
> mWindowContext
;
296 * Used to close the window on a timer, to avoid any exceptions that are
297 * thrown if we try to close the window before it's fully loaded.
299 nsCOMPtr
<nsIDOMWindowInternal
> mWindowToClose
;
300 nsCOMPtr
<nsITimer
> mTimer
;
303 * The following field is set if we were processing an http channel that had
304 * a content disposition header which specified the SUGGESTED file name we
305 * should present to the user in the save to disk dialog.
307 nsString mSuggestedFileName
;
310 * If set, this handler should forcibly save the file to disk regardless of
311 * MIME info settings or anything else, without ever popping up the
312 * unknown content type handling dialog.
314 PRPackedBool mForceSave
;
317 * The canceled flag is set if the user canceled the launching of this
318 * application before we finished saving the data to a temp file.
320 PRPackedBool mCanceled
;
323 * This is set based on whether the channel indicates that a new window
324 * was opened specifically for this download. If so, then we
327 PRPackedBool mShouldCloseWindow
;
330 * have we received information from the user about how they want to
331 * dispose of this content
333 PRPackedBool mReceivedDispositionInfo
;
334 PRPackedBool mStopRequestIssued
;
335 PRPackedBool mProgressListenerInitialized
;
337 PRPackedBool mIsFileChannel
;
340 * One of the REASON_ constants from nsIHelperAppLauncherDialog. Indicates the
341 * reason the dialog was shown (unknown content type, server requested it,
347 * Track the executable-ness of the temporary file.
349 PRBool mTempFileIsExecutable
;
351 PRTime mTimeDownloadStarted
;
352 nsInt64 mContentLength
;
353 nsInt64 mProgress
; /**< Number of bytes received (for sending progress notifications). */
356 * When we are told to save the temp file to disk (in a more permament
357 * location) before we are done writing the content to a temp file, then
358 * we need to remember the final destination until we are ready to use it.
360 nsCOMPtr
<nsIFile
> mFinalFileDestination
;
362 char mDataBuffer
[DATA_BUFFER_SIZE
];
365 * Creates the temporary file for the download and an output stream for it.
366 * Upon successful return, both mTempFile and mOutStream will be valid.
368 nsresult
SetUpTempFile(nsIChannel
* aChannel
);
370 * When we download a helper app, we are going to retarget all load
371 * notifications into our own docloader and load group instead of
372 * using the window which initiated the load....RetargetLoadNotifications
373 * contains that information...
375 void RetargetLoadNotifications(nsIRequest
*request
);
377 * If the user tells us how they want to dispose of the content and
378 * we still haven't finished downloading while they were deciding,
379 * then create a progress listener of some kind so they know
382 nsresult
CreateProgressListener();
383 nsresult
PromptForSaveToFile(nsILocalFile
** aNewFile
,
384 const nsAFlatString
&aDefaultFile
,
385 const nsAFlatString
&aDefaultFileExt
);
388 * After we're done prompting the user for any information, if the original
389 * channel had a refresh url associated with it (which might point to a
390 * "thank you for downloading" kind of page, then process that....It is safe
391 * to invoke this method multiple times. We'll clear mOriginalChannel after
392 * it's called and this ensures we won't call it again....
394 void ProcessAnyRefreshTags();
397 * An internal method used to actually move the temp file to the final
398 * destination once we done receiving data AND have showed the progress dialog
400 nsresult
MoveFile(nsIFile
* aNewFileLocation
);
402 * An internal method used to actually launch a helper app given the temp file
403 * once we are done receiving data AND have showed the progress dialog.
404 * Uses the application specified in the mime info.
406 nsresult
OpenWithApplication();
409 * Helper routine which peaks at the mime action specified by mMimeInfo
410 * and calls either MoveFile or OpenWithApplication
412 nsresult
ExecuteDesiredAction();
414 * Helper routine that searches a pref string for a given mime type
416 PRBool
GetNeverAskFlagFromPref(const char * prefName
, const char * aContentType
);
419 * Initialize an nsITransfer object for use as a progress object
421 nsresult
InitializeDownload(nsITransfer
*);
424 * Helper routine to ensure mSuggestedFileName is "correct";
425 * this ensures that mTempFileExtension only contains an extension when it
426 * is different from mSuggestedFileName's extension.
428 void EnsureSuggestedFileName();
430 typedef enum { kReadError
, kWriteError
, kLaunchError
} ErrorType
;
432 * Utility function to send proper error notification to web progress listener
434 void SendStatusChange(ErrorType type
, nsresult aStatus
, nsIRequest
*aRequest
, const nsAFlatString
&path
);
437 * Closes the window context if it does not have a refresh header
438 * and it never displayed content before the external helper app
439 * service was invoked.
441 nsresult
MaybeCloseWindow();
443 nsCOMPtr
<nsIWebProgressListener2
> mWebProgressListener
;
444 nsCOMPtr
<nsIChannel
> mOriginalChannel
; /**< in the case of a redirect, this will be the pre-redirect channel. */
445 nsCOMPtr
<nsIHelperAppLauncherDialog
> mDialog
;
448 * The request that's being loaded. Not used after OnStopRequest, so a weak
449 * reference suffices. Initialized in OnStartRequest.
451 nsIRequest
* mRequest
;
454 extern NS_HIDDEN_(nsExternalHelperAppService
*) gExtProtSvc
;
456 #endif // nsExternalHelperAppService_h__