uriloader/exthandler/android/nsMIMEInfoAndroid.cpp

Thu, 15 Jan 2015 15:59:08 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:59:08 +0100
branch
TOR_BUG_9701
changeset 10
ac0c01689b40
permissions
-rw-r--r--

Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 /* -*- Mode: c++; c-basic-offset: 2; tab-width: 20; indent-tabs-mode: nil; -*-
michael@0 2 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5 #include "nsMIMEInfoAndroid.h"
michael@0 6 #include "AndroidBridge.h"
michael@0 7 #include "nsAndroidHandlerApp.h"
michael@0 8 #include "nsArrayUtils.h"
michael@0 9 #include "nsISupportsUtils.h"
michael@0 10 #include "nsStringEnumerator.h"
michael@0 11 #include "nsNetUtil.h"
michael@0 12
michael@0 13 using namespace mozilla::widget::android;
michael@0 14
michael@0 15 NS_IMPL_ISUPPORTS(nsMIMEInfoAndroid, nsIMIMEInfo, nsIHandlerInfo)
michael@0 16
michael@0 17 NS_IMETHODIMP
michael@0 18 nsMIMEInfoAndroid::LaunchDefaultWithFile(nsIFile* aFile)
michael@0 19 {
michael@0 20 return LaunchWithFile(aFile);
michael@0 21 }
michael@0 22
michael@0 23 NS_IMETHODIMP
michael@0 24 nsMIMEInfoAndroid::LoadUriInternal(nsIURI * aURI)
michael@0 25 {
michael@0 26 nsCString uriSpec;
michael@0 27 aURI->GetSpec(uriSpec);
michael@0 28
michael@0 29 nsCString uriScheme;
michael@0 30 aURI->GetScheme(uriScheme);
michael@0 31
michael@0 32 nsAutoString mimeType;
michael@0 33 if (mType.Equals(uriScheme) || mType.Equals(uriSpec)) {
michael@0 34 mimeType = EmptyString();
michael@0 35 } else {
michael@0 36 mimeType = NS_ConvertUTF8toUTF16(mType);
michael@0 37 }
michael@0 38
michael@0 39 if (GeckoAppShell::OpenUriExternal(NS_ConvertUTF8toUTF16(uriSpec), mimeType)) {
michael@0 40 return NS_OK;
michael@0 41 }
michael@0 42 return NS_ERROR_FAILURE;
michael@0 43 }
michael@0 44
michael@0 45 bool
michael@0 46 nsMIMEInfoAndroid::GetMimeInfoForMimeType(const nsACString& aMimeType,
michael@0 47 nsMIMEInfoAndroid** aMimeInfo)
michael@0 48 {
michael@0 49 nsRefPtr<nsMIMEInfoAndroid> info = new nsMIMEInfoAndroid(aMimeType);
michael@0 50 mozilla::AndroidBridge* bridge = mozilla::AndroidBridge::Bridge();
michael@0 51 // we don't have access to the bridge, so just assume we can handle
michael@0 52 // the mime type for now and let the system deal with it
michael@0 53 if (!bridge){
michael@0 54 info.forget(aMimeInfo);
michael@0 55 return false;
michael@0 56 }
michael@0 57
michael@0 58 nsIHandlerApp* systemDefault = nullptr;
michael@0 59
michael@0 60 if (!IsUTF8(aMimeType, true))
michael@0 61 return false;
michael@0 62
michael@0 63 NS_ConvertUTF8toUTF16 mimeType(aMimeType);
michael@0 64
michael@0 65 bridge->GetHandlersForMimeType(mimeType,
michael@0 66 info->mHandlerApps, &systemDefault);
michael@0 67
michael@0 68 if (systemDefault)
michael@0 69 info->mPrefApp = systemDefault;
michael@0 70
michael@0 71 nsAutoCString fileExt;
michael@0 72 bridge->GetExtensionFromMimeType(aMimeType, fileExt);
michael@0 73 info->SetPrimaryExtension(fileExt);
michael@0 74
michael@0 75 uint32_t len;
michael@0 76 info->mHandlerApps->GetLength(&len);
michael@0 77 if (len == 1) {
michael@0 78 info.forget(aMimeInfo);
michael@0 79 return false;
michael@0 80 }
michael@0 81
michael@0 82 info.forget(aMimeInfo);
michael@0 83 return true;
michael@0 84 }
michael@0 85
michael@0 86 bool
michael@0 87 nsMIMEInfoAndroid::GetMimeInfoForFileExt(const nsACString& aFileExt,
michael@0 88 nsMIMEInfoAndroid **aMimeInfo)
michael@0 89 {
michael@0 90 nsCString mimeType;
michael@0 91 if (mozilla::AndroidBridge::Bridge())
michael@0 92 mozilla::AndroidBridge::Bridge()->
michael@0 93 GetMimeTypeFromExtensions(aFileExt, mimeType);
michael@0 94
michael@0 95 // "*/*" means that the bridge didn't know.
michael@0 96 if (mimeType.Equals(nsDependentCString("*/*"), nsCaseInsensitiveCStringComparator()))
michael@0 97 return false;
michael@0 98
michael@0 99 bool found = GetMimeInfoForMimeType(mimeType, aMimeInfo);
michael@0 100 (*aMimeInfo)->SetPrimaryExtension(aFileExt);
michael@0 101 return found;
michael@0 102 }
michael@0 103
michael@0 104 /**
michael@0 105 * Returns MIME info for the aURL, which may contain the whole URL or only a protocol
michael@0 106 */
michael@0 107 nsresult
michael@0 108 nsMIMEInfoAndroid::GetMimeInfoForURL(const nsACString &aURL,
michael@0 109 bool *found,
michael@0 110 nsIHandlerInfo **info)
michael@0 111 {
michael@0 112 nsMIMEInfoAndroid *mimeinfo = new nsMIMEInfoAndroid(aURL);
michael@0 113 NS_ADDREF(*info = mimeinfo);
michael@0 114 *found = true;
michael@0 115
michael@0 116 mozilla::AndroidBridge* bridge = mozilla::AndroidBridge::Bridge();
michael@0 117 if (!bridge) {
michael@0 118 // we don't have access to the bridge, so just assume we can handle
michael@0 119 // the protocol for now and let the system deal with it
michael@0 120 return NS_OK;
michael@0 121 }
michael@0 122
michael@0 123 nsIHandlerApp* systemDefault = nullptr;
michael@0 124 bridge->GetHandlersForURL(NS_ConvertUTF8toUTF16(aURL),
michael@0 125 mimeinfo->mHandlerApps, &systemDefault);
michael@0 126
michael@0 127 if (systemDefault)
michael@0 128 mimeinfo->mPrefApp = systemDefault;
michael@0 129
michael@0 130
michael@0 131 nsAutoCString fileExt;
michael@0 132 nsAutoCString mimeType;
michael@0 133 mimeinfo->GetType(mimeType);
michael@0 134 bridge->GetExtensionFromMimeType(mimeType, fileExt);
michael@0 135 mimeinfo->SetPrimaryExtension(fileExt);
michael@0 136
michael@0 137 uint32_t len;
michael@0 138 mimeinfo->mHandlerApps->GetLength(&len);
michael@0 139 if (len == 1) {
michael@0 140 // Code that calls this requires an object regardless if the OS has
michael@0 141 // something for us, so we return the empty object.
michael@0 142 *found = false;
michael@0 143 return NS_OK;
michael@0 144 }
michael@0 145
michael@0 146 return NS_OK;
michael@0 147 }
michael@0 148
michael@0 149 NS_IMETHODIMP
michael@0 150 nsMIMEInfoAndroid::GetType(nsACString& aType)
michael@0 151 {
michael@0 152 aType.Assign(mType);
michael@0 153 return NS_OK;
michael@0 154 }
michael@0 155
michael@0 156 NS_IMETHODIMP
michael@0 157 nsMIMEInfoAndroid::GetDescription(nsAString& aDesc)
michael@0 158 {
michael@0 159 aDesc.Assign(mDescription);
michael@0 160 return NS_OK;
michael@0 161 }
michael@0 162
michael@0 163 NS_IMETHODIMP
michael@0 164 nsMIMEInfoAndroid::SetDescription(const nsAString& aDesc)
michael@0 165 {
michael@0 166 mDescription.Assign(aDesc);
michael@0 167 return NS_OK;
michael@0 168 }
michael@0 169
michael@0 170 NS_IMETHODIMP
michael@0 171 nsMIMEInfoAndroid::GetPreferredApplicationHandler(nsIHandlerApp** aApp)
michael@0 172 {
michael@0 173 *aApp = mPrefApp;
michael@0 174 NS_IF_ADDREF(*aApp);
michael@0 175 return NS_OK;
michael@0 176 }
michael@0 177
michael@0 178 NS_IMETHODIMP
michael@0 179 nsMIMEInfoAndroid::SetPreferredApplicationHandler(nsIHandlerApp* aApp)
michael@0 180 {
michael@0 181 mPrefApp = aApp;
michael@0 182 return NS_OK;
michael@0 183 }
michael@0 184
michael@0 185 NS_IMETHODIMP
michael@0 186 nsMIMEInfoAndroid::GetPossibleApplicationHandlers(nsIMutableArray **aHandlerApps)
michael@0 187 {
michael@0 188 if (!mHandlerApps)
michael@0 189 mHandlerApps = do_CreateInstance(NS_ARRAY_CONTRACTID);
michael@0 190
michael@0 191 if (!mHandlerApps)
michael@0 192 return NS_ERROR_OUT_OF_MEMORY;
michael@0 193
michael@0 194 *aHandlerApps = mHandlerApps;
michael@0 195 NS_IF_ADDREF(*aHandlerApps);
michael@0 196 return NS_OK;
michael@0 197 }
michael@0 198
michael@0 199 NS_IMETHODIMP
michael@0 200 nsMIMEInfoAndroid::GetHasDefaultHandler(bool* aHasDefault)
michael@0 201 {
michael@0 202 uint32_t len;
michael@0 203 *aHasDefault = false;
michael@0 204 if (!mHandlerApps)
michael@0 205 return NS_OK;
michael@0 206
michael@0 207 if (NS_FAILED(mHandlerApps->GetLength(&len)))
michael@0 208 return NS_OK;
michael@0 209
michael@0 210 if (len == 0)
michael@0 211 return NS_OK;
michael@0 212
michael@0 213 *aHasDefault = true;
michael@0 214 return NS_OK;
michael@0 215 }
michael@0 216
michael@0 217 NS_IMETHODIMP
michael@0 218 nsMIMEInfoAndroid::GetDefaultDescription(nsAString& aDesc)
michael@0 219 {
michael@0 220 aDesc.Assign(EmptyString());
michael@0 221 return NS_OK;
michael@0 222 }
michael@0 223
michael@0 224 NS_IMETHODIMP
michael@0 225 nsMIMEInfoAndroid::LaunchWithURI(nsIURI* aURI, nsIInterfaceRequestor* req)
michael@0 226 {
michael@0 227 return mPrefApp->LaunchWithURI(aURI, req);
michael@0 228 }
michael@0 229
michael@0 230 NS_IMETHODIMP
michael@0 231 nsMIMEInfoAndroid::GetPreferredAction(nsHandlerInfoAction* aPrefAction)
michael@0 232 {
michael@0 233 *aPrefAction = mPrefAction;
michael@0 234 return NS_OK;
michael@0 235 }
michael@0 236
michael@0 237 NS_IMETHODIMP
michael@0 238 nsMIMEInfoAndroid::SetPreferredAction(nsHandlerInfoAction aPrefAction)
michael@0 239 {
michael@0 240 mPrefAction = aPrefAction;
michael@0 241 return NS_OK;
michael@0 242 }
michael@0 243
michael@0 244 NS_IMETHODIMP
michael@0 245 nsMIMEInfoAndroid::GetAlwaysAskBeforeHandling(bool* aAlwaysAsk)
michael@0 246 {
michael@0 247 *aAlwaysAsk = mAlwaysAsk;
michael@0 248 return NS_OK;
michael@0 249 }
michael@0 250
michael@0 251 NS_IMETHODIMP
michael@0 252 nsMIMEInfoAndroid::SetAlwaysAskBeforeHandling(bool aAlwaysAsk)
michael@0 253 {
michael@0 254 mAlwaysAsk = aAlwaysAsk;
michael@0 255 return NS_OK;
michael@0 256 }
michael@0 257
michael@0 258 NS_IMETHODIMP
michael@0 259 nsMIMEInfoAndroid::GetFileExtensions(nsIUTF8StringEnumerator** aResult)
michael@0 260 {
michael@0 261 return NS_NewUTF8StringEnumerator(aResult, &mExtensions, this);
michael@0 262 }
michael@0 263
michael@0 264 NS_IMETHODIMP
michael@0 265 nsMIMEInfoAndroid::SetFileExtensions(const nsACString & aExtensions)
michael@0 266 {
michael@0 267 mExtensions.Clear();
michael@0 268 nsCString extList(aExtensions);
michael@0 269
michael@0 270 int32_t breakLocation = -1;
michael@0 271 while ( (breakLocation = extList.FindChar(',')) != -1)
michael@0 272 {
michael@0 273 mExtensions.AppendElement(Substring(extList.get(), extList.get() + breakLocation));
michael@0 274 extList.Cut(0, breakLocation + 1);
michael@0 275 }
michael@0 276 if (!extList.IsEmpty())
michael@0 277 mExtensions.AppendElement(extList);
michael@0 278 return NS_OK;
michael@0 279 }
michael@0 280
michael@0 281 NS_IMETHODIMP
michael@0 282 nsMIMEInfoAndroid::ExtensionExists(const nsACString & aExtension, bool *aRetVal)
michael@0 283 {
michael@0 284 NS_ASSERTION(!aExtension.IsEmpty(), "no extension");
michael@0 285
michael@0 286 nsCString mimeType;
michael@0 287 if (mozilla::AndroidBridge::Bridge()) {
michael@0 288 mozilla::AndroidBridge::Bridge()->
michael@0 289 GetMimeTypeFromExtensions(aExtension, mimeType);
michael@0 290 }
michael@0 291
michael@0 292 // "*/*" means the bridge didn't find anything (i.e., extension doesn't exist).
michael@0 293 *aRetVal = !mimeType.Equals(nsDependentCString("*/*"), nsCaseInsensitiveCStringComparator());
michael@0 294 return NS_OK;
michael@0 295 }
michael@0 296
michael@0 297 NS_IMETHODIMP
michael@0 298 nsMIMEInfoAndroid::AppendExtension(const nsACString & aExtension)
michael@0 299 {
michael@0 300 mExtensions.AppendElement(aExtension);
michael@0 301 return NS_OK;
michael@0 302 }
michael@0 303
michael@0 304 NS_IMETHODIMP
michael@0 305 nsMIMEInfoAndroid::GetPrimaryExtension(nsACString & aPrimaryExtension)
michael@0 306 {
michael@0 307 if (!mExtensions.Length())
michael@0 308 return NS_ERROR_NOT_INITIALIZED;
michael@0 309
michael@0 310 aPrimaryExtension = mExtensions[0];
michael@0 311 return NS_OK;
michael@0 312 }
michael@0 313
michael@0 314 NS_IMETHODIMP
michael@0 315 nsMIMEInfoAndroid::SetPrimaryExtension(const nsACString & aExtension)
michael@0 316 {
michael@0 317 uint32_t extCount = mExtensions.Length();
michael@0 318 uint8_t i;
michael@0 319 bool found = false;
michael@0 320 for (i=0; i < extCount; i++) {
michael@0 321 const nsCString& ext = mExtensions[i];
michael@0 322 if (ext.Equals(aExtension, nsCaseInsensitiveCStringComparator())) {
michael@0 323 found = true;
michael@0 324 break;
michael@0 325 }
michael@0 326 }
michael@0 327 if (found) {
michael@0 328 mExtensions.RemoveElementAt(i);
michael@0 329 }
michael@0 330
michael@0 331 mExtensions.InsertElementAt(0, aExtension);
michael@0 332
michael@0 333 return NS_OK;
michael@0 334 }
michael@0 335
michael@0 336 NS_IMETHODIMP
michael@0 337 nsMIMEInfoAndroid::GetMIMEType(nsACString & aMIMEType)
michael@0 338 {
michael@0 339 aMIMEType.Assign(mType);
michael@0 340 return NS_OK;
michael@0 341 }
michael@0 342
michael@0 343 NS_IMETHODIMP
michael@0 344 nsMIMEInfoAndroid::Equals(nsIMIMEInfo *aMIMEInfo, bool *aRetVal)
michael@0 345 {
michael@0 346 if (!aMIMEInfo) return NS_ERROR_NULL_POINTER;
michael@0 347
michael@0 348 nsAutoCString type;
michael@0 349 nsresult rv = aMIMEInfo->GetMIMEType(type);
michael@0 350 if (NS_FAILED(rv)) return rv;
michael@0 351
michael@0 352 *aRetVal = mType.Equals(type);
michael@0 353
michael@0 354 return NS_OK;
michael@0 355 }
michael@0 356
michael@0 357 NS_IMETHODIMP
michael@0 358 nsMIMEInfoAndroid::GetPossibleLocalHandlers(nsIArray * *aPossibleLocalHandlers)
michael@0 359 {
michael@0 360 return NS_ERROR_NOT_IMPLEMENTED;
michael@0 361 }
michael@0 362
michael@0 363 NS_IMETHODIMP
michael@0 364 nsMIMEInfoAndroid::LaunchWithFile(nsIFile *aFile)
michael@0 365 {
michael@0 366 nsCOMPtr<nsIURI> uri;
michael@0 367 NS_NewFileURI(getter_AddRefs(uri), aFile);
michael@0 368 return LoadUriInternal(uri);
michael@0 369 }
michael@0 370
michael@0 371 nsMIMEInfoAndroid::nsMIMEInfoAndroid(const nsACString& aMIMEType) :
michael@0 372 mType(aMIMEType), mAlwaysAsk(true),
michael@0 373 mPrefAction(nsIMIMEInfo::useHelperApp)
michael@0 374 {
michael@0 375 mPrefApp = new nsMIMEInfoAndroid::SystemChooser(this);
michael@0 376 nsresult rv;
michael@0 377 mHandlerApps = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
michael@0 378 mHandlerApps->AppendElement(mPrefApp, false);
michael@0 379 }
michael@0 380
michael@0 381 NS_IMPL_ISUPPORTS(nsMIMEInfoAndroid::SystemChooser, nsIHandlerApp)
michael@0 382
michael@0 383
michael@0 384 nsresult nsMIMEInfoAndroid::SystemChooser::GetName(nsAString & aName) {
michael@0 385 aName.Assign(NS_LITERAL_STRING("Android chooser"));
michael@0 386 return NS_OK;
michael@0 387 }
michael@0 388
michael@0 389 nsresult
michael@0 390 nsMIMEInfoAndroid::SystemChooser::SetName(const nsAString&) {
michael@0 391 return NS_OK;
michael@0 392 }
michael@0 393
michael@0 394 nsresult
michael@0 395 nsMIMEInfoAndroid::SystemChooser::GetDetailedDescription(nsAString & aDesc) {
michael@0 396 aDesc.Assign(NS_LITERAL_STRING("Android's default handler application chooser"));
michael@0 397 return NS_OK;
michael@0 398 }
michael@0 399
michael@0 400 nsresult
michael@0 401 nsMIMEInfoAndroid::SystemChooser::SetDetailedDescription(const nsAString&) {
michael@0 402 return NS_OK;
michael@0 403 }
michael@0 404
michael@0 405 nsresult
michael@0 406 nsMIMEInfoAndroid::SystemChooser::Equals(nsIHandlerApp *aHandlerApp, bool *aRetVal) {
michael@0 407 nsCOMPtr<nsMIMEInfoAndroid::SystemChooser> info = do_QueryInterface(aHandlerApp);
michael@0 408 if (info)
michael@0 409 return mOuter->Equals(info->mOuter, aRetVal);
michael@0 410 *aRetVal = false;
michael@0 411 return NS_OK;
michael@0 412 }
michael@0 413
michael@0 414 nsresult
michael@0 415 nsMIMEInfoAndroid::SystemChooser::LaunchWithURI(nsIURI* aURI, nsIInterfaceRequestor*)
michael@0 416 {
michael@0 417 return mOuter->LoadUriInternal(aURI);
michael@0 418 }

mercurial