1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=2 sw=2 et tw=79: */
3 : /* ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
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/
10 : *
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
14 : * License.
15 : *
16 : * The Original Code is mozilla.org code.
17 : *
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.
22 : *
23 : * Contributor(s):
24 : * Pierre Phaneuf <pp@ludusdesign.com>
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either of the GNU General Public License Version 2 or later (the "GPL"),
28 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #include "nsMimeTypeArray.h"
41 : #include "nsContentUtils.h"
42 : #include "nsIScriptGlobalObject.h"
43 : #include "nsIDOMNavigator.h"
44 : #include "nsIDOMPluginArray.h"
45 : #include "nsIDOMPlugin.h"
46 : #include "nsDOMClassInfoID.h"
47 : #include "nsIMIMEService.h"
48 : #include "nsIMIMEInfo.h"
49 : #include "nsIFile.h"
50 :
51 :
52 0 : nsMimeTypeArray::nsMimeTypeArray(nsIDOMNavigator* navigator)
53 : : mNavigator(navigator),
54 : mPluginMimeTypeCount(0),
55 0 : mInited(false)
56 : {
57 0 : }
58 :
59 0 : nsMimeTypeArray::~nsMimeTypeArray()
60 : {
61 0 : Clear();
62 0 : }
63 :
64 :
65 : DOMCI_DATA(MimeTypeArray, nsMimeTypeArray)
66 :
67 : // QueryInterface implementation for nsMimeTypeArray
68 0 : NS_INTERFACE_MAP_BEGIN(nsMimeTypeArray)
69 0 : NS_INTERFACE_MAP_ENTRY(nsISupports)
70 0 : NS_INTERFACE_MAP_ENTRY(nsIDOMMimeTypeArray)
71 0 : NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MimeTypeArray)
72 0 : NS_INTERFACE_MAP_END
73 :
74 :
75 0 : NS_IMPL_ADDREF(nsMimeTypeArray)
76 0 : NS_IMPL_RELEASE(nsMimeTypeArray)
77 :
78 :
79 : NS_IMETHODIMP
80 0 : nsMimeTypeArray::GetLength(PRUint32* aLength)
81 : {
82 0 : if (!mInited) {
83 0 : nsresult rv = GetMimeTypes();
84 0 : if (rv != NS_OK)
85 0 : return rv;
86 : }
87 :
88 0 : NS_ASSERTION(mPluginMimeTypeCount <= (PRUint32)mMimeTypeArray.Count(),
89 : "The number of total mimetypes should be equal to or higher "
90 : "than the number of plugin mimetypes.");
91 :
92 0 : *aLength = mPluginMimeTypeCount;
93 0 : return NS_OK;
94 : }
95 :
96 : nsIDOMMimeType*
97 0 : nsMimeTypeArray::GetItemAt(PRUint32 aIndex, nsresult *aResult)
98 : {
99 0 : if (!mInited) {
100 0 : *aResult = GetMimeTypes();
101 0 : if (*aResult != NS_OK)
102 0 : return nsnull;
103 : }
104 :
105 0 : NS_ASSERTION(mPluginMimeTypeCount <= (PRUint32)mMimeTypeArray.Count(),
106 : "The number of total mimetypes should be equal to or higher "
107 : "than the number of plugin mimetypes.");
108 :
109 0 : if (aIndex >= mPluginMimeTypeCount) {
110 0 : *aResult = NS_ERROR_FAILURE;
111 :
112 0 : return nsnull;
113 : }
114 :
115 0 : *aResult = NS_OK;
116 :
117 0 : return mMimeTypeArray[aIndex];
118 : }
119 :
120 : NS_IMETHODIMP
121 0 : nsMimeTypeArray::Item(PRUint32 aIndex, nsIDOMMimeType** aReturn)
122 : {
123 : nsresult rv;
124 :
125 0 : NS_IF_ADDREF(*aReturn = GetItemAt(aIndex, &rv));
126 :
127 0 : return rv;
128 : }
129 :
130 : nsIDOMMimeType*
131 0 : nsMimeTypeArray::GetNamedItem(const nsAString& aName, nsresult* aResult)
132 : {
133 0 : if (!mInited) {
134 0 : *aResult = GetMimeTypes();
135 0 : if (*aResult != NS_OK)
136 0 : return nsnull;
137 : }
138 :
139 0 : NS_ASSERTION(mPluginMimeTypeCount <= (PRUint32)mMimeTypeArray.Count(),
140 : "The number of total mimetypes should be equal to or higher "
141 : "than the number of plugin mimetypes.");
142 :
143 0 : *aResult = NS_OK;
144 :
145 0 : nsAutoString type;
146 :
147 0 : for (PRInt32 i = 0; i < mMimeTypeArray.Count(); i++) {
148 0 : nsIDOMMimeType *mtype = mMimeTypeArray[i];
149 :
150 0 : mtype->GetType(type);
151 :
152 0 : if (type.Equals(aName)) {
153 0 : return mtype;
154 : }
155 : }
156 :
157 : // Now let's check with the MIME service.
158 0 : nsCOMPtr<nsIMIMEService> mimeSrv = do_GetService("@mozilla.org/mime;1");
159 0 : if (mimeSrv) {
160 0 : nsCOMPtr<nsIMIMEInfo> mimeInfo;
161 0 : mimeSrv->GetFromTypeAndExtension(NS_ConvertUTF16toUTF8(aName), EmptyCString(),
162 0 : getter_AddRefs(mimeInfo));
163 0 : if (mimeInfo) {
164 : // Now we check whether we can really claim to support this type
165 0 : nsHandlerInfoAction action = nsIHandlerInfo::saveToDisk;
166 0 : mimeInfo->GetPreferredAction(&action);
167 0 : if (action != nsIMIMEInfo::handleInternally) {
168 0 : bool hasHelper = false;
169 0 : mimeInfo->GetHasDefaultHandler(&hasHelper);
170 0 : if (!hasHelper) {
171 0 : nsCOMPtr<nsIHandlerApp> helper;
172 0 : mimeInfo->GetPreferredApplicationHandler(getter_AddRefs(helper));
173 0 : if (!helper) {
174 : // mime info from the OS may not have a PreferredApplicationHandler
175 : // so just check for an empty default description
176 0 : nsAutoString defaultDescription;
177 0 : mimeInfo->GetDefaultDescription(defaultDescription);
178 0 : if (defaultDescription.IsEmpty()) {
179 : // no support; just leave
180 0 : return nsnull;
181 : }
182 : }
183 : }
184 : }
185 :
186 : // If we got here, we support this type! Say so.
187 0 : nsCOMPtr<nsIDOMMimeType> helper, entry;
188 0 : if (!(helper = new nsHelperMimeType(aName)) ||
189 0 : !(entry = new nsMimeType(nsnull, helper)) ||
190 0 : !mMimeTypeArray.AppendObject(entry)) {
191 0 : *aResult = NS_ERROR_OUT_OF_MEMORY;
192 :
193 0 : return nsnull;
194 : }
195 :
196 0 : return entry;
197 : }
198 : }
199 :
200 0 : return nsnull;
201 : }
202 :
203 : NS_IMETHODIMP
204 0 : nsMimeTypeArray::NamedItem(const nsAString& aName, nsIDOMMimeType** aReturn)
205 : {
206 : nsresult rv;
207 :
208 0 : NS_IF_ADDREF(*aReturn = GetNamedItem(aName, &rv));
209 :
210 0 : return rv;
211 : }
212 :
213 : void
214 0 : nsMimeTypeArray::Clear()
215 : {
216 0 : mInited = false;
217 0 : mMimeTypeArray.Clear();
218 0 : mPluginMimeTypeCount = 0;
219 0 : }
220 :
221 : void
222 0 : nsMimeTypeArray::Refresh()
223 : {
224 0 : Clear();
225 0 : GetMimeTypes();
226 0 : }
227 :
228 : nsresult
229 0 : nsMimeTypeArray::GetMimeTypes()
230 : {
231 0 : NS_PRECONDITION(!mInited && mPluginMimeTypeCount==0,
232 : "already initialized");
233 :
234 0 : if (!mNavigator) {
235 0 : return NS_ERROR_NOT_AVAILABLE;
236 : }
237 :
238 0 : nsIDOMPluginArray* pluginArray = nsnull;
239 0 : nsresult rv = mNavigator->GetPlugins(&pluginArray);
240 0 : if (rv == NS_OK) {
241 : // count up all possible MimeTypes, and collect them here. Later,
242 : // we'll remove duplicates.
243 0 : PRUint32 pluginMimeTypeCount = 0;
244 0 : PRUint32 pluginCount = 0;
245 0 : rv = pluginArray->GetLength(&pluginCount);
246 0 : if (rv == NS_OK) {
247 : PRUint32 i;
248 0 : for (i = 0; i < pluginCount; i++) {
249 0 : nsCOMPtr<nsIDOMPlugin> plugin;
250 0 : if (NS_SUCCEEDED(pluginArray->Item(i, getter_AddRefs(plugin))) &&
251 0 : plugin) {
252 0 : PRUint32 mimeTypeCount = 0;
253 0 : if (plugin->GetLength(&mimeTypeCount) == NS_OK)
254 0 : pluginMimeTypeCount += mimeTypeCount;
255 : }
256 : }
257 : // now we know how many there are, start gathering them.
258 0 : if (!mMimeTypeArray.SetCapacity(pluginMimeTypeCount))
259 0 : return NS_ERROR_OUT_OF_MEMORY;
260 :
261 0 : mPluginMimeTypeCount = pluginMimeTypeCount;
262 0 : mInited = true;
263 :
264 : PRUint32 k;
265 0 : for (k = 0; k < pluginCount; k++) {
266 0 : nsCOMPtr<nsIDOMPlugin> plugin;
267 0 : if (NS_SUCCEEDED(pluginArray->Item(k, getter_AddRefs(plugin))) &&
268 0 : plugin) {
269 0 : PRUint32 mimeTypeCount = 0;
270 0 : if (plugin->GetLength(&mimeTypeCount) == NS_OK) {
271 0 : nsCOMPtr<nsIDOMMimeType> item;
272 0 : for (PRUint32 j = 0; j < mimeTypeCount; j++) {
273 0 : plugin->Item(j, getter_AddRefs(item));
274 0 : mMimeTypeArray.AppendObject(item);
275 : }
276 : }
277 : }
278 : }
279 : }
280 0 : NS_RELEASE(pluginArray);
281 : }
282 0 : return rv;
283 : }
284 :
285 0 : nsMimeType::nsMimeType(nsIDOMPlugin* aPlugin, nsIDOMMimeType* aMimeType)
286 : {
287 0 : mPlugin = aPlugin;
288 0 : mMimeType = aMimeType;
289 0 : }
290 :
291 0 : nsMimeType::~nsMimeType()
292 : {
293 0 : }
294 :
295 :
296 : DOMCI_DATA(MimeType, nsMimeType)
297 :
298 : // QueryInterface implementation for nsMimeType
299 0 : NS_INTERFACE_MAP_BEGIN(nsMimeType)
300 0 : NS_INTERFACE_MAP_ENTRY(nsISupports)
301 0 : NS_INTERFACE_MAP_ENTRY(nsIDOMMimeType)
302 0 : NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MimeType)
303 0 : NS_INTERFACE_MAP_END
304 :
305 :
306 0 : NS_IMPL_ADDREF(nsMimeType)
307 0 : NS_IMPL_RELEASE(nsMimeType)
308 :
309 :
310 : NS_IMETHODIMP
311 0 : nsMimeType::GetDescription(nsAString& aDescription)
312 : {
313 0 : return mMimeType->GetDescription(aDescription);
314 : }
315 :
316 : NS_IMETHODIMP
317 0 : nsMimeType::GetEnabledPlugin(nsIDOMPlugin** aEnabledPlugin)
318 : {
319 0 : nsAutoString type;
320 0 : GetType(type);
321 :
322 0 : *aEnabledPlugin = mPlugin;
323 :
324 0 : NS_IF_ADDREF(*aEnabledPlugin);
325 :
326 0 : return NS_OK;
327 : }
328 :
329 : NS_IMETHODIMP
330 0 : nsMimeType::GetSuffixes(nsAString& aSuffixes)
331 : {
332 0 : return mMimeType->GetSuffixes(aSuffixes);
333 : }
334 :
335 : NS_IMETHODIMP
336 0 : nsMimeType::GetType(nsAString& aType)
337 : {
338 0 : return mMimeType->GetType(aType);
339 : }
340 :
341 : // QueryInterface implementation for nsHelperMimeType
342 0 : NS_IMPL_ISUPPORTS1(nsHelperMimeType, nsIDOMMimeType)
343 :
344 : NS_IMETHODIMP
345 0 : nsHelperMimeType::GetDescription(nsAString& aDescription)
346 : {
347 0 : aDescription.Truncate();
348 0 : return NS_OK;
349 : }
350 :
351 : NS_IMETHODIMP
352 0 : nsHelperMimeType::GetEnabledPlugin(nsIDOMPlugin** aEnabledPlugin)
353 : {
354 0 : *aEnabledPlugin = nsnull;
355 0 : return NS_OK;
356 : }
357 :
358 : NS_IMETHODIMP
359 0 : nsHelperMimeType::GetSuffixes(nsAString& aSuffixes)
360 : {
361 0 : aSuffixes.Truncate();
362 0 : return NS_OK;
363 : }
364 :
365 : NS_IMETHODIMP
366 0 : nsHelperMimeType::GetType(nsAString& aType)
367 : {
368 0 : aType = mType;
369 0 : return NS_OK;
370 : }
371 :
|