tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

GIOChannelParent.cpp (9730B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=4 sw=2 sts=2 et tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "GIOChannelParent.h"
      8 #include "nsGIOProtocolHandler.h"
      9 #include "mozilla/Assertions.h"
     10 #include "mozilla/dom/ContentParent.h"
     11 #include "mozilla/dom/BrowserParent.h"
     12 #include "mozilla/net/NeckoParent.h"
     13 #include "nsNetUtil.h"
     14 #include "nsIChannel.h"
     15 #include "mozilla/net/NeckoChannelParams.h"
     16 #include "nsIAuthPrompt.h"
     17 #include "nsIAuthPromptProvider.h"
     18 #include "nsISecureBrowserUI.h"
     19 #include "nsQueryObject.h"
     20 #include "mozilla/Logging.h"
     21 #include "mozilla/net/ChannelEventQueue.h"
     22 #include "mozilla/ipc/URIUtils.h"
     23 
     24 using namespace mozilla::dom;
     25 using namespace mozilla::ipc;
     26 
     27 namespace mozilla {
     28 #undef LOG
     29 #define LOG(args) MOZ_LOG(gGIOLog, mozilla::LogLevel::Debug, args)
     30 namespace net {
     31 
     32 GIOChannelParent::GIOChannelParent(dom::BrowserParent* aIframeEmbedding,
     33                                   nsILoadContext* aLoadContext,
     34                                   PBOverrideStatus aOverrideStatus)
     35    : mLoadContext(aLoadContext),
     36      mPBOverride(aOverrideStatus),
     37      mBrowserParent(aIframeEmbedding) {
     38  mEventQ = new ChannelEventQueue(static_cast<nsIParentChannel*>(this));
     39 }
     40 
     41 void GIOChannelParent::ActorDestroy(ActorDestroyReason why) {
     42  // We may still have refcount>0 if the channel hasn't called OnStopRequest
     43  // yet, but we must not send any more msgs to child.
     44  mIPCClosed = true;
     45 }
     46 
     47 //-----------------------------------------------------------------------------
     48 // GIOChannelParent::nsISupports
     49 //-----------------------------------------------------------------------------
     50 NS_IMPL_ISUPPORTS(GIOChannelParent, nsIStreamListener, nsIParentChannel,
     51                  nsIInterfaceRequestor, nsIRequestObserver)
     52 
     53 //-----------------------------------------------------------------------------
     54 // GIOChannelParent methods
     55 //-----------------------------------------------------------------------------
     56 
     57 bool GIOChannelParent::Init(const GIOChannelCreationArgs& aOpenArgs) {
     58  switch (aOpenArgs.type()) {
     59    case GIOChannelCreationArgs::TGIOChannelOpenArgs: {
     60      const GIOChannelOpenArgs& a = aOpenArgs.get_GIOChannelOpenArgs();
     61      return DoAsyncOpen(a.uri(), a.startPos(), a.entityID(), a.uploadStream(),
     62                         a.loadInfo(), a.loadFlags());
     63    }
     64    case GIOChannelCreationArgs::TGIOChannelConnectArgs: {
     65      const GIOChannelConnectArgs& cArgs =
     66          aOpenArgs.get_GIOChannelConnectArgs();
     67      return ConnectChannel(cArgs.channelId());
     68    }
     69    default:
     70      MOZ_ASSERT_UNREACHABLE("unknown open type");
     71      return false;
     72  }
     73 }
     74 
     75 bool GIOChannelParent::DoAsyncOpen(const URIParams& aURI,
     76                                   const uint64_t& aStartPos,
     77                                   const nsCString& aEntityID,
     78                                   const Maybe<IPCStream>& aUploadStream,
     79                                   const LoadInfoArgs& aLoadInfoArgs,
     80                                   const uint32_t& aLoadFlags) {
     81  nsresult rv;
     82 
     83  nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
     84  if (!uri) {
     85    return false;
     86  }
     87 
     88 #ifdef DEBUG
     89  LOG(("GIOChannelParent DoAsyncOpen [this=%p uri=%s]\n", this,
     90       uri->GetSpecOrDefault().get()));
     91 #endif
     92 
     93  nsCOMPtr<nsIIOService> ios(do_GetIOService(&rv));
     94  if (NS_FAILED(rv)) {
     95    return SendFailedAsyncOpen(rv);
     96  }
     97 
     98  nsAutoCString remoteType;
     99  rv = GetRemoteType(remoteType);
    100  if (NS_FAILED(rv)) {
    101    return SendFailedAsyncOpen(rv);
    102  }
    103 
    104  nsCOMPtr<nsILoadInfo> loadInfo;
    105  rv = mozilla::ipc::LoadInfoArgsToLoadInfo(aLoadInfoArgs, remoteType,
    106                                            getter_AddRefs(loadInfo));
    107  if (NS_FAILED(rv)) {
    108    return SendFailedAsyncOpen(rv);
    109  }
    110 
    111  OriginAttributes attrs;
    112  rv = loadInfo->GetOriginAttributes(&attrs);
    113  if (NS_FAILED(rv)) {
    114    return SendFailedAsyncOpen(rv);
    115  }
    116 
    117  nsCOMPtr<nsIChannel> chan;
    118  rv = NS_NewChannelInternal(getter_AddRefs(chan), uri, loadInfo, nullptr,
    119                             nullptr, nullptr, aLoadFlags, ios);
    120 
    121  if (NS_FAILED(rv)) {
    122    return SendFailedAsyncOpen(rv);
    123  }
    124 
    125  mChannel = chan;
    126 
    127  nsIChannel* gioChan = static_cast<nsIChannel*>(mChannel.get());
    128 
    129  rv = gioChan->AsyncOpen(this);
    130  if (NS_FAILED(rv)) {
    131    return SendFailedAsyncOpen(rv);
    132  }
    133 
    134  return true;
    135 }
    136 
    137 bool GIOChannelParent::ConnectChannel(const uint64_t& channelId) {
    138  nsresult rv;
    139 
    140  LOG(("Looking for a registered channel [this=%p, id=%" PRIx64 "]", this,
    141       channelId));
    142 
    143  nsCOMPtr<nsIChannel> channel;
    144  rv = NS_LinkRedirectChannels(channelId, this, getter_AddRefs(channel));
    145  if (NS_SUCCEEDED(rv)) {
    146    mChannel = channel;
    147  }
    148 
    149  LOG(("  found channel %p, rv=%08" PRIx32, mChannel.get(),
    150       static_cast<uint32_t>(rv)));
    151 
    152  return true;
    153 }
    154 
    155 mozilla::ipc::IPCResult GIOChannelParent::RecvCancel(const nsresult& status) {
    156  if (mChannel) {
    157    mChannel->Cancel(status);
    158  }
    159 
    160  return IPC_OK();
    161 }
    162 
    163 mozilla::ipc::IPCResult GIOChannelParent::RecvSuspend() {
    164  if (mChannel) {
    165    mChannel->Suspend();
    166  }
    167  return IPC_OK();
    168 }
    169 
    170 mozilla::ipc::IPCResult GIOChannelParent::RecvResume() {
    171  if (mChannel) {
    172    mChannel->Resume();
    173  }
    174  return IPC_OK();
    175 }
    176 
    177 //-----------------------------------------------------------------------------
    178 // GIOChannelParent::nsIRequestObserver
    179 //-----------------------------------------------------------------------------
    180 
    181 NS_IMETHODIMP
    182 GIOChannelParent::OnStartRequest(nsIRequest* aRequest) {
    183  LOG(("GIOChannelParent::OnStartRequest [this=%p]\n", this));
    184  nsCOMPtr<nsIChannel> chan = do_QueryInterface(aRequest);
    185  MOZ_ASSERT(chan);
    186  NS_ENSURE_TRUE(chan, NS_ERROR_UNEXPECTED);
    187 
    188  int64_t contentLength;
    189  chan->GetContentLength(&contentLength);
    190  nsCString contentType;
    191  chan->GetContentType(contentType);
    192  nsresult channelStatus = NS_OK;
    193  chan->GetStatus(&channelStatus);
    194 
    195  nsCString entityID;
    196  URIParams uriparam;
    197  nsCOMPtr<nsIURI> uri;
    198  chan->GetURI(getter_AddRefs(uri));
    199  SerializeURI(uri, uriparam);
    200 
    201  if (mIPCClosed || !SendOnStartRequest(channelStatus, contentLength,
    202                                        contentType, entityID, uriparam)) {
    203    return NS_ERROR_UNEXPECTED;
    204  }
    205 
    206  return NS_OK;
    207 }
    208 
    209 NS_IMETHODIMP
    210 GIOChannelParent::OnStopRequest(nsIRequest* aRequest, nsresult aStatusCode) {
    211  LOG(("GIOChannelParent::OnStopRequest: [this=%p status=%" PRIu32 "]\n", this,
    212       static_cast<uint32_t>(aStatusCode)));
    213 
    214  if (mIPCClosed || !SendOnStopRequest(aStatusCode)) {
    215    return NS_ERROR_UNEXPECTED;
    216  }
    217 
    218  return NS_OK;
    219 }
    220 
    221 //-----------------------------------------------------------------------------
    222 // GIOChannelParent::nsIStreamListener
    223 //-----------------------------------------------------------------------------
    224 
    225 NS_IMETHODIMP
    226 GIOChannelParent::OnDataAvailable(nsIRequest* aRequest,
    227                                  nsIInputStream* aInputStream,
    228                                  uint64_t aOffset, uint32_t aCount) {
    229  LOG(("GIOChannelParent::OnDataAvailable [this=%p]\n", this));
    230 
    231  nsCString data;
    232  nsresult rv = NS_ReadInputStreamToString(aInputStream, data, aCount);
    233  if (NS_FAILED(rv)) {
    234    return rv;
    235  }
    236 
    237  nsresult channelStatus = NS_OK;
    238  mChannel->GetStatus(&channelStatus);
    239 
    240  if (mIPCClosed ||
    241      !SendOnDataAvailable(channelStatus, data, aOffset, aCount)) {
    242    return NS_ERROR_UNEXPECTED;
    243  }
    244  return NS_OK;
    245 }
    246 
    247 //-----------------------------------------------------------------------------
    248 // GIOChannelParent::nsIParentChannel
    249 //-----------------------------------------------------------------------------
    250 
    251 NS_IMETHODIMP
    252 GIOChannelParent::SetParentListener(ParentChannelListener* aListener) {
    253  // Do not need ptr to ParentChannelListener.
    254  return NS_OK;
    255 }
    256 
    257 NS_IMETHODIMP
    258 GIOChannelParent::NotifyClassificationFlags(uint32_t aClassificationFlags,
    259                                            bool aIsThirdParty) {
    260  // Nothing to do.
    261  return NS_OK;
    262 }
    263 
    264 NS_IMETHODIMP
    265 GIOChannelParent::SetClassifierMatchedInfo(const nsACString& aList,
    266                                           const nsACString& aProvider,
    267                                           const nsACString& aFullHash) {
    268  // nothing to do
    269  return NS_OK;
    270 }
    271 
    272 NS_IMETHODIMP
    273 GIOChannelParent::SetClassifierMatchedTrackingInfo(
    274    const nsACString& aLists, const nsACString& aFullHashes) {
    275  // nothing to do
    276  return NS_OK;
    277 }
    278 
    279 NS_IMETHODIMP
    280 GIOChannelParent::Delete() {
    281  if (mIPCClosed || !SendDeleteSelf()) {
    282    return NS_ERROR_UNEXPECTED;
    283  }
    284 
    285  return NS_OK;
    286 }
    287 
    288 NS_IMETHODIMP
    289 GIOChannelParent::GetRemoteType(nsACString& aRemoteType) {
    290  if (!CanSend()) {
    291    return NS_ERROR_UNEXPECTED;
    292  }
    293 
    294  dom::PContentParent* pcp = Manager()->Manager();
    295  aRemoteType = static_cast<dom::ContentParent*>(pcp)->GetRemoteType();
    296  return NS_OK;
    297 }
    298 
    299 //-----------------------------------------------------------------------------
    300 // GIOChannelParent::nsIInterfaceRequestor
    301 //-----------------------------------------------------------------------------
    302 
    303 NS_IMETHODIMP
    304 GIOChannelParent::GetInterface(const nsIID& uuid, void** result) {
    305  if (uuid.Equals(NS_GET_IID(nsIAuthPromptProvider)) ||
    306      uuid.Equals(NS_GET_IID(nsISecureBrowserUI))) {
    307    if (mBrowserParent) {
    308      return mBrowserParent->QueryInterface(uuid, result);
    309    }
    310  }
    311 
    312  // Only support nsILoadContext if child channel's callbacks did too
    313  if (uuid.Equals(NS_GET_IID(nsILoadContext)) && mLoadContext) {
    314    nsCOMPtr<nsILoadContext> copy = mLoadContext;
    315    copy.forget(result);
    316    return NS_OK;
    317  }
    318 
    319  return QueryInterface(uuid, result);
    320 }
    321 
    322 //---------------------
    323 }  // namespace net
    324 }  // namespace mozilla