Merge mozilla-central and tracemonkey. (a=blockers)
[mozilla-central.git] / dom / base / nsMimeTypeArray.cpp
blobbbed90365da6f8ac0ab358f00b255ad27255651f
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
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
14 * License.
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.
23 * Contributor(s):
24 * Pierre Phaneuf <pp@ludusdesign.com>
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.
38 * ***** END LICENSE BLOCK ***** */
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 "nsDOMClassInfo.h"
47 #include "nsIMIMEService.h"
48 #include "nsIMIMEInfo.h"
49 #include "nsIFile.h"
52 nsMimeTypeArray::nsMimeTypeArray(nsIDOMNavigator* navigator)
53 : mNavigator(navigator),
54 mPluginMimeTypeCount(0),
55 mInited(PR_FALSE)
59 nsMimeTypeArray::~nsMimeTypeArray()
61 Clear();
65 DOMCI_DATA(MimeTypeArray, nsMimeTypeArray)
67 // QueryInterface implementation for nsMimeTypeArray
68 NS_INTERFACE_MAP_BEGIN(nsMimeTypeArray)
69 NS_INTERFACE_MAP_ENTRY(nsISupports)
70 NS_INTERFACE_MAP_ENTRY(nsIDOMMimeTypeArray)
71 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MimeTypeArray)
72 NS_INTERFACE_MAP_END
75 NS_IMPL_ADDREF(nsMimeTypeArray)
76 NS_IMPL_RELEASE(nsMimeTypeArray)
79 NS_IMETHODIMP
80 nsMimeTypeArray::GetLength(PRUint32* aLength)
82 if (!mInited) {
83 nsresult rv = GetMimeTypes();
84 if (rv != NS_OK)
85 return rv;
88 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.");
92 *aLength = mPluginMimeTypeCount;
93 return NS_OK;
96 nsIDOMMimeType*
97 nsMimeTypeArray::GetItemAt(PRUint32 aIndex, nsresult *aResult)
99 if (!mInited) {
100 *aResult = GetMimeTypes();
101 if (*aResult != NS_OK)
102 return nsnull;
105 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.");
109 if (aIndex >= mPluginMimeTypeCount) {
110 *aResult = NS_ERROR_FAILURE;
112 return nsnull;
115 *aResult = NS_OK;
117 return mMimeTypeArray[aIndex];
120 NS_IMETHODIMP
121 nsMimeTypeArray::Item(PRUint32 aIndex, nsIDOMMimeType** aReturn)
123 nsresult rv;
125 NS_IF_ADDREF(*aReturn = GetItemAt(aIndex, &rv));
127 return rv;
130 nsIDOMMimeType*
131 nsMimeTypeArray::GetNamedItem(const nsAString& aName, nsresult* aResult)
133 if (!mInited) {
134 *aResult = GetMimeTypes();
135 if (*aResult != NS_OK)
136 return nsnull;
139 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.");
143 *aResult = NS_OK;
145 nsAutoString type;
147 for (PRInt32 i = 0; i < mMimeTypeArray.Count(); i++) {
148 nsIDOMMimeType *mtype = mMimeTypeArray[i];
150 mtype->GetType(type);
152 if (type.Equals(aName)) {
153 return mtype;
157 // Now let's check with the MIME service.
158 nsCOMPtr<nsIMIMEService> mimeSrv = do_GetService("@mozilla.org/mime;1");
159 if (mimeSrv) {
160 nsCOMPtr<nsIMIMEInfo> mimeInfo;
161 mimeSrv->GetFromTypeAndExtension(NS_ConvertUTF16toUTF8(aName), EmptyCString(),
162 getter_AddRefs(mimeInfo));
163 if (mimeInfo) {
164 // Now we check whether we can really claim to support this type
165 nsHandlerInfoAction action = nsIHandlerInfo::saveToDisk;
166 mimeInfo->GetPreferredAction(&action);
167 if (action != nsIMIMEInfo::handleInternally) {
168 PRBool hasHelper = PR_FALSE;
169 mimeInfo->GetHasDefaultHandler(&hasHelper);
170 if (!hasHelper) {
171 nsCOMPtr<nsIHandlerApp> helper;
172 mimeInfo->GetPreferredApplicationHandler(getter_AddRefs(helper));
173 if (!helper) {
174 // mime info from the OS may not have a PreferredApplicationHandler
175 // so just check for an empty default description
176 nsAutoString defaultDescription;
177 mimeInfo->GetDefaultDescription(defaultDescription);
178 if (defaultDescription.IsEmpty()) {
179 // no support; just leave
180 return nsnull;
186 // If we got here, we support this type! Say so.
187 nsCOMPtr<nsIDOMMimeType> helper, entry;
188 if (!(helper = new nsHelperMimeType(aName)) ||
189 !(entry = new nsMimeType(nsnull, helper)) ||
190 !mMimeTypeArray.AppendObject(entry)) {
191 *aResult = NS_ERROR_OUT_OF_MEMORY;
193 return nsnull;
196 return entry;
200 return nsnull;
203 NS_IMETHODIMP
204 nsMimeTypeArray::NamedItem(const nsAString& aName, nsIDOMMimeType** aReturn)
206 nsresult rv;
208 NS_IF_ADDREF(*aReturn = GetNamedItem(aName, &rv));
210 return rv;
213 void nsMimeTypeArray::Clear()
215 mInited = PR_FALSE;
216 mMimeTypeArray.Clear();
217 mPluginMimeTypeCount = 0;
220 nsresult nsMimeTypeArray::Refresh()
222 Clear();
223 return GetMimeTypes();
226 nsresult nsMimeTypeArray::GetMimeTypes()
228 NS_PRECONDITION(!mInited && mPluginMimeTypeCount==0,
229 "already initialized");
231 if (!mNavigator) {
232 return NS_ERROR_NOT_AVAILABLE;
235 nsIDOMPluginArray* pluginArray = nsnull;
236 nsresult rv = mNavigator->GetPlugins(&pluginArray);
237 if (rv == NS_OK) {
238 // count up all possible MimeTypes, and collect them here. Later,
239 // we'll remove duplicates.
240 PRUint32 pluginMimeTypeCount = 0;
241 PRUint32 pluginCount = 0;
242 rv = pluginArray->GetLength(&pluginCount);
243 if (rv == NS_OK) {
244 PRUint32 i;
245 for (i = 0; i < pluginCount; i++) {
246 nsCOMPtr<nsIDOMPlugin> plugin;
247 if (NS_SUCCEEDED(pluginArray->Item(i, getter_AddRefs(plugin))) &&
248 plugin) {
249 PRUint32 mimeTypeCount = 0;
250 if (plugin->GetLength(&mimeTypeCount) == NS_OK)
251 pluginMimeTypeCount += mimeTypeCount;
254 // now we know how many there are, start gathering them.
255 if (!mMimeTypeArray.SetCapacity(pluginMimeTypeCount))
256 return NS_ERROR_OUT_OF_MEMORY;
258 mPluginMimeTypeCount = pluginMimeTypeCount;
259 mInited = PR_TRUE;
261 PRUint32 k;
262 for (k = 0; k < pluginCount; k++) {
263 nsCOMPtr<nsIDOMPlugin> plugin;
264 if (NS_SUCCEEDED(pluginArray->Item(k, getter_AddRefs(plugin))) &&
265 plugin) {
266 PRUint32 mimeTypeCount = 0;
267 if (plugin->GetLength(&mimeTypeCount) == NS_OK) {
268 nsCOMPtr<nsIDOMMimeType> item;
269 for (PRUint32 j = 0; j < mimeTypeCount; j++) {
270 plugin->Item(j, getter_AddRefs(item));
271 mMimeTypeArray.AppendObject(item);
277 NS_RELEASE(pluginArray);
279 return rv;
282 nsMimeType::nsMimeType(nsIDOMPlugin* aPlugin, nsIDOMMimeType* aMimeType)
284 mPlugin = aPlugin;
285 mMimeType = aMimeType;
288 nsMimeType::~nsMimeType()
293 DOMCI_DATA(MimeType, nsMimeType)
295 // QueryInterface implementation for nsMimeType
296 NS_INTERFACE_MAP_BEGIN(nsMimeType)
297 NS_INTERFACE_MAP_ENTRY(nsISupports)
298 NS_INTERFACE_MAP_ENTRY(nsIDOMMimeType)
299 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MimeType)
300 NS_INTERFACE_MAP_END
303 NS_IMPL_ADDREF(nsMimeType)
304 NS_IMPL_RELEASE(nsMimeType)
307 NS_IMETHODIMP
308 nsMimeType::GetDescription(nsAString& aDescription)
310 return mMimeType->GetDescription(aDescription);
313 NS_IMETHODIMP
314 nsMimeType::GetEnabledPlugin(nsIDOMPlugin** aEnabledPlugin)
316 nsAutoString type;
317 GetType(type);
319 *aEnabledPlugin = mPlugin;
321 NS_IF_ADDREF(*aEnabledPlugin);
323 return NS_OK;
326 NS_IMETHODIMP
327 nsMimeType::GetSuffixes(nsAString& aSuffixes)
329 return mMimeType->GetSuffixes(aSuffixes);
332 NS_IMETHODIMP
333 nsMimeType::GetType(nsAString& aType)
335 return mMimeType->GetType(aType);
338 // QueryInterface implementation for nsHelperMimeType
339 NS_IMPL_ISUPPORTS1(nsHelperMimeType, nsIDOMMimeType)
341 NS_IMETHODIMP
342 nsHelperMimeType::GetDescription(nsAString& aDescription)
344 aDescription.Truncate();
345 return NS_OK;
348 NS_IMETHODIMP
349 nsHelperMimeType::GetEnabledPlugin(nsIDOMPlugin** aEnabledPlugin)
351 *aEnabledPlugin = nsnull;
352 return NS_OK;
355 NS_IMETHODIMP
356 nsHelperMimeType::GetSuffixes(nsAString& aSuffixes)
358 aSuffixes.Truncate();
359 return NS_OK;
362 NS_IMETHODIMP
363 nsHelperMimeType::GetType(nsAString& aType)
365 aType = mType;
366 return NS_OK;