content/base/src/nsHostObjectProtocolHandler.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #include "nsHostObjectProtocolHandler.h"
michael@0 8 #include "nsHostObjectURI.h"
michael@0 9 #include "nsError.h"
michael@0 10 #include "nsClassHashtable.h"
michael@0 11 #include "nsNetUtil.h"
michael@0 12 #include "nsIPrincipal.h"
michael@0 13 #include "nsIDOMFile.h"
michael@0 14 #include "nsIDOMMediaStream.h"
michael@0 15 #include "mozilla/dom/MediaSource.h"
michael@0 16 #include "nsIMemoryReporter.h"
michael@0 17 #include "mozilla/Preferences.h"
michael@0 18
michael@0 19 // -----------------------------------------------------------------------
michael@0 20 // Hash table
michael@0 21 struct DataInfo
michael@0 22 {
michael@0 23 // mObject is expected to be an nsIDOMBlob, nsIDOMMediaStream, or MediaSource
michael@0 24 nsCOMPtr<nsISupports> mObject;
michael@0 25 nsCOMPtr<nsIPrincipal> mPrincipal;
michael@0 26 nsCString mStack;
michael@0 27 };
michael@0 28
michael@0 29 static nsClassHashtable<nsCStringHashKey, DataInfo>* gDataTable;
michael@0 30
michael@0 31 // Memory reporting for the hash table.
michael@0 32 namespace mozilla {
michael@0 33
michael@0 34 class HostObjectURLsReporter MOZ_FINAL : public nsIMemoryReporter
michael@0 35 {
michael@0 36 public:
michael@0 37 NS_DECL_ISUPPORTS
michael@0 38
michael@0 39 NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
michael@0 40 nsISupports* aData)
michael@0 41 {
michael@0 42 return MOZ_COLLECT_REPORT(
michael@0 43 "host-object-urls", KIND_OTHER, UNITS_COUNT,
michael@0 44 gDataTable ? gDataTable->Count() : 0,
michael@0 45 "The number of host objects stored for access via URLs "
michael@0 46 "(e.g. blobs passed to URL.createObjectURL).");
michael@0 47 }
michael@0 48 };
michael@0 49
michael@0 50 NS_IMPL_ISUPPORTS(HostObjectURLsReporter, nsIMemoryReporter)
michael@0 51
michael@0 52 class BlobURLsReporter MOZ_FINAL : public nsIMemoryReporter
michael@0 53 {
michael@0 54 public:
michael@0 55 NS_DECL_ISUPPORTS
michael@0 56
michael@0 57 NS_IMETHOD CollectReports(nsIHandleReportCallback* aCallback,
michael@0 58 nsISupports* aData)
michael@0 59 {
michael@0 60 EnumArg env;
michael@0 61 env.mCallback = aCallback;
michael@0 62 env.mData = aData;
michael@0 63
michael@0 64 if (gDataTable) {
michael@0 65 gDataTable->EnumerateRead(CountCallback, &env);
michael@0 66 gDataTable->EnumerateRead(ReportCallback, &env);
michael@0 67 }
michael@0 68 return NS_OK;
michael@0 69 }
michael@0 70
michael@0 71 // Initialize info->mStack to record JS stack info, if enabled.
michael@0 72 // The string generated here is used in ReportCallback, below.
michael@0 73 static void GetJSStackForBlob(DataInfo* aInfo)
michael@0 74 {
michael@0 75 nsCString& stack = aInfo->mStack;
michael@0 76 MOZ_ASSERT(stack.IsEmpty());
michael@0 77 const uint32_t maxFrames = Preferences::GetUint("memory.blob_report.stack_frames");
michael@0 78
michael@0 79 if (maxFrames == 0) {
michael@0 80 return;
michael@0 81 }
michael@0 82
michael@0 83 nsresult rv;
michael@0 84 nsIXPConnect* xpc = nsContentUtils::XPConnect();
michael@0 85 nsCOMPtr<nsIStackFrame> frame;
michael@0 86 rv = xpc->GetCurrentJSStack(getter_AddRefs(frame));
michael@0 87 NS_ENSURE_SUCCESS_VOID(rv);
michael@0 88
michael@0 89 nsAutoCString origin;
michael@0 90 nsCOMPtr<nsIURI> principalURI;
michael@0 91 if (NS_SUCCEEDED(aInfo->mPrincipal->GetURI(getter_AddRefs(principalURI)))
michael@0 92 && principalURI) {
michael@0 93 principalURI->GetPrePath(origin);
michael@0 94 }
michael@0 95
michael@0 96 for (uint32_t i = 0; i < maxFrames && frame; ++i) {
michael@0 97 nsString fileNameUTF16;
michael@0 98 int32_t lineNumber = 0;
michael@0 99
michael@0 100 frame->GetFilename(fileNameUTF16);
michael@0 101 frame->GetLineNumber(&lineNumber);
michael@0 102
michael@0 103 if (!fileNameUTF16.IsEmpty()) {
michael@0 104 NS_ConvertUTF16toUTF8 fileName(fileNameUTF16);
michael@0 105 stack += "js(";
michael@0 106 if (!origin.IsEmpty()) {
michael@0 107 // Make the file name root-relative for conciseness if possible.
michael@0 108 const char* originData;
michael@0 109 uint32_t originLen;
michael@0 110
michael@0 111 originLen = origin.GetData(&originData);
michael@0 112 // If fileName starts with origin + "/", cut up to that "/".
michael@0 113 if (fileName.Length() >= originLen + 1 &&
michael@0 114 memcmp(fileName.get(), originData, originLen) == 0 &&
michael@0 115 fileName[originLen] == '/') {
michael@0 116 fileName.Cut(0, originLen);
michael@0 117 }
michael@0 118 }
michael@0 119 fileName.ReplaceChar('/', '\\');
michael@0 120 stack += fileName;
michael@0 121 if (lineNumber > 0) {
michael@0 122 stack += ", line=";
michael@0 123 stack.AppendInt(lineNumber);
michael@0 124 }
michael@0 125 stack += ")/";
michael@0 126 }
michael@0 127
michael@0 128 rv = frame->GetCaller(getter_AddRefs(frame));
michael@0 129 NS_ENSURE_SUCCESS_VOID(rv);
michael@0 130 }
michael@0 131 }
michael@0 132
michael@0 133 private:
michael@0 134 struct EnumArg {
michael@0 135 nsIHandleReportCallback* mCallback;
michael@0 136 nsISupports* mData;
michael@0 137 nsDataHashtable<nsPtrHashKey<nsIDOMBlob>, uint32_t> mRefCounts;
michael@0 138 };
michael@0 139
michael@0 140 // Determine number of URLs per blob, to handle the case where it's > 1.
michael@0 141 static PLDHashOperator CountCallback(nsCStringHashKey::KeyType aKey,
michael@0 142 DataInfo* aInfo,
michael@0 143 void* aUserArg)
michael@0 144 {
michael@0 145 EnumArg* envp = static_cast<EnumArg*>(aUserArg);
michael@0 146 nsCOMPtr<nsIDOMBlob> blob;
michael@0 147
michael@0 148 blob = do_QueryInterface(aInfo->mObject);
michael@0 149 if (blob) {
michael@0 150 envp->mRefCounts.Put(blob, envp->mRefCounts.Get(blob) + 1);
michael@0 151 }
michael@0 152 return PL_DHASH_NEXT;
michael@0 153 }
michael@0 154
michael@0 155 static PLDHashOperator ReportCallback(nsCStringHashKey::KeyType aKey,
michael@0 156 DataInfo* aInfo,
michael@0 157 void* aUserArg)
michael@0 158 {
michael@0 159 EnumArg* envp = static_cast<EnumArg*>(aUserArg);
michael@0 160 nsCOMPtr<nsIDOMBlob> blob;
michael@0 161
michael@0 162 blob = do_QueryInterface(aInfo->mObject);
michael@0 163 if (blob) {
michael@0 164 NS_NAMED_LITERAL_CSTRING
michael@0 165 (desc, "A blob URL allocated with URL.createObjectURL; the referenced "
michael@0 166 "blob cannot be freed until all URLs for it have been explicitly "
michael@0 167 "invalidated with URL.revokeObjectURL.");
michael@0 168 nsAutoCString path, url, owner, specialDesc;
michael@0 169 nsCOMPtr<nsIURI> principalURI;
michael@0 170 uint64_t size = 0;
michael@0 171 uint32_t refCount = 1;
michael@0 172 DebugOnly<bool> blobWasCounted;
michael@0 173
michael@0 174 blobWasCounted = envp->mRefCounts.Get(blob, &refCount);
michael@0 175 MOZ_ASSERT(blobWasCounted);
michael@0 176 MOZ_ASSERT(refCount > 0);
michael@0 177
michael@0 178 bool isMemoryFile = blob->IsMemoryFile();
michael@0 179
michael@0 180 if (isMemoryFile) {
michael@0 181 if (NS_FAILED(blob->GetSize(&size))) {
michael@0 182 size = 0;
michael@0 183 }
michael@0 184 }
michael@0 185
michael@0 186 path = isMemoryFile ? "memory-blob-urls/" : "file-blob-urls/";
michael@0 187 if (NS_SUCCEEDED(aInfo->mPrincipal->GetURI(getter_AddRefs(principalURI))) &&
michael@0 188 principalURI != nullptr &&
michael@0 189 NS_SUCCEEDED(principalURI->GetSpec(owner)) &&
michael@0 190 !owner.IsEmpty()) {
michael@0 191 owner.ReplaceChar('/', '\\');
michael@0 192 path += "owner(";
michael@0 193 path += owner;
michael@0 194 path += ")";
michael@0 195 } else {
michael@0 196 path += "owner unknown";
michael@0 197 }
michael@0 198 path += "/";
michael@0 199 path += aInfo->mStack;
michael@0 200 url = aKey;
michael@0 201 url.ReplaceChar('/', '\\');
michael@0 202 path += url;
michael@0 203 if (refCount > 1) {
michael@0 204 nsAutoCString addrStr;
michael@0 205
michael@0 206 addrStr = "0x";
michael@0 207 addrStr.AppendInt((uint64_t)(nsIDOMBlob*)blob, 16);
michael@0 208
michael@0 209 path += " ";
michael@0 210 path.AppendInt(refCount);
michael@0 211 path += "@";
michael@0 212 path += addrStr;
michael@0 213
michael@0 214 specialDesc = desc;
michael@0 215 specialDesc += "\n\nNOTE: This blob (address ";
michael@0 216 specialDesc += addrStr;
michael@0 217 specialDesc += ") has ";
michael@0 218 specialDesc.AppendInt(refCount);
michael@0 219 specialDesc += " URLs.";
michael@0 220 if (isMemoryFile) {
michael@0 221 specialDesc += " Its size is divided ";
michael@0 222 specialDesc += refCount > 2 ? "among" : "between";
michael@0 223 specialDesc += " them in this report.";
michael@0 224 }
michael@0 225 }
michael@0 226
michael@0 227 const nsACString& descString = specialDesc.IsEmpty()
michael@0 228 ? static_cast<const nsACString&>(desc)
michael@0 229 : static_cast<const nsACString&>(specialDesc);
michael@0 230 if (isMemoryFile) {
michael@0 231 envp->mCallback->Callback(EmptyCString(),
michael@0 232 path,
michael@0 233 KIND_OTHER,
michael@0 234 UNITS_BYTES,
michael@0 235 size / refCount,
michael@0 236 descString,
michael@0 237 envp->mData);
michael@0 238 }
michael@0 239 else {
michael@0 240 envp->mCallback->Callback(EmptyCString(),
michael@0 241 path,
michael@0 242 KIND_OTHER,
michael@0 243 UNITS_COUNT,
michael@0 244 1,
michael@0 245 descString,
michael@0 246 envp->mData);
michael@0 247 }
michael@0 248 }
michael@0 249 return PL_DHASH_NEXT;
michael@0 250 }
michael@0 251 };
michael@0 252
michael@0 253 NS_IMPL_ISUPPORTS(BlobURLsReporter, nsIMemoryReporter)
michael@0 254
michael@0 255 }
michael@0 256
michael@0 257 void
michael@0 258 nsHostObjectProtocolHandler::Init(void)
michael@0 259 {
michael@0 260 static bool initialized = false;
michael@0 261
michael@0 262 if (!initialized) {
michael@0 263 initialized = true;
michael@0 264 RegisterStrongMemoryReporter(new mozilla::HostObjectURLsReporter());
michael@0 265 RegisterStrongMemoryReporter(new mozilla::BlobURLsReporter());
michael@0 266 }
michael@0 267 }
michael@0 268
michael@0 269 nsHostObjectProtocolHandler::nsHostObjectProtocolHandler()
michael@0 270 {
michael@0 271 Init();
michael@0 272 }
michael@0 273
michael@0 274 nsresult
michael@0 275 nsHostObjectProtocolHandler::AddDataEntry(const nsACString& aScheme,
michael@0 276 nsISupports* aObject,
michael@0 277 nsIPrincipal* aPrincipal,
michael@0 278 nsACString& aUri)
michael@0 279 {
michael@0 280 Init();
michael@0 281
michael@0 282 nsresult rv = GenerateURIString(aScheme, aUri);
michael@0 283 NS_ENSURE_SUCCESS(rv, rv);
michael@0 284
michael@0 285 if (!gDataTable) {
michael@0 286 gDataTable = new nsClassHashtable<nsCStringHashKey, DataInfo>;
michael@0 287 }
michael@0 288
michael@0 289 DataInfo* info = new DataInfo;
michael@0 290
michael@0 291 info->mObject = aObject;
michael@0 292 info->mPrincipal = aPrincipal;
michael@0 293 mozilla::BlobURLsReporter::GetJSStackForBlob(info);
michael@0 294
michael@0 295 gDataTable->Put(aUri, info);
michael@0 296 return NS_OK;
michael@0 297 }
michael@0 298
michael@0 299 void
michael@0 300 nsHostObjectProtocolHandler::RemoveDataEntry(const nsACString& aUri)
michael@0 301 {
michael@0 302 if (gDataTable) {
michael@0 303 nsCString uriIgnoringRef;
michael@0 304 int32_t hashPos = aUri.FindChar('#');
michael@0 305 if (hashPos < 0) {
michael@0 306 uriIgnoringRef = aUri;
michael@0 307 }
michael@0 308 else {
michael@0 309 uriIgnoringRef = StringHead(aUri, hashPos);
michael@0 310 }
michael@0 311 gDataTable->Remove(uriIgnoringRef);
michael@0 312 if (gDataTable->Count() == 0) {
michael@0 313 delete gDataTable;
michael@0 314 gDataTable = nullptr;
michael@0 315 }
michael@0 316 }
michael@0 317 }
michael@0 318
michael@0 319 nsresult
michael@0 320 nsHostObjectProtocolHandler::GenerateURIString(const nsACString &aScheme,
michael@0 321 nsACString& aUri)
michael@0 322 {
michael@0 323 nsresult rv;
michael@0 324 nsCOMPtr<nsIUUIDGenerator> uuidgen =
michael@0 325 do_GetService("@mozilla.org/uuid-generator;1", &rv);
michael@0 326 NS_ENSURE_SUCCESS(rv, rv);
michael@0 327
michael@0 328 nsID id;
michael@0 329 rv = uuidgen->GenerateUUIDInPlace(&id);
michael@0 330 NS_ENSURE_SUCCESS(rv, rv);
michael@0 331
michael@0 332 char chars[NSID_LENGTH];
michael@0 333 id.ToProvidedString(chars);
michael@0 334
michael@0 335 aUri += aScheme;
michael@0 336 aUri += NS_LITERAL_CSTRING(":");
michael@0 337 aUri += Substring(chars + 1, chars + NSID_LENGTH - 2);
michael@0 338
michael@0 339 return NS_OK;
michael@0 340 }
michael@0 341
michael@0 342 static DataInfo*
michael@0 343 GetDataInfo(const nsACString& aUri)
michael@0 344 {
michael@0 345 if (!gDataTable) {
michael@0 346 return nullptr;
michael@0 347 }
michael@0 348
michael@0 349 DataInfo* res;
michael@0 350 nsCString uriIgnoringRef;
michael@0 351 int32_t hashPos = aUri.FindChar('#');
michael@0 352 if (hashPos < 0) {
michael@0 353 uriIgnoringRef = aUri;
michael@0 354 }
michael@0 355 else {
michael@0 356 uriIgnoringRef = StringHead(aUri, hashPos);
michael@0 357 }
michael@0 358 gDataTable->Get(uriIgnoringRef, &res);
michael@0 359
michael@0 360 return res;
michael@0 361 }
michael@0 362
michael@0 363 nsIPrincipal*
michael@0 364 nsHostObjectProtocolHandler::GetDataEntryPrincipal(const nsACString& aUri)
michael@0 365 {
michael@0 366 if (!gDataTable) {
michael@0 367 return nullptr;
michael@0 368 }
michael@0 369
michael@0 370 DataInfo* res = GetDataInfo(aUri);
michael@0 371
michael@0 372 if (!res) {
michael@0 373 return nullptr;
michael@0 374 }
michael@0 375
michael@0 376 return res->mPrincipal;
michael@0 377 }
michael@0 378
michael@0 379 void
michael@0 380 nsHostObjectProtocolHandler::Traverse(const nsACString& aUri,
michael@0 381 nsCycleCollectionTraversalCallback& aCallback)
michael@0 382 {
michael@0 383 if (!gDataTable) {
michael@0 384 return;
michael@0 385 }
michael@0 386
michael@0 387 DataInfo* res;
michael@0 388 gDataTable->Get(aUri, &res);
michael@0 389 if (!res) {
michael@0 390 return;
michael@0 391 }
michael@0 392
michael@0 393 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCallback, "HostObjectProtocolHandler DataInfo.mObject");
michael@0 394 aCallback.NoteXPCOMChild(res->mObject);
michael@0 395 }
michael@0 396
michael@0 397 static nsISupports*
michael@0 398 GetDataObject(nsIURI* aURI)
michael@0 399 {
michael@0 400 nsCString spec;
michael@0 401 aURI->GetSpec(spec);
michael@0 402
michael@0 403 DataInfo* info = GetDataInfo(spec);
michael@0 404 return info ? info->mObject : nullptr;
michael@0 405 }
michael@0 406
michael@0 407 // -----------------------------------------------------------------------
michael@0 408 // Protocol handler
michael@0 409
michael@0 410 NS_IMPL_ISUPPORTS(nsHostObjectProtocolHandler, nsIProtocolHandler)
michael@0 411
michael@0 412 NS_IMETHODIMP
michael@0 413 nsHostObjectProtocolHandler::GetDefaultPort(int32_t *result)
michael@0 414 {
michael@0 415 *result = -1;
michael@0 416 return NS_OK;
michael@0 417 }
michael@0 418
michael@0 419 NS_IMETHODIMP
michael@0 420 nsHostObjectProtocolHandler::GetProtocolFlags(uint32_t *result)
michael@0 421 {
michael@0 422 *result = URI_NORELATIVE | URI_NOAUTH | URI_LOADABLE_BY_SUBSUMERS |
michael@0 423 URI_IS_LOCAL_RESOURCE | URI_NON_PERSISTABLE;
michael@0 424 return NS_OK;
michael@0 425 }
michael@0 426
michael@0 427 NS_IMETHODIMP
michael@0 428 nsHostObjectProtocolHandler::NewURI(const nsACString& aSpec,
michael@0 429 const char *aCharset,
michael@0 430 nsIURI *aBaseURI,
michael@0 431 nsIURI **aResult)
michael@0 432 {
michael@0 433 *aResult = nullptr;
michael@0 434 nsresult rv;
michael@0 435
michael@0 436 DataInfo* info = GetDataInfo(aSpec);
michael@0 437
michael@0 438 nsRefPtr<nsHostObjectURI> uri =
michael@0 439 new nsHostObjectURI(info ? info->mPrincipal.get() : nullptr);
michael@0 440
michael@0 441 rv = uri->SetSpec(aSpec);
michael@0 442 NS_ENSURE_SUCCESS(rv, rv);
michael@0 443
michael@0 444 NS_TryToSetImmutable(uri);
michael@0 445 uri.forget(aResult);
michael@0 446
michael@0 447 return NS_OK;
michael@0 448 }
michael@0 449
michael@0 450 NS_IMETHODIMP
michael@0 451 nsHostObjectProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
michael@0 452 {
michael@0 453 *result = nullptr;
michael@0 454
michael@0 455 nsCString spec;
michael@0 456 uri->GetSpec(spec);
michael@0 457
michael@0 458 DataInfo* info = GetDataInfo(spec);
michael@0 459
michael@0 460 if (!info) {
michael@0 461 return NS_ERROR_DOM_BAD_URI;
michael@0 462 }
michael@0 463 nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(info->mObject);
michael@0 464 if (!blob) {
michael@0 465 return NS_ERROR_DOM_BAD_URI;
michael@0 466 }
michael@0 467
michael@0 468 #ifdef DEBUG
michael@0 469 {
michael@0 470 nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(uri);
michael@0 471 nsCOMPtr<nsIPrincipal> principal;
michael@0 472 uriPrinc->GetPrincipal(getter_AddRefs(principal));
michael@0 473 NS_ASSERTION(info->mPrincipal == principal, "Wrong principal!");
michael@0 474 }
michael@0 475 #endif
michael@0 476
michael@0 477 nsCOMPtr<nsIInputStream> stream;
michael@0 478 nsresult rv = blob->GetInternalStream(getter_AddRefs(stream));
michael@0 479 NS_ENSURE_SUCCESS(rv, rv);
michael@0 480
michael@0 481 nsCOMPtr<nsIChannel> channel;
michael@0 482 rv = NS_NewInputStreamChannel(getter_AddRefs(channel),
michael@0 483 uri,
michael@0 484 stream);
michael@0 485 NS_ENSURE_SUCCESS(rv, rv);
michael@0 486
michael@0 487 nsCOMPtr<nsISupports> owner = do_QueryInterface(info->mPrincipal);
michael@0 488
michael@0 489 nsString type;
michael@0 490 rv = blob->GetType(type);
michael@0 491 NS_ENSURE_SUCCESS(rv, rv);
michael@0 492
michael@0 493 nsCOMPtr<nsIDOMFile> file = do_QueryInterface(info->mObject);
michael@0 494 if (file) {
michael@0 495 nsString filename;
michael@0 496 rv = file->GetName(filename);
michael@0 497 NS_ENSURE_SUCCESS(rv, rv);
michael@0 498 channel->SetContentDispositionFilename(filename);
michael@0 499 }
michael@0 500
michael@0 501 uint64_t size;
michael@0 502 rv = blob->GetSize(&size);
michael@0 503 NS_ENSURE_SUCCESS(rv, rv);
michael@0 504
michael@0 505 channel->SetOwner(owner);
michael@0 506 channel->SetOriginalURI(uri);
michael@0 507 channel->SetContentType(NS_ConvertUTF16toUTF8(type));
michael@0 508 channel->SetContentLength(size);
michael@0 509
michael@0 510 channel.forget(result);
michael@0 511
michael@0 512 return NS_OK;
michael@0 513 }
michael@0 514
michael@0 515 NS_IMETHODIMP
michael@0 516 nsHostObjectProtocolHandler::AllowPort(int32_t port, const char *scheme,
michael@0 517 bool *_retval)
michael@0 518 {
michael@0 519 // don't override anything.
michael@0 520 *_retval = false;
michael@0 521 return NS_OK;
michael@0 522 }
michael@0 523
michael@0 524 NS_IMETHODIMP
michael@0 525 nsBlobProtocolHandler::GetScheme(nsACString &result)
michael@0 526 {
michael@0 527 result.AssignLiteral(BLOBURI_SCHEME);
michael@0 528 return NS_OK;
michael@0 529 }
michael@0 530
michael@0 531 NS_IMETHODIMP
michael@0 532 nsMediaStreamProtocolHandler::GetScheme(nsACString &result)
michael@0 533 {
michael@0 534 result.AssignLiteral(MEDIASTREAMURI_SCHEME);
michael@0 535 return NS_OK;
michael@0 536 }
michael@0 537
michael@0 538 NS_IMETHODIMP
michael@0 539 nsMediaSourceProtocolHandler::GetScheme(nsACString &result)
michael@0 540 {
michael@0 541 result.AssignLiteral(MEDIASOURCEURI_SCHEME);
michael@0 542 return NS_OK;
michael@0 543 }
michael@0 544
michael@0 545 NS_IMETHODIMP
michael@0 546 nsFontTableProtocolHandler::GetScheme(nsACString &result)
michael@0 547 {
michael@0 548 result.AssignLiteral(FONTTABLEURI_SCHEME);
michael@0 549 return NS_OK;
michael@0 550 }
michael@0 551
michael@0 552 nsresult
michael@0 553 NS_GetStreamForBlobURI(nsIURI* aURI, nsIInputStream** aStream)
michael@0 554 {
michael@0 555 NS_ASSERTION(IsBlobURI(aURI), "Only call this with blob URIs");
michael@0 556
michael@0 557 *aStream = nullptr;
michael@0 558
michael@0 559 nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(GetDataObject(aURI));
michael@0 560 if (!blob) {
michael@0 561 return NS_ERROR_DOM_BAD_URI;
michael@0 562 }
michael@0 563
michael@0 564 return blob->GetInternalStream(aStream);
michael@0 565 }
michael@0 566
michael@0 567 nsresult
michael@0 568 NS_GetStreamForMediaStreamURI(nsIURI* aURI, nsIDOMMediaStream** aStream)
michael@0 569 {
michael@0 570 NS_ASSERTION(IsMediaStreamURI(aURI), "Only call this with mediastream URIs");
michael@0 571
michael@0 572 *aStream = nullptr;
michael@0 573
michael@0 574 nsCOMPtr<nsIDOMMediaStream> stream = do_QueryInterface(GetDataObject(aURI));
michael@0 575 if (!stream) {
michael@0 576 return NS_ERROR_DOM_BAD_URI;
michael@0 577 }
michael@0 578
michael@0 579 *aStream = stream;
michael@0 580 NS_ADDREF(*aStream);
michael@0 581 return NS_OK;
michael@0 582 }
michael@0 583
michael@0 584 NS_IMETHODIMP
michael@0 585 nsFontTableProtocolHandler::NewURI(const nsACString& aSpec,
michael@0 586 const char *aCharset,
michael@0 587 nsIURI *aBaseURI,
michael@0 588 nsIURI **aResult)
michael@0 589 {
michael@0 590 nsRefPtr<nsIURI> uri;
michael@0 591
michael@0 592 // Either you got here via a ref or a fonttable: uri
michael@0 593 if (aSpec.Length() && aSpec.CharAt(0) == '#') {
michael@0 594 nsresult rv = aBaseURI->CloneIgnoringRef(getter_AddRefs(uri));
michael@0 595 NS_ENSURE_SUCCESS(rv, rv);
michael@0 596
michael@0 597 uri->SetRef(aSpec);
michael@0 598 } else {
michael@0 599 // Relative URIs (other than #ref) are not meaningful within the
michael@0 600 // fonttable: scheme.
michael@0 601 // If aSpec is a relative URI -other- than a bare #ref,
michael@0 602 // this will leave uri empty, and we'll return a failure code below.
michael@0 603 uri = new nsSimpleURI();
michael@0 604 uri->SetSpec(aSpec);
michael@0 605 }
michael@0 606
michael@0 607 bool schemeIs;
michael@0 608 if (NS_FAILED(uri->SchemeIs(FONTTABLEURI_SCHEME, &schemeIs)) || !schemeIs) {
michael@0 609 NS_WARNING("Non-fonttable spec in nsFontTableProtocolHander");
michael@0 610 return NS_ERROR_NOT_AVAILABLE;
michael@0 611 }
michael@0 612
michael@0 613 uri.forget(aResult);
michael@0 614 return NS_OK;
michael@0 615 }
michael@0 616
michael@0 617 nsresult
michael@0 618 NS_GetSourceForMediaSourceURI(nsIURI* aURI, mozilla::dom::MediaSource** aSource)
michael@0 619 {
michael@0 620 NS_ASSERTION(IsMediaSourceURI(aURI), "Only call this with mediasource URIs");
michael@0 621
michael@0 622 *aSource = nullptr;
michael@0 623
michael@0 624 nsCOMPtr<mozilla::dom::MediaSource> source = do_QueryInterface(GetDataObject(aURI));
michael@0 625 if (!source) {
michael@0 626 return NS_ERROR_DOM_BAD_URI;
michael@0 627 }
michael@0 628
michael@0 629 source.forget(aSource);
michael@0 630 return NS_OK;
michael@0 631 }

mercurial