diff -r 000000000000 -r 6474c204b198 dom/base/nsMimeTypeArray.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dom/base/nsMimeTypeArray.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,298 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 sw=2 et tw=79: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsMimeTypeArray.h" + +#include "mozilla/dom/MimeTypeArrayBinding.h" +#include "mozilla/dom/MimeTypeBinding.h" +#include "nsIDOMNavigator.h" +#include "nsPluginArray.h" +#include "nsIMIMEService.h" +#include "nsIMIMEInfo.h" +#include "Navigator.h" +#include "nsServiceManagerUtils.h" + +using namespace mozilla; +using namespace mozilla::dom; + +NS_IMPL_CYCLE_COLLECTING_ADDREF(nsMimeTypeArray) +NS_IMPL_CYCLE_COLLECTING_RELEASE(nsMimeTypeArray) +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsMimeTypeArray) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_3(nsMimeTypeArray, + mWindow, + mMimeTypes, + mHiddenMimeTypes) + +nsMimeTypeArray::nsMimeTypeArray(nsPIDOMWindow* aWindow) + : mWindow(aWindow) +{ + SetIsDOMBinding(); +} + +nsMimeTypeArray::~nsMimeTypeArray() +{ +} + +JSObject* +nsMimeTypeArray::WrapObject(JSContext* aCx) +{ + return MimeTypeArrayBinding::Wrap(aCx, this); +} + +void +nsMimeTypeArray::Refresh() +{ + mMimeTypes.Clear(); + mHiddenMimeTypes.Clear(); +} + +nsPIDOMWindow* +nsMimeTypeArray::GetParentObject() const +{ + MOZ_ASSERT(mWindow); + return mWindow; +} + +nsMimeType* +nsMimeTypeArray::Item(uint32_t aIndex) +{ + bool unused; + return IndexedGetter(aIndex, unused); +} + +nsMimeType* +nsMimeTypeArray::NamedItem(const nsAString& aName) +{ + bool unused; + return NamedGetter(aName, unused); +} + +nsMimeType* +nsMimeTypeArray::IndexedGetter(uint32_t aIndex, bool &aFound) +{ + aFound = false; + + EnsurePluginMimeTypes(); + + if (aIndex >= mMimeTypes.Length()) { + return nullptr; + } + + aFound = true; + + return mMimeTypes[aIndex]; +} + +static nsMimeType* +FindMimeType(const nsTArray >& aMimeTypes, + const nsAString& aType) +{ + for (uint32_t i = 0; i < aMimeTypes.Length(); ++i) { + nsMimeType* mimeType = aMimeTypes[i]; + if (aType.Equals(mimeType->Type())) { + return mimeType; + } + } + + return nullptr; +} + +nsMimeType* +nsMimeTypeArray::NamedGetter(const nsAString& aName, bool &aFound) +{ + aFound = false; + + EnsurePluginMimeTypes(); + + nsString lowerName(aName); + ToLowerCase(lowerName); + + nsMimeType* mimeType = FindMimeType(mMimeTypes, lowerName); + if (!mimeType) { + mimeType = FindMimeType(mHiddenMimeTypes, lowerName); + } + + if (mimeType) { + aFound = true; + return mimeType; + } + + // Now let's check with the MIME service. + nsCOMPtr mimeSrv = do_GetService("@mozilla.org/mime;1"); + if (!mimeSrv) { + return nullptr; + } + + nsCOMPtr mimeInfo; + mimeSrv->GetFromTypeAndExtension(NS_ConvertUTF16toUTF8(lowerName), + EmptyCString(), getter_AddRefs(mimeInfo)); + if (!mimeInfo) { + return nullptr; + } + + // Now we check whether we can really claim to support this type + nsHandlerInfoAction action = nsIHandlerInfo::saveToDisk; + mimeInfo->GetPreferredAction(&action); + if (action != nsIMIMEInfo::handleInternally) { + bool hasHelper = false; + mimeInfo->GetHasDefaultHandler(&hasHelper); + + if (!hasHelper) { + nsCOMPtr helper; + mimeInfo->GetPreferredApplicationHandler(getter_AddRefs(helper)); + + if (!helper) { + // mime info from the OS may not have a PreferredApplicationHandler + // so just check for an empty default description + nsAutoString defaultDescription; + mimeInfo->GetDefaultDescription(defaultDescription); + + if (defaultDescription.IsEmpty()) { + // no support; just leave + return nullptr; + } + } + } + } + + // If we got here, we support this type! Say so. + aFound = true; + + // We don't want navigator.mimeTypes enumeration to expose MIME types with + // application handlers, so add them to the list of hidden MIME types. + nsMimeType *mt = new nsMimeType(mWindow, lowerName); + mHiddenMimeTypes.AppendElement(mt); + + return mt; +} + +bool +nsMimeTypeArray::NameIsEnumerable(const nsAString& aName) +{ + return true; +} + +uint32_t +nsMimeTypeArray::Length() +{ + EnsurePluginMimeTypes(); + + return mMimeTypes.Length(); +} + +void +nsMimeTypeArray::GetSupportedNames(unsigned, nsTArray< nsString >& aRetval) +{ + EnsurePluginMimeTypes(); + + for (uint32_t i = 0; i < mMimeTypes.Length(); ++i) { + aRetval.AppendElement(mMimeTypes[i]->Type()); + } +} + +void +nsMimeTypeArray::EnsurePluginMimeTypes() +{ + if (!mMimeTypes.IsEmpty() || !mHiddenMimeTypes.IsEmpty() || !mWindow) { + return; + } + + nsCOMPtr navigator; + mWindow->GetNavigator(getter_AddRefs(navigator)); + + if (!navigator) { + return; + } + + ErrorResult rv; + nsPluginArray *pluginArray = + static_cast(navigator.get())->GetPlugins(rv); + if (!pluginArray) { + return; + } + + pluginArray->GetMimeTypes(mMimeTypes, mHiddenMimeTypes); +} + +NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsMimeType, AddRef) +NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsMimeType, Release) + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_2(nsMimeType, mWindow, mPluginElement) + +nsMimeType::nsMimeType(nsPIDOMWindow* aWindow, nsPluginElement* aPluginElement, + uint32_t aPluginTagMimeIndex, const nsAString& aType) + : mWindow(aWindow), + mPluginElement(aPluginElement), + mPluginTagMimeIndex(aPluginTagMimeIndex), + mType(aType) +{ + SetIsDOMBinding(); +} + +nsMimeType::nsMimeType(nsPIDOMWindow* aWindow, const nsAString& aType) + : mWindow(aWindow), + mPluginElement(nullptr), + mPluginTagMimeIndex(0), + mType(aType) +{ + SetIsDOMBinding(); +} + +nsMimeType::~nsMimeType() +{ +} + +nsPIDOMWindow* +nsMimeType::GetParentObject() const +{ + MOZ_ASSERT(mWindow); + return mWindow; +} + +JSObject* +nsMimeType::WrapObject(JSContext* aCx) +{ + return MimeTypeBinding::Wrap(aCx, this); +} + +void +nsMimeType::GetDescription(nsString& retval) const +{ + retval.Truncate(); + + if (mPluginElement) { + CopyUTF8toUTF16(mPluginElement->PluginTag()-> + mMimeDescriptions[mPluginTagMimeIndex], retval); + } +} + +nsPluginElement* +nsMimeType::GetEnabledPlugin() const +{ + return (mPluginElement && mPluginElement->PluginTag()->IsEnabled()) ? + mPluginElement : nullptr; +} + +void +nsMimeType::GetSuffixes(nsString& retval) const +{ + retval.Truncate(); + + if (mPluginElement) { + CopyUTF8toUTF16(mPluginElement->PluginTag()-> + mExtensions[mPluginTagMimeIndex], retval); + } +} + +void +nsMimeType::GetType(nsString& aRetval) const +{ + aRetval = mType; +}