1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et: */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is mozilla.org code.
18 * The Initial Developer of the Original Code is
19 * Netscape Communications Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 1998
21 * the Initial Developer. All Rights Reserved.
25 * Alternatively, the contents of this file may be used under the terms of
26 * either of the GNU General Public License Version 2 or later (the "GPL"),
27 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 #include "nsMIMEInfoImpl.h"
40 #include "nsXPIDLString.h"
41 #include "nsReadableUtils.h"
42 #include "nsStringEnumerator.h"
43 #include "nsIProcess.h"
44 #include "nsILocalFile.h"
45 #include "nsIFileURL.h"
47 #include "nsNetUtil.h"
48 #include "nsIURILoader.h"
49 #include "nsCURILoader.h"
51 // nsISupports methods
52 NS_IMPL_THREADSAFE_ADDREF(nsMIMEInfoBase
)
53 NS_IMPL_THREADSAFE_RELEASE(nsMIMEInfoBase
)
55 NS_INTERFACE_MAP_BEGIN(nsMIMEInfoBase
)
56 NS_INTERFACE_MAP_ENTRY(nsIHandlerInfo
)
57 // This is only an nsIMIMEInfo if it's a MIME handler.
58 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIMIMEInfo
, mClass
== eMIMEInfo
)
59 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIHandlerInfo
)
60 NS_INTERFACE_MAP_END_THREADSAFE
62 // nsMIMEInfoImpl methods
64 // Constructors for a MIME handler.
65 nsMIMEInfoBase::nsMIMEInfoBase(const char *aMIMEType
) :
70 mPreferredAction(nsIMIMEInfo::saveToDisk
),
71 mAlwaysAskBeforeHandling(PR_TRUE
)
75 nsMIMEInfoBase::nsMIMEInfoBase(const nsACString
& aMIMEType
) :
80 mPreferredAction(nsIMIMEInfo::saveToDisk
),
81 mAlwaysAskBeforeHandling(PR_TRUE
)
85 // Constructor for a handler that lets the caller specify whether this is a
86 // MIME handler or a protocol handler. In the long run, these will be distinct
87 // classes (f.e. nsMIMEInfo and nsProtocolInfo), but for now we reuse this class
88 // for both and distinguish between the two kinds of handlers via the aClass
89 // argument to this method, which can be either eMIMEInfo or eProtocolInfo.
90 nsMIMEInfoBase::nsMIMEInfoBase(const nsACString
& aType
, HandlerClass aClass
) :
95 mPreferredAction(nsIMIMEInfo::saveToDisk
),
96 mAlwaysAskBeforeHandling(PR_TRUE
)
100 nsMIMEInfoBase::~nsMIMEInfoBase()
105 nsMIMEInfoBase::GetFileExtensions(nsIUTF8StringEnumerator
** aResult
)
107 return NS_NewUTF8StringEnumerator(aResult
, &mExtensions
, this);
111 nsMIMEInfoBase::ExtensionExists(const nsACString
& aExtension
, PRBool
*_retval
)
113 NS_ASSERTION(!aExtension
.IsEmpty(), "no extension");
114 PRBool found
= PR_FALSE
;
115 PRUint32 extCount
= mExtensions
.Count();
116 if (extCount
< 1) return NS_OK
;
118 for (PRUint8 i
=0; i
< extCount
; i
++) {
119 nsCString
* ext
= (nsCString
*)mExtensions
.CStringAt(i
);
120 if (ext
->Equals(aExtension
, nsCaseInsensitiveCStringComparator())) {
131 nsMIMEInfoBase::GetPrimaryExtension(nsACString
& _retval
)
133 PRUint32 extCount
= mExtensions
.Count();
134 if (extCount
< 1) return NS_ERROR_NOT_INITIALIZED
;
136 _retval
= *(mExtensions
.CStringAt(0));
141 nsMIMEInfoBase::SetPrimaryExtension(const nsACString
& aExtension
)
143 NS_ASSERTION(!aExtension
.IsEmpty(), "no extension");
144 PRUint32 extCount
= mExtensions
.Count();
146 PRBool found
= PR_FALSE
;
147 for (i
=0; i
< extCount
; i
++) {
148 nsCString
* ext
= (nsCString
*)mExtensions
.CStringAt(i
);
149 if (ext
->Equals(aExtension
, nsCaseInsensitiveCStringComparator())) {
155 mExtensions
.RemoveCStringAt(i
);
158 mExtensions
.InsertCStringAt(aExtension
, 0);
164 nsMIMEInfoBase::AppendExtension(const nsACString
& aExtension
)
166 mExtensions
.AppendCString(aExtension
);
171 nsMIMEInfoBase::GetType(nsACString
& aType
)
174 return NS_ERROR_NOT_INITIALIZED
;
181 nsMIMEInfoBase::GetMIMEType(nsACString
& aMIMEType
)
184 return NS_ERROR_NOT_INITIALIZED
;
191 nsMIMEInfoBase::GetDescription(nsAString
& aDescription
)
193 aDescription
= mDescription
;
198 nsMIMEInfoBase::SetDescription(const nsAString
& aDescription
)
200 mDescription
= aDescription
;
205 nsMIMEInfoBase::Equals(nsIMIMEInfo
*aMIMEInfo
, PRBool
*_retval
)
207 if (!aMIMEInfo
) return NS_ERROR_NULL_POINTER
;
210 nsresult rv
= aMIMEInfo
->GetMIMEType(type
);
211 if (NS_FAILED(rv
)) return rv
;
213 *_retval
= mType
.Equals(type
);
219 nsMIMEInfoBase::GetMacType(PRUint32
*aMacType
)
221 *aMacType
= mMacType
;
224 return NS_ERROR_NOT_INITIALIZED
;
230 nsMIMEInfoBase::SetMacType(PRUint32 aMacType
)
237 nsMIMEInfoBase::GetMacCreator(PRUint32
*aMacCreator
)
239 *aMacCreator
= mMacCreator
;
242 return NS_ERROR_NOT_INITIALIZED
;
248 nsMIMEInfoBase::SetMacCreator(PRUint32 aMacCreator
)
250 mMacCreator
= aMacCreator
;
255 nsMIMEInfoBase::SetFileExtensions(const nsACString
& aExtensions
)
258 nsCString
extList( aExtensions
);
260 PRInt32 breakLocation
= -1;
261 while ( (breakLocation
= extList
.FindChar(',') )!= -1)
263 mExtensions
.AppendCString(Substring(extList
.get(), extList
.get() + breakLocation
));
264 extList
.Cut(0, breakLocation
+1 );
266 if ( !extList
.IsEmpty() )
267 mExtensions
.AppendCString( extList
);
272 nsMIMEInfoBase::GetDefaultDescription(nsAString
& aDefaultDescription
)
274 aDefaultDescription
= mDefaultAppDescription
;
279 nsMIMEInfoBase::GetPreferredApplicationHandler(nsIHandlerApp
** aPreferredAppHandler
)
281 *aPreferredAppHandler
= mPreferredApplication
;
282 NS_IF_ADDREF(*aPreferredAppHandler
);
287 nsMIMEInfoBase::SetPreferredApplicationHandler(nsIHandlerApp
* aPreferredAppHandler
)
289 mPreferredApplication
= aPreferredAppHandler
;
294 nsMIMEInfoBase::GetPossibleApplicationHandlers(nsIMutableArray
** aPossibleAppHandlers
)
296 if (!mPossibleApplications
)
297 mPossibleApplications
= do_CreateInstance(NS_ARRAY_CONTRACTID
);
299 if (!mPossibleApplications
)
300 return NS_ERROR_OUT_OF_MEMORY
;
302 *aPossibleAppHandlers
= mPossibleApplications
;
303 NS_IF_ADDREF(*aPossibleAppHandlers
);
308 nsMIMEInfoBase::GetPreferredAction(nsHandlerInfoAction
* aPreferredAction
)
310 *aPreferredAction
= mPreferredAction
;
315 nsMIMEInfoBase::SetPreferredAction(nsHandlerInfoAction aPreferredAction
)
317 mPreferredAction
= aPreferredAction
;
322 nsMIMEInfoBase::GetAlwaysAskBeforeHandling(PRBool
* aAlwaysAsk
)
324 *aAlwaysAsk
= mAlwaysAskBeforeHandling
;
330 nsMIMEInfoBase::SetAlwaysAskBeforeHandling(PRBool aAlwaysAsk
)
332 mAlwaysAskBeforeHandling
= aAlwaysAsk
;
338 nsMIMEInfoBase::GetLocalFileFromURI(nsIURI
*aURI
, nsILocalFile
**aFile
)
342 nsCOMPtr
<nsIFileURL
> fileUrl
= do_QueryInterface(aURI
, &rv
);
343 if (NS_FAILED(rv
)) return rv
;
345 nsCOMPtr
<nsIFile
> file
;
346 rv
= fileUrl
->GetFile(getter_AddRefs(file
));
347 if (NS_FAILED(rv
)) return rv
;
349 return CallQueryInterface(file
, aFile
);
353 nsMIMEInfoBase::LaunchWithFile(nsIFile
* aFile
)
357 // it doesn't make any sense to call this on protocol handlers
358 NS_ASSERTION(mClass
== eMIMEInfo
,
359 "nsMIMEInfoBase should have mClass == eMIMEInfo");
361 if (mPreferredAction
== useSystemDefault
) {
362 return LaunchDefaultWithFile(aFile
);
365 if (mPreferredAction
== useHelperApp
) {
366 if (!mPreferredApplication
)
367 return NS_ERROR_FILE_NOT_FOUND
;
369 // at the moment, we only know how to hand files off to local handlers
370 nsCOMPtr
<nsILocalHandlerApp
> localHandler
=
371 do_QueryInterface(mPreferredApplication
, &rv
);
372 NS_ENSURE_SUCCESS(rv
, rv
);
374 nsCOMPtr
<nsIFile
> executable
;
375 rv
= localHandler
->GetExecutable(getter_AddRefs(executable
));
376 NS_ENSURE_SUCCESS(rv
, rv
);
379 aFile
->GetNativePath(path
);
380 return LaunchWithIProcess(executable
, path
);
383 return NS_ERROR_INVALID_ARG
;
387 nsMIMEInfoBase::LaunchWithURI(nsIURI
* aURI
,
388 nsIInterfaceRequestor
* aWindowContext
)
390 // for now, this is only being called with protocol handlers; that
391 // will change once we get to more general registerContentHandler
393 NS_ASSERTION(mClass
== eProtocolInfo
,
394 "nsMIMEInfoBase should be a protocol handler");
396 if (mPreferredAction
== useSystemDefault
) {
397 return LoadUriInternal(aURI
);
400 if (mPreferredAction
== useHelperApp
) {
401 if (!mPreferredApplication
)
402 return NS_ERROR_FILE_NOT_FOUND
;
404 return mPreferredApplication
->LaunchWithURI(aURI
, aWindowContext
);
407 return NS_ERROR_INVALID_ARG
;
411 nsMIMEInfoBase::CopyBasicDataTo(nsMIMEInfoBase
* aOther
)
413 aOther
->mType
= mType
;
414 aOther
->mDefaultAppDescription
= mDefaultAppDescription
;
415 aOther
->mExtensions
= mExtensions
;
417 aOther
->mMacType
= mMacType
;
418 aOther
->mMacCreator
= mMacCreator
;
423 nsMIMEInfoBase::LaunchWithIProcess(nsIFile
* aApp
, const nsCString
& aArg
)
425 NS_ASSERTION(aApp
, "Unexpected null pointer, fix caller");
428 nsCOMPtr
<nsIProcess
> process
= do_CreateInstance(NS_PROCESS_CONTRACTID
, &rv
);
432 if (NS_FAILED(rv
= process
->Init(aApp
)))
435 const char *string
= aArg
.get();
438 return process
->Run(PR_FALSE
, &string
, 1, &pid
);
441 // nsMIMEInfoImpl implementation
443 nsMIMEInfoImpl::GetDefaultDescription(nsAString
& aDefaultDescription
)
445 if (mDefaultAppDescription
.IsEmpty() && mDefaultApplication
) {
446 // Don't want to cache this, just in case someone resets the app
447 // without changing the description....
448 mDefaultApplication
->GetLeafName(aDefaultDescription
);
450 aDefaultDescription
= mDefaultAppDescription
;
457 nsMIMEInfoImpl::GetHasDefaultHandler(PRBool
* _retval
)
459 *_retval
= !mDefaultAppDescription
.IsEmpty();
460 if (mDefaultApplication
) {
462 *_retval
= NS_SUCCEEDED(mDefaultApplication
->Exists(&exists
)) && exists
;
468 nsMIMEInfoImpl::LaunchDefaultWithFile(nsIFile
* aFile
)
470 if (!mDefaultApplication
)
471 return NS_ERROR_FILE_NOT_FOUND
;
473 nsCAutoString nativePath
;
474 aFile
->GetNativePath(nativePath
);
476 return LaunchWithIProcess(mDefaultApplication
, nativePath
);
480 nsMIMEInfoBase::GetPossibleLocalHandlers(nsIArray
**_retval
)
482 return NS_ERROR_NOT_IMPLEMENTED
;