ObliviousHttpChannel.cpp (26699B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set sw=2 ts=8 et tw=80 : */ 3 4 /* This Source Code Form is subject to the terms of the Mozilla Public 5 * License, v. 2.0. If a copy of the MPL was not distributed with this 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 7 8 // HttpLog.h should generally be included first 9 #include "HttpLog.h" 10 11 #include "ObliviousHttpChannel.h" 12 13 #include "BinaryHttpRequest.h" 14 #include "nsIHttpHeaderVisitor.h" 15 #include "nsStringStream.h" 16 17 namespace mozilla::net { 18 19 NS_IMPL_ISUPPORTS(ObliviousHttpChannel, nsIChannel, nsIHttpChannel, 20 nsIObliviousHttpChannel, nsIHttpChannelInternal, 21 nsIIdentChannel, nsIRequest, nsIRequestObserver, 22 nsIStreamListener, nsIUploadChannel2, nsITimedChannel) 23 24 ObliviousHttpChannel::ObliviousHttpChannel( 25 nsIURI* targetURI, const nsTArray<uint8_t>& encodedConfig, 26 nsIHttpChannel* innerChannel) 27 : mTargetURI(targetURI), 28 mEncodedConfig(encodedConfig.Clone()), 29 mInnerChannel(innerChannel), 30 mInnerChannelInternal(do_QueryInterface(innerChannel)), 31 mInnerChannelTimed(do_QueryInterface(innerChannel)) { 32 LOG(("ObliviousHttpChannel ctor [this=%p]", this)); 33 MOZ_ASSERT(mInnerChannel); 34 MOZ_ASSERT(mInnerChannelInternal); 35 MOZ_ASSERT(mInnerChannelTimed); 36 } 37 38 ObliviousHttpChannel::~ObliviousHttpChannel() { 39 LOG(("ObliviousHttpChannel dtor [this=%p]", this)); 40 } 41 42 //----------------------------------------------------------------------------- 43 // ObliviousHttpChannel::nsIHttpChannel 44 //----------------------------------------------------------------------------- 45 46 NS_IMETHODIMP 47 ObliviousHttpChannel::GetTopLevelContentWindowId(uint64_t* aWindowId) { 48 return mInnerChannel->GetTopLevelContentWindowId(aWindowId); 49 } 50 51 NS_IMETHODIMP 52 ObliviousHttpChannel::SetTopLevelContentWindowId(uint64_t aWindowId) { 53 return mInnerChannel->SetTopLevelContentWindowId(aWindowId); 54 } 55 56 NS_IMETHODIMP 57 ObliviousHttpChannel::GetBrowserId(uint64_t* aWindowId) { 58 return mInnerChannel->GetBrowserId(aWindowId); 59 } 60 61 NS_IMETHODIMP 62 ObliviousHttpChannel::SetBrowserId(uint64_t aId) { 63 return mInnerChannel->SetBrowserId(aId); 64 } 65 66 NS_IMETHODIMP 67 ObliviousHttpChannel::GetTransferSize(uint64_t* aTransferSize) { 68 return mInnerChannel->GetTransferSize(aTransferSize); 69 } 70 71 NS_IMETHODIMP 72 ObliviousHttpChannel::GetRequestSize(uint64_t* aRequestSize) { 73 return mInnerChannel->GetRequestSize(aRequestSize); 74 } 75 76 NS_IMETHODIMP 77 ObliviousHttpChannel::GetDecodedBodySize(uint64_t* aDecodedBodySize) { 78 return mInnerChannel->GetDecodedBodySize(aDecodedBodySize); 79 } 80 81 NS_IMETHODIMP 82 ObliviousHttpChannel::GetRequestMethod(nsACString& aRequestMethod) { 83 aRequestMethod.Assign(mMethod); 84 return NS_OK; 85 } 86 87 NS_IMETHODIMP 88 ObliviousHttpChannel::SetRequestMethod(const nsACString& aRequestMethod) { 89 mMethod.Assign(aRequestMethod); 90 return NS_OK; 91 } 92 93 NS_IMETHODIMP 94 ObliviousHttpChannel::GetReferrerInfo(nsIReferrerInfo** aReferrerInfo) { 95 return mInnerChannel->GetReferrerInfo(aReferrerInfo); 96 } 97 98 NS_IMETHODIMP 99 ObliviousHttpChannel::SetReferrerInfo(nsIReferrerInfo* aReferrerInfo) { 100 return mInnerChannel->SetReferrerInfo(aReferrerInfo); 101 } 102 103 NS_IMETHODIMP 104 ObliviousHttpChannel::SetReferrerInfoWithoutClone( 105 nsIReferrerInfo* aReferrerInfo) { 106 return mInnerChannel->SetReferrerInfoWithoutClone(aReferrerInfo); 107 } 108 109 NS_IMETHODIMP 110 ObliviousHttpChannel::GetRequestHeader(const nsACString& aHeader, 111 nsACString& _retval) { 112 _retval.Truncate(); 113 auto value = mHeaders.Lookup(aHeader); 114 if (!value) { 115 return NS_ERROR_NOT_AVAILABLE; 116 } 117 _retval.Assign(*value); 118 return NS_OK; 119 } 120 121 NS_IMETHODIMP 122 ObliviousHttpChannel::SetRequestHeader(const nsACString& aHeader, 123 const nsACString& aValue, bool aMerge) { 124 mHeaders.WithEntryHandle(aHeader, [&aValue, aMerge](auto&& entry) { 125 if (!entry) { 126 entry.Insert(aValue); 127 return; 128 } 129 if (!aMerge) { 130 entry.Update(aValue); 131 return; 132 } 133 nsAutoCString newValue(*entry); 134 newValue.AppendLiteral(", "); 135 newValue.Append(aValue); 136 entry.Update(newValue); 137 }); 138 return NS_OK; 139 } 140 141 NS_IMETHODIMP 142 ObliviousHttpChannel::SetNewReferrerInfo( 143 const nsACString& aUrl, nsIReferrerInfo::ReferrerPolicyIDL aPolicy, 144 bool aSendReferrer) { 145 return mInnerChannel->SetNewReferrerInfo(aUrl, aPolicy, aSendReferrer); 146 } 147 148 NS_IMETHODIMP 149 ObliviousHttpChannel::SetEmptyRequestHeader(const nsACString& aHeader) { 150 return SetRequestHeader(aHeader, EmptyCString(), false); 151 } 152 153 NS_IMETHODIMP 154 ObliviousHttpChannel::VisitRequestHeaders(nsIHttpHeaderVisitor* aVisitor) { 155 for (auto iter = mHeaders.ConstIter(); !iter.Done(); iter.Next()) { 156 nsresult rv = aVisitor->VisitHeader(iter.Key(), iter.Data()); 157 if (NS_FAILED(rv)) { 158 return rv; 159 } 160 } 161 return NS_OK; 162 } 163 164 NS_IMETHODIMP 165 ObliviousHttpChannel::VisitNonDefaultRequestHeaders( 166 nsIHttpHeaderVisitor* aVisitor) { 167 return mInnerChannel->VisitNonDefaultRequestHeaders(aVisitor); 168 } 169 170 NS_IMETHODIMP 171 ObliviousHttpChannel::GetAllowSTS(bool* aAllowSTS) { 172 return mInnerChannel->GetAllowSTS(aAllowSTS); 173 } 174 175 NS_IMETHODIMP 176 ObliviousHttpChannel::SetAllowSTS(bool aAllowSTS) { 177 return mInnerChannel->SetAllowSTS(aAllowSTS); 178 } 179 180 NS_IMETHODIMP 181 ObliviousHttpChannel::GetRedirectionLimit(uint32_t* aRedirectionLimit) { 182 return mInnerChannel->GetRedirectionLimit(aRedirectionLimit); 183 } 184 185 NS_IMETHODIMP 186 ObliviousHttpChannel::SetRedirectionLimit(uint32_t aRedirectionLimit) { 187 return mInnerChannel->SetRedirectionLimit(aRedirectionLimit); 188 } 189 190 NS_IMETHODIMP 191 ObliviousHttpChannel::GetResponseStatus(uint32_t* aResponseStatus) { 192 if (!mBinaryHttpResponse) { 193 return NS_ERROR_NOT_AVAILABLE; 194 } 195 uint16_t responseStatus; 196 nsresult rv = mBinaryHttpResponse->GetStatus(&responseStatus); 197 if (NS_FAILED(rv)) { 198 return rv; 199 } 200 *aResponseStatus = responseStatus; 201 return NS_OK; 202 } 203 204 NS_IMETHODIMP 205 ObliviousHttpChannel::GetResponseStatusText(nsACString& aResponseStatusText) { 206 LOG(("ObliviousHttpChannel::GetResponseStatusText NOT IMPLEMENTED [this=%p]", 207 this)); 208 return NS_ERROR_NOT_IMPLEMENTED; 209 } 210 211 NS_IMETHODIMP 212 ObliviousHttpChannel::GetRequestSucceeded(bool* aRequestSucceeded) { 213 uint32_t responseStatus; 214 nsresult rv = GetResponseStatus(&responseStatus); 215 if (NS_FAILED(rv)) { 216 return rv; 217 } 218 *aRequestSucceeded = (responseStatus / 100) == 2; 219 return NS_OK; 220 } 221 222 NS_IMETHODIMP 223 ObliviousHttpChannel::GetIsMainDocumentChannel(bool* aValue) { 224 return mInnerChannel->GetIsMainDocumentChannel(aValue); 225 } 226 227 NS_IMETHODIMP 228 ObliviousHttpChannel::SetIsMainDocumentChannel(bool aValue) { 229 return mInnerChannel->SetIsMainDocumentChannel(aValue); 230 } 231 232 NS_IMETHODIMP 233 ObliviousHttpChannel::GetResponseHeader(const nsACString& header, 234 nsACString& _retval) { 235 if (!mBinaryHttpResponse) { 236 return NS_ERROR_NOT_AVAILABLE; 237 } 238 nsTArray<nsCString> responseHeaderNames; 239 nsTArray<nsCString> responseHeaderValues; 240 nsresult rv = mBinaryHttpResponse->GetHeaderNames(responseHeaderNames); 241 if (NS_FAILED(rv)) { 242 return rv; 243 } 244 rv = mBinaryHttpResponse->GetHeaderValues(responseHeaderValues); 245 if (NS_FAILED(rv)) { 246 return rv; 247 } 248 for (size_t i = 0; 249 i < responseHeaderNames.Length() && i < responseHeaderValues.Length(); 250 i++) { 251 if (responseHeaderNames[i].EqualsIgnoreCase(header)) { 252 _retval.Assign(responseHeaderValues[i]); 253 return NS_OK; 254 } 255 } 256 return NS_ERROR_NOT_AVAILABLE; 257 } 258 259 NS_IMETHODIMP 260 ObliviousHttpChannel::SetResponseHeader(const nsACString& header, 261 const nsACString& value, bool merge) { 262 LOG(("ObliviousHttpChannel::SetResponseHeader NOT IMPLEMENTED [this=%p]", 263 this)); 264 return NS_ERROR_NOT_IMPLEMENTED; 265 } 266 267 NS_IMETHODIMP 268 ObliviousHttpChannel::VisitResponseHeaders(nsIHttpHeaderVisitor* aVisitor) { 269 if (!mBinaryHttpResponse) { 270 return NS_ERROR_NOT_AVAILABLE; 271 } 272 nsTArray<nsCString> responseHeaderNames; 273 nsTArray<nsCString> responseHeaderValues; 274 nsresult rv = mBinaryHttpResponse->GetHeaderNames(responseHeaderNames); 275 if (NS_FAILED(rv)) { 276 return rv; 277 } 278 rv = mBinaryHttpResponse->GetHeaderValues(responseHeaderValues); 279 if (NS_FAILED(rv)) { 280 return rv; 281 } 282 for (size_t i = 0; 283 i < responseHeaderNames.Length() && i < responseHeaderValues.Length(); 284 i++) { 285 rv = aVisitor->VisitHeader(responseHeaderNames[i], responseHeaderValues[i]); 286 if (NS_FAILED(rv)) { 287 return rv; 288 } 289 } 290 return rv; 291 } 292 293 NS_IMETHODIMP 294 ObliviousHttpChannel::GetOriginalResponseHeader( 295 const nsACString& header, nsIHttpHeaderVisitor* aVisitor) { 296 return NS_ERROR_NOT_IMPLEMENTED; 297 } 298 299 NS_IMETHODIMP 300 ObliviousHttpChannel::VisitOriginalResponseHeaders( 301 nsIHttpHeaderVisitor* aVisitor) { 302 LOG( 303 ("ObliviousHttpChannel::VisitOriginalResponseHeaders NOT IMPLEMENTED " 304 "[this=%p]", 305 this)); 306 return NS_ERROR_NOT_IMPLEMENTED; 307 } 308 309 NS_IMETHODIMP 310 ObliviousHttpChannel::ShouldStripRequestBodyHeader(const nsACString& aMethod, 311 bool* aResult) { 312 LOG( 313 ("ObliviousHttpChannel::ShouldStripRequestBodyHeader NOT IMPLEMENTED " 314 "[this=%p]", 315 this)); 316 return NS_ERROR_NOT_IMPLEMENTED; 317 } 318 319 NS_IMETHODIMP 320 ObliviousHttpChannel::IsNoStoreResponse(bool* _retval) { 321 LOG(("ObliviousHttpChannel::IsNoStoreResponse NOT IMPLEMENTED [this=%p]", 322 this)); 323 return NS_ERROR_NOT_IMPLEMENTED; 324 } 325 326 NS_IMETHODIMP 327 ObliviousHttpChannel::IsNoCacheResponse(bool* _retval) { 328 LOG(("ObliviousHttpChannel::IsNoCacheResponse NOT IMPLEMENTED [this=%p]", 329 this)); 330 return NS_ERROR_NOT_IMPLEMENTED; 331 } 332 333 NS_IMETHODIMP 334 ObliviousHttpChannel::RedirectTo(nsIURI* aNewURI) { 335 LOG(("ObliviousHttpChannel::RedirectTo NOT IMPLEMENTED [this=%p]", this)); 336 return NS_ERROR_NOT_IMPLEMENTED; 337 } 338 339 NS_IMETHODIMP 340 ObliviousHttpChannel::UpgradeToSecure() { 341 LOG(("ObliviousHttpChannel::UpgradeToSecure NOT IMPLEMENTED [this=%p]", 342 this)); 343 return NS_ERROR_NOT_IMPLEMENTED; 344 } 345 346 NS_IMETHODIMP 347 ObliviousHttpChannel::GetRequestObserversCalled(bool* aCalled) { 348 return mInnerChannel->GetRequestObserversCalled(aCalled); 349 } 350 351 NS_IMETHODIMP 352 ObliviousHttpChannel::SetRequestObserversCalled(bool aCalled) { 353 return mInnerChannel->SetRequestObserversCalled(aCalled); 354 } 355 356 NS_IMETHODIMP 357 ObliviousHttpChannel::GetRequestContextID(uint64_t* _retval) { 358 return mInnerChannel->GetRequestContextID(_retval); 359 } 360 361 NS_IMETHODIMP 362 ObliviousHttpChannel::SetRequestContextID(uint64_t rcID) { 363 return mInnerChannel->SetRequestContextID(rcID); 364 } 365 366 NS_IMETHODIMP 367 ObliviousHttpChannel::GetIsUserAgentHeaderOutdated(bool* aValue) { 368 return mInnerChannel->GetIsUserAgentHeaderOutdated(aValue); 369 } 370 371 NS_IMETHODIMP 372 ObliviousHttpChannel::SetIsUserAgentHeaderOutdated(bool aValue) { 373 return mInnerChannel->SetIsUserAgentHeaderOutdated(aValue); 374 } 375 376 NS_IMETHODIMP 377 ObliviousHttpChannel::GetProtocolVersion(nsACString& aProtocolVersion) { 378 return mInnerChannel->GetProtocolVersion(aProtocolVersion); 379 } 380 381 NS_IMETHODIMP 382 ObliviousHttpChannel::GetEncodedBodySize(uint64_t* aEncodedBodySize) { 383 LOG(("ObliviousHttpChannel::GetEncodedBodySize NOT IMPLEMENTED [this=%p]", 384 this)); 385 return NS_ERROR_NOT_IMPLEMENTED; 386 } 387 388 NS_IMETHODIMP 389 ObliviousHttpChannel::LogBlockedCORSRequest(const nsAString& aMessage, 390 const nsACString& aCategory, 391 bool aIsWarning) { 392 return mInnerChannel->LogBlockedCORSRequest(aMessage, aCategory, aIsWarning); 393 } 394 395 NS_IMETHODIMP 396 ObliviousHttpChannel::LogMimeTypeMismatch(const nsACString& aMessageName, 397 bool aWarning, const nsAString& aURL, 398 const nsAString& aContentType) { 399 return mInnerChannel->LogMimeTypeMismatch(aMessageName, aWarning, aURL, 400 aContentType); 401 } 402 403 void ObliviousHttpChannel::SetSource( 404 mozilla::UniquePtr<mozilla::ProfileChunkedBuffer> aSource) { 405 LOG(("ObliviousHttpChannel::SetSource NOT IMPLEMENTED [this=%p]", this)); 406 // NS_ERROR_NOT_IMPLEMENTED 407 } 408 409 void ObliviousHttpChannel::SetConnectionInfo(nsHttpConnectionInfo* aCi) { 410 if (mInnerChannelInternal) { 411 mInnerChannelInternal->SetConnectionInfo(aCi); 412 } 413 } 414 415 void ObliviousHttpChannel::DoDiagnosticAssertWhenOnStopNotCalledOnDestroy() { 416 if (mInnerChannelInternal) { 417 mInnerChannelInternal->DoDiagnosticAssertWhenOnStopNotCalledOnDestroy(); 418 } 419 } 420 421 void ObliviousHttpChannel::DisableAltDataCache() { 422 if (mInnerChannelInternal) { 423 mInnerChannelInternal->DisableAltDataCache(); 424 } 425 } 426 427 void ObliviousHttpChannel::SetAltDataForChild(bool aIsForChild) { 428 if (mInnerChannelInternal) { 429 mInnerChannelInternal->SetAltDataForChild(aIsForChild); 430 } 431 } 432 433 void ObliviousHttpChannel::SetCorsPreflightParameters( 434 nsTArray<nsTString<char>> const& aUnsafeHeaders, 435 bool aShouldStripRequestBodyHeader, bool aShouldStripAuthHeader) { 436 if (mInnerChannelInternal) { 437 mInnerChannelInternal->SetCorsPreflightParameters( 438 aUnsafeHeaders, aShouldStripRequestBodyHeader, aShouldStripAuthHeader); 439 } 440 } 441 442 //----------------------------------------------------------------------------- 443 // ObliviousHttpChannel::nsIChannel 444 //----------------------------------------------------------------------------- 445 446 NS_IMETHODIMP 447 ObliviousHttpChannel::GetOriginalURI(nsIURI** aOriginalURI) { 448 return mInnerChannel->GetOriginalURI(aOriginalURI); 449 } 450 451 NS_IMETHODIMP 452 ObliviousHttpChannel::SetOriginalURI(nsIURI* aOriginalURI) { 453 return mInnerChannel->SetOriginalURI(aOriginalURI); 454 } 455 456 NS_IMETHODIMP 457 ObliviousHttpChannel::GetURI(nsIURI** aURI) { 458 *aURI = do_AddRef(mTargetURI).take(); 459 return NS_OK; 460 } 461 462 NS_IMETHODIMP 463 ObliviousHttpChannel::GetOwner(nsISupports** aOwner) { 464 return mInnerChannel->GetOwner(aOwner); 465 } 466 467 NS_IMETHODIMP 468 ObliviousHttpChannel::SetOwner(nsISupports* aOwner) { 469 return mInnerChannel->SetOwner(aOwner); 470 } 471 472 NS_IMETHODIMP 473 ObliviousHttpChannel::GetNotificationCallbacks( 474 nsIInterfaceRequestor** aNotificationCallbacks) { 475 return mInnerChannel->GetNotificationCallbacks(aNotificationCallbacks); 476 } 477 478 NS_IMETHODIMP 479 ObliviousHttpChannel::SetNotificationCallbacks( 480 nsIInterfaceRequestor* aNotificationCallbacks) { 481 return mInnerChannel->SetNotificationCallbacks(aNotificationCallbacks); 482 } 483 484 NS_IMETHODIMP 485 ObliviousHttpChannel::GetSecurityInfo( 486 nsITransportSecurityInfo** aSecurityInfo) { 487 return mInnerChannel->GetSecurityInfo(aSecurityInfo); 488 } 489 490 NS_IMETHODIMP 491 ObliviousHttpChannel::GetContentType(nsACString& aContentType) { 492 return GetResponseHeader("content-type"_ns, aContentType); 493 } 494 495 NS_IMETHODIMP 496 ObliviousHttpChannel::SetContentType(const nsACString& aContentType) { 497 mContentType = aContentType; 498 return NS_OK; 499 } 500 501 NS_IMETHODIMP 502 ObliviousHttpChannel::GetContentCharset(nsACString& aContentCharset) { 503 return mInnerChannel->GetContentCharset(aContentCharset); 504 } 505 506 NS_IMETHODIMP 507 ObliviousHttpChannel::SetContentCharset(const nsACString& aContentCharset) { 508 return mInnerChannel->SetContentCharset(aContentCharset); 509 } 510 511 NS_IMETHODIMP 512 ObliviousHttpChannel::GetContentLength(int64_t* aContentLength) { 513 return mInnerChannel->GetContentLength(aContentLength); 514 } 515 516 NS_IMETHODIMP 517 ObliviousHttpChannel::SetContentLength(int64_t aContentLength) { 518 return mInnerChannel->SetContentLength(aContentLength); 519 } 520 521 NS_IMETHODIMP 522 ObliviousHttpChannel::Open(nsIInputStream** aStream) { 523 LOG(("ObliviousHttpChannel::Open NOT IMPLEMENTED [this=%p]", this)); 524 return NS_ERROR_NOT_IMPLEMENTED; 525 } 526 527 NS_IMETHODIMP 528 ObliviousHttpChannel::AsyncOpen(nsIStreamListener* aListener) { 529 LOG(("ObliviousHttpChannel::AsyncOpen [this=%p, listener=%p]", this, 530 aListener)); 531 mStreamListener = aListener; 532 nsresult rv = mInnerChannel->SetRequestMethod("POST"_ns); 533 if (NS_FAILED(rv)) { 534 return rv; 535 } 536 rv = mInnerChannel->SetRequestHeader("Content-Type"_ns, 537 "message/ohttp-req"_ns, false); 538 if (NS_FAILED(rv)) { 539 return rv; 540 } 541 nsAutoCString scheme; 542 if (!mTargetURI) { 543 return NS_ERROR_NULL_POINTER; 544 } 545 rv = mTargetURI->GetScheme(scheme); 546 if (NS_FAILED(rv)) { 547 return rv; 548 } 549 nsAutoCString authority; 550 rv = mTargetURI->GetHostPort(authority); 551 if (NS_FAILED(rv)) { 552 return rv; 553 } 554 nsAutoCString path; 555 rv = mTargetURI->GetPathQueryRef(path); 556 if (NS_FAILED(rv)) { 557 return rv; 558 } 559 nsTArray<nsCString> headerNames; 560 nsTArray<nsCString> headerValues; 561 for (auto iter = mHeaders.ConstIter(); !iter.Done(); iter.Next()) { 562 headerNames.AppendElement(iter.Key()); 563 headerValues.AppendElement(iter.Data()); 564 } 565 if (!mContentType.IsEmpty() && !headerNames.Contains("Content-Type")) { 566 headerNames.AppendElement("Content-Type"_ns); 567 headerValues.AppendElement(mContentType); 568 } 569 nsCOMPtr<nsIBinaryHttp> bhttp( 570 do_GetService("@mozilla.org/network/binary-http;1")); 571 nsCOMPtr<nsIBinaryHttpRequest> bhttpRequest(new BinaryHttpRequest( 572 mMethod, scheme, authority, path, std::move(headerNames), 573 std::move(headerValues), std::move(mContent))); 574 nsTArray<uint8_t> encodedRequest; 575 rv = bhttp->EncodeRequest(bhttpRequest, encodedRequest); 576 if (NS_FAILED(rv)) { 577 return rv; 578 } 579 nsCOMPtr<nsIObliviousHttp> obliviousHttp( 580 do_GetService("@mozilla.org/network/oblivious-http;1")); 581 if (!obliviousHttp) { 582 return NS_ERROR_FAILURE; 583 } 584 rv = obliviousHttp->EncapsulateRequest(mEncodedConfig, encodedRequest, 585 getter_AddRefs(mEncapsulatedRequest)); 586 if (NS_FAILED(rv)) { 587 return rv; 588 } 589 nsTArray<uint8_t> encRequest; 590 rv = mEncapsulatedRequest->GetEncRequest(encRequest); 591 if (NS_FAILED(rv)) { 592 return rv; 593 } 594 nsCOMPtr<nsIUploadChannel2> uploadChannel(do_QueryInterface(mInnerChannel)); 595 if (!uploadChannel) { 596 return NS_ERROR_UNEXPECTED; 597 } 598 nsCOMPtr<nsIInputStream> uploadStream; 599 uint32_t streamLength = encRequest.Length(); 600 rv = NS_NewByteInputStream(getter_AddRefs(uploadStream), 601 std::move(encRequest)); 602 if (NS_FAILED(rv)) { 603 return rv; 604 } 605 rv = uploadChannel->ExplicitSetUploadStream( 606 uploadStream, "message/ohttp-req"_ns, streamLength, "POST"_ns, false); 607 if (NS_FAILED(rv)) { 608 return rv; 609 } 610 return mInnerChannel->AsyncOpen(this); 611 } 612 613 NS_IMETHODIMP 614 ObliviousHttpChannel::GetCanceled(bool* aCanceled) { 615 return mInnerChannel->GetCanceled(aCanceled); 616 } 617 618 NS_IMETHODIMP 619 ObliviousHttpChannel::GetContentDisposition(uint32_t* aContentDisposition) { 620 return mInnerChannel->GetContentDisposition(aContentDisposition); 621 } 622 623 NS_IMETHODIMP 624 ObliviousHttpChannel::SetContentDisposition(uint32_t aContentDisposition) { 625 return mInnerChannel->SetContentDisposition(aContentDisposition); 626 } 627 628 NS_IMETHODIMP 629 ObliviousHttpChannel::GetContentDispositionFilename( 630 nsAString& aContentDispositionFilename) { 631 return mInnerChannel->GetContentDispositionFilename( 632 aContentDispositionFilename); 633 } 634 635 NS_IMETHODIMP 636 ObliviousHttpChannel::SetContentDispositionFilename( 637 const nsAString& aContentDispositionFilename) { 638 return mInnerChannel->SetContentDispositionFilename( 639 aContentDispositionFilename); 640 } 641 642 NS_IMETHODIMP 643 ObliviousHttpChannel::GetContentDispositionHeader( 644 nsACString& aContentDispositionHeader) { 645 return mInnerChannel->GetContentDispositionHeader(aContentDispositionHeader); 646 } 647 648 NS_IMETHODIMP 649 ObliviousHttpChannel::GetLoadInfo(nsILoadInfo** aLoadInfo) { 650 return mInnerChannel->GetLoadInfo(aLoadInfo); 651 } 652 653 NS_IMETHODIMP 654 ObliviousHttpChannel::SetLoadInfo(nsILoadInfo* aLoadInfo) { 655 return mInnerChannel->SetLoadInfo(aLoadInfo); 656 } 657 658 NS_IMETHODIMP 659 ObliviousHttpChannel::GetIsDocument(bool* aIsDocument) { 660 return mInnerChannel->GetIsDocument(aIsDocument); 661 } 662 663 //----------------------------------------------------------------------------- 664 // ObliviousHttpChannel::nsIStreamListener 665 //----------------------------------------------------------------------------- 666 667 NS_IMETHODIMP 668 ObliviousHttpChannel::OnDataAvailable(nsIRequest* aRequest, 669 nsIInputStream* aStream, uint64_t aOffset, 670 uint32_t aCount) { 671 LOG( 672 ("ObliviousHttpChannel::OnDataAvailable [this=%p, request=%p, stream=%p, " 673 "offset=%" PRIu64 ", count=%u]", 674 this, aRequest, aStream, aOffset, aCount)); 675 MOZ_ASSERT(aOffset == mRawResponse.Length()); 676 size_t oldLength = mRawResponse.Length(); 677 size_t newLength = oldLength + aCount; 678 if (newLength < oldLength) { // i.e., overflow 679 return NS_ERROR_FAILURE; 680 } 681 mRawResponse.SetCapacity(newLength); 682 mRawResponse.SetLengthAndRetainStorage(newLength); 683 void* dest = mRawResponse.Elements() + oldLength; 684 uint64_t written = 0; 685 nsresult rv = NS_ReadInputStreamToBuffer(aStream, &dest, aCount, &written); 686 if (NS_FAILED(rv)) { 687 return rv; 688 } 689 if (written != aCount) { 690 return NS_ERROR_FAILURE; 691 } 692 return NS_OK; 693 } 694 695 //----------------------------------------------------------------------------- 696 // ObliviousHttpChannel::nsIRequestObserver 697 //----------------------------------------------------------------------------- 698 699 NS_IMETHODIMP 700 ObliviousHttpChannel::OnStartRequest(nsIRequest* aRequest) { 701 LOG(("ObliviousHttpChannel::OnStartRequest [this=%p, request=%p]", this, 702 aRequest)); 703 return NS_OK; 704 } 705 706 nsresult ObliviousHttpChannel::ProcessOnStopRequest() { 707 if (mRawResponse.IsEmpty()) { 708 return NS_OK; 709 } 710 nsCOMPtr<nsIObliviousHttp> obliviousHttp( 711 do_GetService("@mozilla.org/network/oblivious-http;1")); 712 if (!obliviousHttp) { 713 return NS_ERROR_FAILURE; 714 } 715 nsCOMPtr<nsIObliviousHttpClientResponse> response; 716 nsresult rv = mEncapsulatedRequest->GetResponse(getter_AddRefs(response)); 717 if (NS_FAILED(rv)) { 718 return rv; 719 } 720 nsTArray<uint8_t> decapsulated; 721 rv = response->Decapsulate(mRawResponse, decapsulated); 722 if (NS_FAILED(rv)) { 723 return rv; 724 } 725 nsCOMPtr<nsIBinaryHttp> bhttp( 726 do_GetService("@mozilla.org/network/binary-http;1")); 727 if (!bhttp) { 728 return NS_ERROR_FAILURE; 729 } 730 return bhttp->DecodeResponse(decapsulated, 731 getter_AddRefs(mBinaryHttpResponse)); 732 } 733 734 void ObliviousHttpChannel::EmitOnDataAvailable() { 735 if (!mBinaryHttpResponse) { 736 return; 737 } 738 nsTArray<uint8_t> content; 739 nsresult rv = mBinaryHttpResponse->GetContent(content); 740 if (NS_FAILED(rv)) { 741 return; 742 } 743 if (content.IsEmpty()) { 744 return; 745 } 746 if (content.Length() > std::numeric_limits<uint32_t>::max()) { 747 return; 748 } 749 uint32_t contentLength = (uint32_t)content.Length(); 750 nsCOMPtr<nsIInputStream> contentStream; 751 rv = NS_NewByteInputStream(getter_AddRefs(contentStream), std::move(content)); 752 if (NS_FAILED(rv)) { 753 return; 754 } 755 rv = mStreamListener->OnDataAvailable(this, contentStream, 0, contentLength); 756 (void)rv; 757 } 758 759 NS_IMETHODIMP 760 ObliviousHttpChannel::OnStopRequest(nsIRequest* aRequest, 761 nsresult aStatusCode) { 762 LOG(("ObliviousHttpChannel::OnStopRequest [this=%p, request=%p, status=%u]", 763 this, aRequest, (uint32_t)aStatusCode)); 764 765 auto releaseStreamListener = MakeScopeExit( 766 [self = RefPtr{this}]() mutable { self->mStreamListener = nullptr; }); 767 768 if (NS_SUCCEEDED(aStatusCode)) { 769 bool requestSucceeded; 770 nsresult rv = mInnerChannel->GetRequestSucceeded(&requestSucceeded); 771 if (NS_SUCCEEDED(rv) && requestSucceeded) { 772 aStatusCode = ProcessOnStopRequest(); 773 } 774 } 775 (void)mStreamListener->OnStartRequest(this); 776 if (NS_SUCCEEDED(aStatusCode)) { 777 EmitOnDataAvailable(); 778 } 779 (void)mStreamListener->OnStopRequest(this, aStatusCode); 780 781 return NS_OK; 782 } 783 784 //----------------------------------------------------------------------------- 785 // ObliviousHttpChannel::nsIObliviousHttpChannel 786 //----------------------------------------------------------------------------- 787 788 NS_IMETHODIMP 789 ObliviousHttpChannel::GetRelayChannel(nsIHttpChannel** aChannel) { 790 if (!aChannel) { 791 return NS_ERROR_INVALID_ARG; 792 } 793 *aChannel = do_AddRef(mInnerChannel).take(); 794 return NS_OK; 795 } 796 797 //----------------------------------------------------------------------------- 798 // ObliviousHttpChannel::nsIUploadChannel2 799 //----------------------------------------------------------------------------- 800 801 NS_IMETHODIMP ObliviousHttpChannel::ExplicitSetUploadStream( 802 nsIInputStream* aStream, const nsACString& aContentType, 803 int64_t aContentLength, const nsACString& aMethod, bool aStreamHasHeaders) { 804 // This function should only be called before AsyncOpen. 805 if (mStreamListener) { 806 return NS_ERROR_IN_PROGRESS; 807 } 808 if (aMethod != "POST"_ns && aMethod != "PUT" && aMethod != "DELETE") { 809 return NS_ERROR_INVALID_ARG; 810 } 811 if (aStreamHasHeaders) { 812 return NS_ERROR_INVALID_ARG; 813 } 814 mMethod.Assign(aMethod); 815 uint64_t available; 816 if (aContentLength < 0) { 817 nsresult rv = aStream->Available(&available); 818 if (NS_FAILED(rv)) { 819 return rv; 820 } 821 } else { 822 available = aContentLength; 823 } 824 if (available > std::numeric_limits<int64_t>::max()) { 825 return NS_ERROR_FAILURE; 826 } 827 mContent.SetCapacity(available); 828 mContent.SetLengthAndRetainStorage(available); 829 void* dest = mContent.Elements(); 830 uint64_t written = 0; 831 nsresult rv = 832 NS_ReadInputStreamToBuffer(aStream, &dest, (int64_t)available, &written); 833 if (NS_FAILED(rv)) { 834 return rv; 835 } 836 if (written != available) { 837 return NS_ERROR_FAILURE; 838 } 839 mContentType = aContentType; 840 return NS_OK; 841 } 842 843 NS_IMETHODIMP ObliviousHttpChannel::GetUploadStreamHasHeaders( 844 bool* aUploadStreamHasHeaders) { 845 *aUploadStreamHasHeaders = false; 846 return NS_OK; 847 } 848 849 NS_IMETHODIMP ObliviousHttpChannel::CloneUploadStream( 850 int64_t* aContentLength, nsIInputStream** _retval) { 851 LOG(("ObliviousHttpChannel::CloneUploadStream NOT IMPLEMENTED [this=%p]", 852 this)); 853 return NS_ERROR_NOT_IMPLEMENTED; 854 } 855 856 NS_IMETHODIMP ObliviousHttpChannel::SetClassicScriptHintCharset( 857 const nsAString& aClassicScriptHintCharset) { 858 return NS_ERROR_NOT_IMPLEMENTED; 859 } 860 861 NS_IMETHODIMP ObliviousHttpChannel::GetClassicScriptHintCharset( 862 nsAString& aClassicScriptHintCharset) { 863 return NS_ERROR_NOT_IMPLEMENTED; 864 } 865 866 NS_IMETHODIMP ObliviousHttpChannel::SetDocumentCharacterSet( 867 const nsAString& aDocumentCharacterSet) { 868 return NS_ERROR_NOT_IMPLEMENTED; 869 } 870 871 NS_IMETHODIMP ObliviousHttpChannel::GetDocumentCharacterSet( 872 nsAString& aDocumenharacterSet) { 873 return NS_ERROR_NOT_IMPLEMENTED; 874 } 875 876 NS_IMETHODIMP ObliviousHttpChannel::GetDecompressDictionary( 877 DictionaryCacheEntry** aDictionary) { 878 *aDictionary = nullptr; 879 return NS_OK; 880 } 881 882 NS_IMETHODIMP ObliviousHttpChannel::SetDecompressDictionary( 883 DictionaryCacheEntry* aDictionary) { 884 return NS_OK; 885 } 886 887 } // namespace mozilla::net