1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/uriloader/exthandler/android/nsMIMEInfoAndroid.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,418 @@ 1.4 +/* -*- Mode: c++; c-basic-offset: 2; tab-width: 20; indent-tabs-mode: nil; -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 +#include "nsMIMEInfoAndroid.h" 1.9 +#include "AndroidBridge.h" 1.10 +#include "nsAndroidHandlerApp.h" 1.11 +#include "nsArrayUtils.h" 1.12 +#include "nsISupportsUtils.h" 1.13 +#include "nsStringEnumerator.h" 1.14 +#include "nsNetUtil.h" 1.15 + 1.16 +using namespace mozilla::widget::android; 1.17 + 1.18 +NS_IMPL_ISUPPORTS(nsMIMEInfoAndroid, nsIMIMEInfo, nsIHandlerInfo) 1.19 + 1.20 +NS_IMETHODIMP 1.21 +nsMIMEInfoAndroid::LaunchDefaultWithFile(nsIFile* aFile) 1.22 +{ 1.23 + return LaunchWithFile(aFile); 1.24 +} 1.25 + 1.26 +NS_IMETHODIMP 1.27 +nsMIMEInfoAndroid::LoadUriInternal(nsIURI * aURI) 1.28 +{ 1.29 + nsCString uriSpec; 1.30 + aURI->GetSpec(uriSpec); 1.31 + 1.32 + nsCString uriScheme; 1.33 + aURI->GetScheme(uriScheme); 1.34 + 1.35 + nsAutoString mimeType; 1.36 + if (mType.Equals(uriScheme) || mType.Equals(uriSpec)) { 1.37 + mimeType = EmptyString(); 1.38 + } else { 1.39 + mimeType = NS_ConvertUTF8toUTF16(mType); 1.40 + } 1.41 + 1.42 + if (GeckoAppShell::OpenUriExternal(NS_ConvertUTF8toUTF16(uriSpec), mimeType)) { 1.43 + return NS_OK; 1.44 + } 1.45 + return NS_ERROR_FAILURE; 1.46 +} 1.47 + 1.48 +bool 1.49 +nsMIMEInfoAndroid::GetMimeInfoForMimeType(const nsACString& aMimeType, 1.50 + nsMIMEInfoAndroid** aMimeInfo) 1.51 +{ 1.52 + nsRefPtr<nsMIMEInfoAndroid> info = new nsMIMEInfoAndroid(aMimeType); 1.53 + mozilla::AndroidBridge* bridge = mozilla::AndroidBridge::Bridge(); 1.54 + // we don't have access to the bridge, so just assume we can handle 1.55 + // the mime type for now and let the system deal with it 1.56 + if (!bridge){ 1.57 + info.forget(aMimeInfo); 1.58 + return false; 1.59 + } 1.60 + 1.61 + nsIHandlerApp* systemDefault = nullptr; 1.62 + 1.63 + if (!IsUTF8(aMimeType, true)) 1.64 + return false; 1.65 + 1.66 + NS_ConvertUTF8toUTF16 mimeType(aMimeType); 1.67 + 1.68 + bridge->GetHandlersForMimeType(mimeType, 1.69 + info->mHandlerApps, &systemDefault); 1.70 + 1.71 + if (systemDefault) 1.72 + info->mPrefApp = systemDefault; 1.73 + 1.74 + nsAutoCString fileExt; 1.75 + bridge->GetExtensionFromMimeType(aMimeType, fileExt); 1.76 + info->SetPrimaryExtension(fileExt); 1.77 + 1.78 + uint32_t len; 1.79 + info->mHandlerApps->GetLength(&len); 1.80 + if (len == 1) { 1.81 + info.forget(aMimeInfo); 1.82 + return false; 1.83 + } 1.84 + 1.85 + info.forget(aMimeInfo); 1.86 + return true; 1.87 +} 1.88 + 1.89 +bool 1.90 +nsMIMEInfoAndroid::GetMimeInfoForFileExt(const nsACString& aFileExt, 1.91 + nsMIMEInfoAndroid **aMimeInfo) 1.92 +{ 1.93 + nsCString mimeType; 1.94 + if (mozilla::AndroidBridge::Bridge()) 1.95 + mozilla::AndroidBridge::Bridge()-> 1.96 + GetMimeTypeFromExtensions(aFileExt, mimeType); 1.97 + 1.98 + // "*/*" means that the bridge didn't know. 1.99 + if (mimeType.Equals(nsDependentCString("*/*"), nsCaseInsensitiveCStringComparator())) 1.100 + return false; 1.101 + 1.102 + bool found = GetMimeInfoForMimeType(mimeType, aMimeInfo); 1.103 + (*aMimeInfo)->SetPrimaryExtension(aFileExt); 1.104 + return found; 1.105 +} 1.106 + 1.107 +/** 1.108 + * Returns MIME info for the aURL, which may contain the whole URL or only a protocol 1.109 + */ 1.110 +nsresult 1.111 +nsMIMEInfoAndroid::GetMimeInfoForURL(const nsACString &aURL, 1.112 + bool *found, 1.113 + nsIHandlerInfo **info) 1.114 +{ 1.115 + nsMIMEInfoAndroid *mimeinfo = new nsMIMEInfoAndroid(aURL); 1.116 + NS_ADDREF(*info = mimeinfo); 1.117 + *found = true; 1.118 + 1.119 + mozilla::AndroidBridge* bridge = mozilla::AndroidBridge::Bridge(); 1.120 + if (!bridge) { 1.121 + // we don't have access to the bridge, so just assume we can handle 1.122 + // the protocol for now and let the system deal with it 1.123 + return NS_OK; 1.124 + } 1.125 + 1.126 + nsIHandlerApp* systemDefault = nullptr; 1.127 + bridge->GetHandlersForURL(NS_ConvertUTF8toUTF16(aURL), 1.128 + mimeinfo->mHandlerApps, &systemDefault); 1.129 + 1.130 + if (systemDefault) 1.131 + mimeinfo->mPrefApp = systemDefault; 1.132 + 1.133 + 1.134 + nsAutoCString fileExt; 1.135 + nsAutoCString mimeType; 1.136 + mimeinfo->GetType(mimeType); 1.137 + bridge->GetExtensionFromMimeType(mimeType, fileExt); 1.138 + mimeinfo->SetPrimaryExtension(fileExt); 1.139 + 1.140 + uint32_t len; 1.141 + mimeinfo->mHandlerApps->GetLength(&len); 1.142 + if (len == 1) { 1.143 + // Code that calls this requires an object regardless if the OS has 1.144 + // something for us, so we return the empty object. 1.145 + *found = false; 1.146 + return NS_OK; 1.147 + } 1.148 + 1.149 + return NS_OK; 1.150 +} 1.151 + 1.152 +NS_IMETHODIMP 1.153 +nsMIMEInfoAndroid::GetType(nsACString& aType) 1.154 +{ 1.155 + aType.Assign(mType); 1.156 + return NS_OK; 1.157 +} 1.158 + 1.159 +NS_IMETHODIMP 1.160 +nsMIMEInfoAndroid::GetDescription(nsAString& aDesc) 1.161 +{ 1.162 + aDesc.Assign(mDescription); 1.163 + return NS_OK; 1.164 +} 1.165 + 1.166 +NS_IMETHODIMP 1.167 +nsMIMEInfoAndroid::SetDescription(const nsAString& aDesc) 1.168 +{ 1.169 + mDescription.Assign(aDesc); 1.170 + return NS_OK; 1.171 +} 1.172 + 1.173 +NS_IMETHODIMP 1.174 +nsMIMEInfoAndroid::GetPreferredApplicationHandler(nsIHandlerApp** aApp) 1.175 +{ 1.176 + *aApp = mPrefApp; 1.177 + NS_IF_ADDREF(*aApp); 1.178 + return NS_OK; 1.179 +} 1.180 + 1.181 +NS_IMETHODIMP 1.182 +nsMIMEInfoAndroid::SetPreferredApplicationHandler(nsIHandlerApp* aApp) 1.183 +{ 1.184 + mPrefApp = aApp; 1.185 + return NS_OK; 1.186 +} 1.187 + 1.188 +NS_IMETHODIMP 1.189 +nsMIMEInfoAndroid::GetPossibleApplicationHandlers(nsIMutableArray **aHandlerApps) 1.190 +{ 1.191 + if (!mHandlerApps) 1.192 + mHandlerApps = do_CreateInstance(NS_ARRAY_CONTRACTID); 1.193 + 1.194 + if (!mHandlerApps) 1.195 + return NS_ERROR_OUT_OF_MEMORY; 1.196 + 1.197 + *aHandlerApps = mHandlerApps; 1.198 + NS_IF_ADDREF(*aHandlerApps); 1.199 + return NS_OK; 1.200 +} 1.201 + 1.202 +NS_IMETHODIMP 1.203 +nsMIMEInfoAndroid::GetHasDefaultHandler(bool* aHasDefault) 1.204 +{ 1.205 + uint32_t len; 1.206 + *aHasDefault = false; 1.207 + if (!mHandlerApps) 1.208 + return NS_OK; 1.209 + 1.210 + if (NS_FAILED(mHandlerApps->GetLength(&len))) 1.211 + return NS_OK; 1.212 + 1.213 + if (len == 0) 1.214 + return NS_OK; 1.215 + 1.216 + *aHasDefault = true; 1.217 + return NS_OK; 1.218 +} 1.219 + 1.220 +NS_IMETHODIMP 1.221 +nsMIMEInfoAndroid::GetDefaultDescription(nsAString& aDesc) 1.222 +{ 1.223 + aDesc.Assign(EmptyString()); 1.224 + return NS_OK; 1.225 +} 1.226 + 1.227 +NS_IMETHODIMP 1.228 +nsMIMEInfoAndroid::LaunchWithURI(nsIURI* aURI, nsIInterfaceRequestor* req) 1.229 +{ 1.230 + return mPrefApp->LaunchWithURI(aURI, req); 1.231 +} 1.232 + 1.233 +NS_IMETHODIMP 1.234 +nsMIMEInfoAndroid::GetPreferredAction(nsHandlerInfoAction* aPrefAction) 1.235 +{ 1.236 + *aPrefAction = mPrefAction; 1.237 + return NS_OK; 1.238 +} 1.239 + 1.240 +NS_IMETHODIMP 1.241 +nsMIMEInfoAndroid::SetPreferredAction(nsHandlerInfoAction aPrefAction) 1.242 +{ 1.243 + mPrefAction = aPrefAction; 1.244 + return NS_OK; 1.245 +} 1.246 + 1.247 +NS_IMETHODIMP 1.248 +nsMIMEInfoAndroid::GetAlwaysAskBeforeHandling(bool* aAlwaysAsk) 1.249 +{ 1.250 + *aAlwaysAsk = mAlwaysAsk; 1.251 + return NS_OK; 1.252 +} 1.253 + 1.254 +NS_IMETHODIMP 1.255 +nsMIMEInfoAndroid::SetAlwaysAskBeforeHandling(bool aAlwaysAsk) 1.256 +{ 1.257 + mAlwaysAsk = aAlwaysAsk; 1.258 + return NS_OK; 1.259 +} 1.260 + 1.261 +NS_IMETHODIMP 1.262 +nsMIMEInfoAndroid::GetFileExtensions(nsIUTF8StringEnumerator** aResult) 1.263 +{ 1.264 + return NS_NewUTF8StringEnumerator(aResult, &mExtensions, this); 1.265 +} 1.266 + 1.267 +NS_IMETHODIMP 1.268 +nsMIMEInfoAndroid::SetFileExtensions(const nsACString & aExtensions) 1.269 +{ 1.270 + mExtensions.Clear(); 1.271 + nsCString extList(aExtensions); 1.272 + 1.273 + int32_t breakLocation = -1; 1.274 + while ( (breakLocation = extList.FindChar(',')) != -1) 1.275 + { 1.276 + mExtensions.AppendElement(Substring(extList.get(), extList.get() + breakLocation)); 1.277 + extList.Cut(0, breakLocation + 1); 1.278 + } 1.279 + if (!extList.IsEmpty()) 1.280 + mExtensions.AppendElement(extList); 1.281 + return NS_OK; 1.282 +} 1.283 + 1.284 +NS_IMETHODIMP 1.285 +nsMIMEInfoAndroid::ExtensionExists(const nsACString & aExtension, bool *aRetVal) 1.286 +{ 1.287 + NS_ASSERTION(!aExtension.IsEmpty(), "no extension"); 1.288 + 1.289 + nsCString mimeType; 1.290 + if (mozilla::AndroidBridge::Bridge()) { 1.291 + mozilla::AndroidBridge::Bridge()-> 1.292 + GetMimeTypeFromExtensions(aExtension, mimeType); 1.293 + } 1.294 + 1.295 + // "*/*" means the bridge didn't find anything (i.e., extension doesn't exist). 1.296 + *aRetVal = !mimeType.Equals(nsDependentCString("*/*"), nsCaseInsensitiveCStringComparator()); 1.297 + return NS_OK; 1.298 +} 1.299 + 1.300 +NS_IMETHODIMP 1.301 +nsMIMEInfoAndroid::AppendExtension(const nsACString & aExtension) 1.302 +{ 1.303 + mExtensions.AppendElement(aExtension); 1.304 + return NS_OK; 1.305 +} 1.306 + 1.307 +NS_IMETHODIMP 1.308 +nsMIMEInfoAndroid::GetPrimaryExtension(nsACString & aPrimaryExtension) 1.309 +{ 1.310 + if (!mExtensions.Length()) 1.311 + return NS_ERROR_NOT_INITIALIZED; 1.312 + 1.313 + aPrimaryExtension = mExtensions[0]; 1.314 + return NS_OK; 1.315 +} 1.316 + 1.317 +NS_IMETHODIMP 1.318 +nsMIMEInfoAndroid::SetPrimaryExtension(const nsACString & aExtension) 1.319 +{ 1.320 + uint32_t extCount = mExtensions.Length(); 1.321 + uint8_t i; 1.322 + bool found = false; 1.323 + for (i=0; i < extCount; i++) { 1.324 + const nsCString& ext = mExtensions[i]; 1.325 + if (ext.Equals(aExtension, nsCaseInsensitiveCStringComparator())) { 1.326 + found = true; 1.327 + break; 1.328 + } 1.329 + } 1.330 + if (found) { 1.331 + mExtensions.RemoveElementAt(i); 1.332 + } 1.333 + 1.334 + mExtensions.InsertElementAt(0, aExtension); 1.335 + 1.336 + return NS_OK; 1.337 +} 1.338 + 1.339 +NS_IMETHODIMP 1.340 +nsMIMEInfoAndroid::GetMIMEType(nsACString & aMIMEType) 1.341 +{ 1.342 + aMIMEType.Assign(mType); 1.343 + return NS_OK; 1.344 +} 1.345 + 1.346 +NS_IMETHODIMP 1.347 +nsMIMEInfoAndroid::Equals(nsIMIMEInfo *aMIMEInfo, bool *aRetVal) 1.348 +{ 1.349 + if (!aMIMEInfo) return NS_ERROR_NULL_POINTER; 1.350 + 1.351 + nsAutoCString type; 1.352 + nsresult rv = aMIMEInfo->GetMIMEType(type); 1.353 + if (NS_FAILED(rv)) return rv; 1.354 + 1.355 + *aRetVal = mType.Equals(type); 1.356 + 1.357 + return NS_OK; 1.358 +} 1.359 + 1.360 +NS_IMETHODIMP 1.361 +nsMIMEInfoAndroid::GetPossibleLocalHandlers(nsIArray * *aPossibleLocalHandlers) 1.362 +{ 1.363 + return NS_ERROR_NOT_IMPLEMENTED; 1.364 +} 1.365 + 1.366 +NS_IMETHODIMP 1.367 +nsMIMEInfoAndroid::LaunchWithFile(nsIFile *aFile) 1.368 +{ 1.369 + nsCOMPtr<nsIURI> uri; 1.370 + NS_NewFileURI(getter_AddRefs(uri), aFile); 1.371 + return LoadUriInternal(uri); 1.372 +} 1.373 + 1.374 +nsMIMEInfoAndroid::nsMIMEInfoAndroid(const nsACString& aMIMEType) : 1.375 + mType(aMIMEType), mAlwaysAsk(true), 1.376 + mPrefAction(nsIMIMEInfo::useHelperApp) 1.377 +{ 1.378 + mPrefApp = new nsMIMEInfoAndroid::SystemChooser(this); 1.379 + nsresult rv; 1.380 + mHandlerApps = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv); 1.381 + mHandlerApps->AppendElement(mPrefApp, false); 1.382 +} 1.383 + 1.384 +NS_IMPL_ISUPPORTS(nsMIMEInfoAndroid::SystemChooser, nsIHandlerApp) 1.385 + 1.386 + 1.387 +nsresult nsMIMEInfoAndroid::SystemChooser::GetName(nsAString & aName) { 1.388 + aName.Assign(NS_LITERAL_STRING("Android chooser")); 1.389 + return NS_OK; 1.390 +} 1.391 + 1.392 +nsresult 1.393 +nsMIMEInfoAndroid::SystemChooser::SetName(const nsAString&) { 1.394 + return NS_OK; 1.395 +} 1.396 + 1.397 +nsresult 1.398 +nsMIMEInfoAndroid::SystemChooser::GetDetailedDescription(nsAString & aDesc) { 1.399 + aDesc.Assign(NS_LITERAL_STRING("Android's default handler application chooser")); 1.400 + return NS_OK; 1.401 +} 1.402 + 1.403 +nsresult 1.404 +nsMIMEInfoAndroid::SystemChooser::SetDetailedDescription(const nsAString&) { 1.405 + return NS_OK; 1.406 +} 1.407 + 1.408 +nsresult 1.409 +nsMIMEInfoAndroid::SystemChooser::Equals(nsIHandlerApp *aHandlerApp, bool *aRetVal) { 1.410 + nsCOMPtr<nsMIMEInfoAndroid::SystemChooser> info = do_QueryInterface(aHandlerApp); 1.411 + if (info) 1.412 + return mOuter->Equals(info->mOuter, aRetVal); 1.413 + *aRetVal = false; 1.414 + return NS_OK; 1.415 +} 1.416 + 1.417 +nsresult 1.418 +nsMIMEInfoAndroid::SystemChooser::LaunchWithURI(nsIURI* aURI, nsIInterfaceRequestor*) 1.419 +{ 1.420 + return mOuter->LoadUriInternal(aURI); 1.421 +}