1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=4 sw=2 sts=2 et: */
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 #ifndef __nsmimeinfoimpl_h___
7 #define __nsmimeinfoimpl_h___
8 
9 #include "nsIMIMEInfo.h"
10 #include "nsAtom.h"
11 #include "nsString.h"
12 #include "nsTArray.h"
13 #include "nsIMutableArray.h"
14 #include "nsIFile.h"
15 #include "nsCOMPtr.h"
16 #include "nsIURI.h"
17 #include "nsIProcess.h"
18 #include "mozilla/dom/BrowsingContext.h"
19 
20 /**
21  * UTF8 moz-icon URI string for the default handler application's icon, if
22  * available.
23  */
24 #define PROPERTY_DEFAULT_APP_ICON_URL "defaultApplicationIconURL"
25 /**
26  * UTF8 moz-icon URI string for the user's preferred handler application's
27  * icon, if available.
28  */
29 #define PROPERTY_CUSTOM_APP_ICON_URL "customApplicationIconURL"
30 
31 /**
32  * Basic implementation of nsIMIMEInfo. Incomplete - it is meant to be
33  * subclassed, and GetHasDefaultHandler as well as LaunchDefaultWithFile need to
34  * be implemented.
35  */
36 class nsMIMEInfoBase : public nsIMIMEInfo {
37  public:
38   NS_DECL_THREADSAFE_ISUPPORTS
39 
40   // I'd use NS_DECL_NSIMIMEINFO, but I don't want GetHasDefaultHandler
41   NS_IMETHOD GetFileExtensions(nsIUTF8StringEnumerator** _retval) override;
42   NS_IMETHOD SetFileExtensions(const nsACString& aExtensions) override;
43   NS_IMETHOD ExtensionExists(const nsACString& aExtension,
44                              bool* _retval) override;
45   NS_IMETHOD AppendExtension(const nsACString& aExtension) override;
46   NS_IMETHOD GetPrimaryExtension(nsACString& aPrimaryExtension) override;
47   NS_IMETHOD SetPrimaryExtension(const nsACString& aPrimaryExtension) override;
48   NS_IMETHOD GetType(nsACString& aType) override;
49   NS_IMETHOD GetMIMEType(nsACString& aMIMEType) override;
50   NS_IMETHOD GetDescription(nsAString& aDescription) override;
51   NS_IMETHOD SetDescription(const nsAString& aDescription) override;
52   NS_IMETHOD Equals(nsIMIMEInfo* aMIMEInfo, bool* _retval) override;
53   NS_IMETHOD GetPreferredApplicationHandler(
54       nsIHandlerApp** aPreferredAppHandler) override;
55   NS_IMETHOD SetPreferredApplicationHandler(
56       nsIHandlerApp* aPreferredAppHandler) override;
57   NS_IMETHOD GetPossibleApplicationHandlers(
58       nsIMutableArray** aPossibleAppHandlers) override;
59   NS_IMETHOD GetDefaultDescription(nsAString& aDefaultDescription) override;
60   NS_IMETHOD LaunchWithFile(nsIFile* aFile) override;
61   NS_IMETHOD LaunchWithURI(
62       nsIURI* aURI, mozilla::dom::BrowsingContext* aBrowsingContext) override;
63   NS_IMETHOD GetPreferredAction(nsHandlerInfoAction* aPreferredAction) override;
64   NS_IMETHOD SetPreferredAction(nsHandlerInfoAction aPreferredAction) override;
65   NS_IMETHOD GetAlwaysAskBeforeHandling(
66       bool* aAlwaysAskBeforeHandling) override;
67   NS_IMETHOD SetAlwaysAskBeforeHandling(bool aAlwaysAskBeforeHandling) override;
68   NS_IMETHOD GetPossibleLocalHandlers(nsIArray** _retval) override;
69   NS_IMETHOD IsPdf(bool* isPdf);
70 
71   enum HandlerClass { eMIMEInfo, eProtocolInfo };
72 
73   // nsMIMEInfoBase methods
74   explicit nsMIMEInfoBase(const char* aMIMEType = "");
75   explicit nsMIMEInfoBase(const nsACString& aMIMEType);
76   nsMIMEInfoBase(const nsACString& aType, HandlerClass aClass);
77 
SetMIMEType(const nsACString & aMIMEType)78   void SetMIMEType(const nsACString& aMIMEType) { mSchemeOrType = aMIMEType; }
79 
SetDefaultDescription(const nsString & aDesc)80   void SetDefaultDescription(const nsString& aDesc) {
81     mDefaultAppDescription = aDesc;
82   }
83 
84   /**
85    * Copies basic data of this MIME Info Implementation to the given other
86    * MIME Info. The data consists of the MIME Type, the (default) description,
87    * the MacOS type and creator, and the extension list (this object's
88    * extension list will replace aOther's list, not append to it). This
89    * function also ensures that aOther's primary extension will be the same as
90    * the one of this object.
91    */
92   void CopyBasicDataTo(nsMIMEInfoBase* aOther);
93 
94   /**
95    * Return whether this MIMEInfo has any extensions
96    */
HasExtensions()97   bool HasExtensions() const { return mExtensions.Length() != 0; }
98 
99  protected:
100   virtual ~nsMIMEInfoBase();  // must be virtual, as the the base class's
101                               // Release should call the subclass's destructor
102 
103   /**
104    * Launch the default application for the given file.
105    * For even more control over the launching, override launchWithFile.
106    * Also see the comment about nsIMIMEInfo in general, above.
107    *
108    * @param aFile The file that should be opened
109    */
110   virtual nsresult LaunchDefaultWithFile(nsIFile* aFile) = 0;
111 
112   /**
113    * Loads the URI with the OS default app.
114    *
115    * @param aURI The URI to pass off to the OS.
116    */
117   virtual nsresult LoadUriInternal(nsIURI* aURI) = 0;
118 
119   static already_AddRefed<nsIProcess> InitProcess(nsIFile* aApp,
120                                                   nsresult* aResult);
121 
122   /**
123    * This method can be used to launch the file or URI with a single
124    * argument (typically either a file path or a URI spec).  This is
125    * meant as a helper method for implementations of
126    * LaunchWithURI/LaunchDefaultWithFile.
127    *
128    * @param aApp The application to launch (may not be null)
129    * @param aArg The argument to pass on the command line
130    */
131   static nsresult LaunchWithIProcess(nsIFile* aApp, const nsCString& aArg);
132   static nsresult LaunchWithIProcess(nsIFile* aApp, const nsString& aArg);
133   static nsresult LaunchWithIProcess(nsIFile* aApp, const int aArgc,
134                                      const char16_t** aArgv);
135 
136   /**
137    * Given a file: nsIURI, return the associated nsIFile
138    *
139    * @param  aURI      the file: URI in question
140    * @param  aFile     the associated nsIFile (out param)
141    */
142   static nsresult GetLocalFileFromURI(nsIURI* aURI, nsIFile** aFile);
143 
144   /**
145    * Internal helper to avoid adding duplicates.
146    */
147   void AddUniqueExtension(const nsACString& aExtension);
148 
149   // member variables
150   nsTArray<nsCString>
151       mExtensions;  ///< array of file extensions associated w/ this MIME obj
152   nsString mDescription;  ///< human readable description
153   nsCString mSchemeOrType;
154   HandlerClass mClass;
155   nsCOMPtr<nsIHandlerApp> mPreferredApplication;
156   nsCOMPtr<nsIMutableArray> mPossibleApplications;
157   nsHandlerInfoAction
158       mPreferredAction;  ///< preferred action to associate with this type
159   nsString mPreferredAppDescription;
160   nsString mDefaultAppDescription;
161   bool mAlwaysAskBeforeHandling;
162 };
163 
164 /**
165  * This is a complete implementation of nsIMIMEInfo, and contains all necessary
166  * methods. However, depending on your platform you may want to use a different
167  * way of launching applications. This class stores the default application in a
168  * member variable and provides a function for setting it. For local
169  * applications, launching is done using nsIProcess, native path of the file to
170  * open as first argument.
171  */
172 class nsMIMEInfoImpl : public nsMIMEInfoBase {
173  public:
174   explicit nsMIMEInfoImpl(const char* aMIMEType = "")
nsMIMEInfoBase(aMIMEType)175       : nsMIMEInfoBase(aMIMEType) {}
nsMIMEInfoImpl(const nsACString & aMIMEType)176   explicit nsMIMEInfoImpl(const nsACString& aMIMEType)
177       : nsMIMEInfoBase(aMIMEType) {}
nsMIMEInfoImpl(const nsACString & aType,HandlerClass aClass)178   nsMIMEInfoImpl(const nsACString& aType, HandlerClass aClass)
179       : nsMIMEInfoBase(aType, aClass) {}
~nsMIMEInfoImpl()180   virtual ~nsMIMEInfoImpl() {}
181 
182   // nsIMIMEInfo methods
183   NS_IMETHOD GetHasDefaultHandler(bool* _retval) override;
184   NS_IMETHOD GetDefaultDescription(nsAString& aDefaultDescription) override;
185   NS_IMETHOD IsCurrentAppOSDefault(bool* _retval) override;
186 
187   // additional methods
188   /**
189    * Sets the default application. Supposed to be only called by the OS Helper
190    * App Services; the default application is immutable after it is first set.
191    */
SetDefaultApplication(nsIFile * aApp)192   void SetDefaultApplication(nsIFile* aApp) {
193     if (!mDefaultApplication) mDefaultApplication = aApp;
194   }
195 
196  protected:
197   // nsMIMEInfoBase methods
198   /**
199    * The base class implementation is to use LaunchWithIProcess in combination
200    * with mDefaultApplication. Subclasses can override that behaviour.
201    */
202   virtual nsresult LaunchDefaultWithFile(nsIFile* aFile) override;
203 
204   /**
205    * Loads the URI with the OS default app.  This should be overridden by each
206    * OS's implementation.
207    */
208   virtual nsresult LoadUriInternal(nsIURI* aURI) override = 0;
209 
210   nsCOMPtr<nsIFile>
211       mDefaultApplication;  ///< default application associated with this type.
212 };
213 
214 #endif  //__nsmimeinfoimpl_h___
215