tor-browser

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

MediaTransportHandlerIPC.cpp (17424B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #include "MediaTransportHandlerIPC.h"
      6 
      7 #include "common/browser_logging/CSFLog.h"
      8 #include "mozilla/RefPtr.h"
      9 #include "mozilla/dom/MediaTransportChild.h"
     10 #include "mozilla/ipc/BackgroundChild.h"
     11 #include "mozilla/ipc/Endpoint.h"
     12 #include "mozilla/ipc/PBackgroundChild.h"
     13 #include "mozilla/net/SocketProcessBridgeChild.h"
     14 #include "nsThreadUtils.h"
     15 
     16 namespace mozilla {
     17 
     18 static const char* mthipcLogTag = "MediaTransportHandler";
     19 #ifdef LOGTAG
     20 #  undef LOGTAG
     21 #endif
     22 #define LOGTAG mthipcLogTag
     23 
     24 MediaTransportHandlerIPC::MediaTransportHandlerIPC() = default;
     25 
     26 MediaTransportHandlerIPC::~MediaTransportHandlerIPC() = default;
     27 
     28 void MediaTransportHandlerIPC::Initialize() {
     29  using EndpointPromise =
     30      MozPromise<mozilla::ipc::Endpoint<mozilla::dom::PMediaTransportChild>,
     31                 nsCString, true>;
     32 
     33  // TODO(bug 1926450): Historically we've used STS for this, but there are
     34  // probably better options.
     35  nsresult res;
     36  mThread = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &res);
     37  MOZ_ASSERT(mThread);
     38 
     39  mInitPromise =
     40      net::SocketProcessBridgeChild::GetSocketProcessBridge()
     41          ->Then(
     42              GetCurrentSerialEventTarget(), __func__,
     43              [](const RefPtr<net::SocketProcessBridgeChild>& aBridge) {
     44                mozilla::ipc::Endpoint<mozilla::dom::PMediaTransportParent>
     45                    parentEndpoint;
     46                mozilla::ipc::Endpoint<mozilla::dom::PMediaTransportChild>
     47                    childEndpoint;
     48                mozilla::dom::PMediaTransport::CreateEndpoints(&parentEndpoint,
     49                                                               &childEndpoint);
     50 
     51                if (!aBridge || !aBridge->SendInitMediaTransport(
     52                                    std::move(parentEndpoint))) {
     53                  NS_WARNING(
     54                      "MediaTransportHandlerIPC async init failed! Webrtc "
     55                      "networking "
     56                      "will not work!");
     57                  return EndpointPromise::CreateAndReject(
     58                      nsCString("SendInitMediaTransport failed!"), __func__);
     59                }
     60 
     61                return EndpointPromise::CreateAndResolve(
     62                    std::move(childEndpoint), __func__);
     63              },
     64              [](const nsCString& aError) {
     65                return EndpointPromise::CreateAndReject(aError, __func__);
     66              })
     67          ->Then(
     68              mThread, __func__,
     69              [this, self = RefPtr<MediaTransportHandlerIPC>(this)](
     70                  mozilla::ipc::Endpoint<mozilla::dom::PMediaTransportChild>&&
     71                      aEndpoint) {
     72                RefPtr<MediaTransportChild> child =
     73                    new MediaTransportChild(this);
     74                aEndpoint.Bind(child);
     75                mChild = child;
     76 
     77                CSFLogDebug(LOGTAG, "%s Init done", __func__);
     78                return InitPromise::CreateAndResolve(true, __func__);
     79              },
     80              [=](const nsCString& aError) {
     81                CSFLogError(
     82                    LOGTAG,
     83                    "MediaTransportHandlerIPC async init failed! Webrtc "
     84                    "networking will not work! Error was %s",
     85                    aError.get());
     86                NS_WARNING(
     87                    "MediaTransportHandlerIPC async init failed! Webrtc "
     88                    "networking "
     89                    "will not work!");
     90                return InitPromise::CreateAndReject(aError, __func__);
     91              });
     92 }
     93 
     94 RefPtr<MediaTransportHandler::IceLogPromise>
     95 MediaTransportHandlerIPC::GetIceLog(const nsCString& aPattern) {
     96  return mInitPromise->Then(
     97      mThread, __func__,
     98      [=, self = RefPtr<MediaTransportHandlerIPC>(this)](bool /* dummy */) {
     99        if (!mChild) {
    100          return IceLogPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
    101        }
    102        // Compiler has trouble deducing the return type here for some reason,
    103        // so we use a temp variable as a hint.
    104        // SendGetIceLog _almost_ returns an IceLogPromise; the reject value
    105        // differs (ipc::ResponseRejectReason vs nsresult) so we need to
    106        // convert.
    107        RefPtr<IceLogPromise> promise = mChild->SendGetIceLog(aPattern)->Then(
    108            mThread, __func__,
    109            [](WebrtcGlobalLog&& aLogLines) {
    110              return IceLogPromise::CreateAndResolve(std::move(aLogLines),
    111                                                     __func__);
    112            },
    113            [](ipc::ResponseRejectReason aReason) {
    114              return IceLogPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
    115            });
    116        return promise;
    117      },
    118      [](const nsCString& aError) {
    119        return IceLogPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
    120      });
    121 }
    122 
    123 void MediaTransportHandlerIPC::ClearIceLog() {
    124  mInitPromise->Then(
    125      mThread, __func__,
    126      [=, self = RefPtr<MediaTransportHandlerIPC>(this)](bool /*dummy*/) {
    127        if (mChild) {
    128          mChild->SendClearIceLog();
    129        }
    130      },
    131      [](const nsCString& aError) {});
    132 }
    133 
    134 void MediaTransportHandlerIPC::EnterPrivateMode() {
    135  mInitPromise->Then(
    136      mThread, __func__,
    137      [=, self = RefPtr<MediaTransportHandlerIPC>(this)](bool /*dummy*/) {
    138        if (mChild) {
    139          mChild->SendEnterPrivateMode();
    140        }
    141      },
    142      [](const nsCString& aError) {});
    143 }
    144 
    145 void MediaTransportHandlerIPC::ExitPrivateMode() {
    146  mInitPromise->Then(
    147      mThread, __func__,
    148      [=, self = RefPtr<MediaTransportHandlerIPC>(this)](bool /*dummy*/) {
    149        if (mChild) {
    150          mChild->SendExitPrivateMode();
    151        }
    152      },
    153      [](const nsCString& aError) {});
    154 }
    155 
    156 void MediaTransportHandlerIPC::CreateIceCtx(const std::string& aName) {
    157  CSFLogDebug(LOGTAG, "MediaTransportHandlerIPC::CreateIceCtx start");
    158 
    159  mInitPromise->Then(
    160      mThread, __func__,
    161      [=, self = RefPtr<MediaTransportHandlerIPC>(this)](bool /*dummy*/) {
    162        if (mChild) {
    163          CSFLogDebug(LOGTAG, "%s starting", __func__);
    164          if (NS_WARN_IF(!mChild->SendCreateIceCtx(aName))) {
    165            CSFLogError(LOGTAG, "%s failed!", __func__);
    166          }
    167        }
    168      },
    169      [](const nsCString& aError) {});
    170 }
    171 
    172 nsresult MediaTransportHandlerIPC::SetIceConfig(
    173    const nsTArray<dom::RTCIceServer>& aIceServers,
    174    dom::RTCIceTransportPolicy aIcePolicy) {
    175  // Run some validation on this side of the IPC boundary so we can return
    176  // errors synchronously. We don't actually use the results. It might make
    177  // sense to move this check to PeerConnection and have this API take the
    178  // converted form, but we would need to write IPC serialization code for
    179  // the NrIce*Server types.
    180  std::vector<NrIceStunServer> stunServers;
    181  std::vector<NrIceTurnServer> turnServers;
    182  nsresult rv = ConvertIceServers(aIceServers, &stunServers, &turnServers);
    183  if (NS_FAILED(rv)) {
    184    return rv;
    185  }
    186 
    187  mInitPromise->Then(
    188      mThread, __func__,
    189      [=, iceServers = aIceServers.Clone(),
    190       self = RefPtr<MediaTransportHandlerIPC>(this)](bool /*dummy*/) {
    191        if (mChild) {
    192          if (NS_WARN_IF(!mChild->SendSetIceConfig(std::move(iceServers),
    193                                                   aIcePolicy))) {
    194            CSFLogError(LOGTAG, "%s failed!", __func__);
    195          }
    196        }
    197      },
    198      [](const nsCString& aError) {});
    199 
    200  return NS_OK;
    201 }
    202 
    203 void MediaTransportHandlerIPC::Destroy() {
    204  if (mChild) {
    205    mChild->Shutdown();
    206    mThread->Dispatch(NS_NewRunnableFunction(
    207        __func__, [child = std::move(mChild)]() { child->Close(); }));
    208  }
    209  delete this;
    210 }
    211 
    212 // We will probably be able to move the proxy lookup stuff into
    213 // this class once we move mtransport to its own process.
    214 void MediaTransportHandlerIPC::SetProxyConfig(
    215    NrSocketProxyConfig&& aProxyConfig) {
    216  mInitPromise->Then(
    217      mThread, __func__,
    218      [aProxyConfig = std::move(aProxyConfig), this,
    219       self = RefPtr<MediaTransportHandlerIPC>(this)](bool /*dummy*/) mutable {
    220        if (mChild) {
    221          mChild->SendSetProxyConfig(aProxyConfig.GetConfig());
    222        }
    223      },
    224      [](const nsCString& aError) {});
    225 }
    226 
    227 void MediaTransportHandlerIPC::EnsureProvisionalTransport(
    228    const std::string& aTransportId, const std::string& aLocalUfrag,
    229    const std::string& aLocalPwd, int aComponentCount) {
    230  mInitPromise->Then(
    231      mThread, __func__,
    232      [=, self = RefPtr<MediaTransportHandlerIPC>(this)](bool /*dummy*/) {
    233        if (mChild) {
    234          mChild->SendEnsureProvisionalTransport(aTransportId, aLocalUfrag,
    235                                                 aLocalPwd, aComponentCount);
    236        }
    237      },
    238      [](const nsCString& aError) {});
    239 }
    240 
    241 void MediaTransportHandlerIPC::SetTargetForDefaultLocalAddressLookup(
    242    const std::string& aTargetIp, uint16_t aTargetPort) {
    243  mInitPromise->Then(
    244      mThread, __func__,
    245      [=, self = RefPtr<MediaTransportHandlerIPC>(this)](bool /*dummy*/) {
    246        if (mChild) {
    247          mChild->SendSetTargetForDefaultLocalAddressLookup(aTargetIp,
    248                                                            aTargetPort);
    249        }
    250      },
    251      [](const nsCString& aError) {});
    252 }
    253 
    254 // We set default-route-only as late as possible because it depends on what
    255 // capture permissions have been granted on the window, which could easily
    256 // change between Init (ie; when the PC is created) and StartIceGathering
    257 // (ie; when we set the local description).
    258 void MediaTransportHandlerIPC::StartIceGathering(
    259    bool aDefaultRouteOnly, bool aObfuscateHostAddresses,
    260    // TODO(bug 1522205): It probably makes sense to look this up internally
    261    const nsTArray<NrIceStunAddr>& aStunAddrs) {
    262  mInitPromise->Then(
    263      mThread, __func__,
    264      [=, stunAddrs = aStunAddrs.Clone(),
    265       self = RefPtr<MediaTransportHandlerIPC>(this)](bool /*dummy*/) {
    266        if (mChild) {
    267          mChild->SendStartIceGathering(aDefaultRouteOnly,
    268                                        aObfuscateHostAddresses, stunAddrs);
    269        }
    270      },
    271      [](const nsCString& aError) {});
    272 }
    273 
    274 void MediaTransportHandlerIPC::ActivateTransport(
    275    const std::string& aTransportId, const std::string& aLocalUfrag,
    276    const std::string& aLocalPwd, size_t aComponentCount,
    277    const std::string& aUfrag, const std::string& aPassword,
    278    const nsTArray<uint8_t>& aKeyDer, const nsTArray<uint8_t>& aCertDer,
    279    SSLKEAType aAuthType, bool aDtlsClient, const DtlsDigestList& aDigests,
    280    bool aPrivacyRequested) {
    281  mInitPromise->Then(
    282      mThread, __func__,
    283      [=, keyDer = aKeyDer.Clone(), certDer = aCertDer.Clone(),
    284       self = RefPtr<MediaTransportHandlerIPC>(this)](bool /*dummy*/) {
    285        if (mChild) {
    286          mChild->SendActivateTransport(aTransportId, aLocalUfrag, aLocalPwd,
    287                                        aComponentCount, aUfrag, aPassword,
    288                                        keyDer, certDer, aAuthType, aDtlsClient,
    289                                        aDigests, aPrivacyRequested);
    290        }
    291      },
    292      [](const nsCString& aError) {});
    293 }
    294 
    295 void MediaTransportHandlerIPC::RemoveTransportsExcept(
    296    const std::set<std::string>& aTransportIds) {
    297  std::vector<std::string> transportIds(aTransportIds.begin(),
    298                                        aTransportIds.end());
    299  mInitPromise->Then(
    300      mThread, __func__,
    301      [=, self = RefPtr<MediaTransportHandlerIPC>(this)](bool /*dummy*/) {
    302        if (mChild) {
    303          mChild->SendRemoveTransportsExcept(transportIds);
    304        }
    305      },
    306      [](const nsCString& aError) {});
    307 }
    308 
    309 void MediaTransportHandlerIPC::StartIceChecks(
    310    bool aIsControlling, const std::vector<std::string>& aIceOptions) {
    311  mInitPromise->Then(
    312      mThread, __func__,
    313      [=, self = RefPtr<MediaTransportHandlerIPC>(this)](bool /*dummy*/) {
    314        if (mChild) {
    315          mChild->SendStartIceChecks(aIsControlling, aIceOptions);
    316        }
    317      },
    318      [](const nsCString& aError) {});
    319 }
    320 
    321 void MediaTransportHandlerIPC::SendPacket(const std::string& aTransportId,
    322                                          MediaPacket&& aPacket) {
    323  mInitPromise->Then(
    324      mThread, __func__,
    325      [this, self = RefPtr<MediaTransportHandlerIPC>(this), aTransportId,
    326       aPacket = std::move(aPacket)](bool /*dummy*/) mutable {
    327        if (mChild) {
    328          mChild->SendSendPacket(aTransportId, std::move(aPacket));
    329        }
    330      },
    331      [](const nsCString& aError) {});
    332 }
    333 
    334 void MediaTransportHandlerIPC::AddIceCandidate(
    335    const std::string& aTransportId, const std::string& aCandidate,
    336    const std::string& aUfrag, const std::string& aObfuscatedAddress) {
    337  mInitPromise->Then(
    338      mThread, __func__,
    339      [=, self = RefPtr<MediaTransportHandlerIPC>(this)](bool /*dummy*/) {
    340        if (mChild) {
    341          mChild->SendAddIceCandidate(aTransportId, aCandidate, aUfrag,
    342                                      aObfuscatedAddress);
    343        }
    344      },
    345      [](const nsCString& aError) {});
    346 }
    347 
    348 void MediaTransportHandlerIPC::UpdateNetworkState(bool aOnline) {
    349  mInitPromise->Then(
    350      mThread, __func__,
    351      [=, self = RefPtr<MediaTransportHandlerIPC>(this)](bool /*dummy*/) {
    352        if (mChild) {
    353          mChild->SendUpdateNetworkState(aOnline);
    354        }
    355      },
    356      [](const nsCString& aError) {});
    357 }
    358 
    359 RefPtr<dom::RTCStatsPromise> MediaTransportHandlerIPC::GetIceStats(
    360    const std::string& aTransportId, DOMHighResTimeStamp aNow) {
    361  using IPCPromise = dom::PMediaTransportChild::GetIceStatsPromise;
    362  return mInitPromise
    363      ->Then(mThread, __func__,
    364             [aTransportId, aNow, this, self = RefPtr(this)](
    365                 const InitPromise::ResolveOrRejectValue& aValue) {
    366               if (aValue.IsReject()) {
    367                 return IPCPromise::CreateAndResolve(
    368                     MakeUnique<dom::RTCStatsCollection>(),
    369                     "MediaTransportHandlerIPC::GetIceStats_1");
    370               }
    371               if (!mChild) {
    372                 return IPCPromise::CreateAndResolve(
    373                     MakeUnique<dom::RTCStatsCollection>(),
    374                     "MediaTransportHandlerIPC::GetIceStats_1");
    375               }
    376               return mChild->SendGetIceStats(aTransportId, aNow);
    377             })
    378      ->Then(mThread, __func__, [](IPCPromise::ResolveOrRejectValue&& aValue) {
    379        if (aValue.IsReject()) {
    380          return dom::RTCStatsPromise::CreateAndResolve(
    381              MakeUnique<dom::RTCStatsCollection>(),
    382              "MediaTransportHandlerIPC::GetIceStats_2");
    383        }
    384        return dom::RTCStatsPromise::CreateAndResolve(
    385            std::move(aValue.ResolveValue()),
    386            "MediaTransportHandlerIPC::GetIceStats_2");
    387      });
    388 }
    389 
    390 MediaTransportChild::MediaTransportChild(MediaTransportHandlerIPC* aUser)
    391    : mMutex("MediaTransportChild"), mUser(aUser) {}
    392 
    393 MediaTransportChild::~MediaTransportChild() = default;
    394 
    395 mozilla::ipc::IPCResult MediaTransportChild::RecvOnCandidate(
    396    const string& transportId, CandidateInfo&& candidateInfo) {
    397  MutexAutoLock lock(mMutex);
    398  if (mUser) {
    399    mUser->OnCandidate(transportId, std::move(candidateInfo));
    400  }
    401  return ipc::IPCResult::Ok();
    402 }
    403 
    404 mozilla::ipc::IPCResult MediaTransportChild::RecvOnAlpnNegotiated(
    405    const string& alpn) {
    406  MutexAutoLock lock(mMutex);
    407  if (mUser) {
    408    mUser->OnAlpnNegotiated(alpn);
    409  }
    410  return ipc::IPCResult::Ok();
    411 }
    412 
    413 mozilla::ipc::IPCResult MediaTransportChild::RecvOnGatheringStateChange(
    414    const string& transportId, const int& state) {
    415  MutexAutoLock lock(mMutex);
    416  if (mUser) {
    417    mUser->OnGatheringStateChange(transportId,
    418                                  static_cast<dom::RTCIceGathererState>(state));
    419  }
    420  return ipc::IPCResult::Ok();
    421 }
    422 
    423 mozilla::ipc::IPCResult MediaTransportChild::RecvOnConnectionStateChange(
    424    const string& transportId, const int& state) {
    425  MutexAutoLock lock(mMutex);
    426  if (mUser) {
    427    mUser->OnConnectionStateChange(
    428        transportId, static_cast<dom::RTCIceTransportState>(state));
    429  }
    430  return ipc::IPCResult::Ok();
    431 }
    432 
    433 mozilla::ipc::IPCResult MediaTransportChild::RecvOnPacketReceived(
    434    string&& transportId, MediaPacket&& packet) {
    435  MutexAutoLock lock(mMutex);
    436  if (mUser) {
    437    mUser->OnPacketReceived(std::forward<string>(transportId),
    438                            std::forward<MediaPacket>(packet));
    439  }
    440  return ipc::IPCResult::Ok();
    441 }
    442 
    443 mozilla::ipc::IPCResult MediaTransportChild::RecvOnEncryptedSending(
    444    const string& transportId, MediaPacket&& packet) {
    445  MutexAutoLock lock(mMutex);
    446  if (mUser) {
    447    mUser->OnEncryptedSending(transportId, std::move(packet));
    448  }
    449  return ipc::IPCResult::Ok();
    450 }
    451 
    452 mozilla::ipc::IPCResult MediaTransportChild::RecvOnStateChange(
    453    const string& transportId, const int& state) {
    454  MutexAutoLock lock(mMutex);
    455  if (mUser) {
    456    mUser->OnStateChange(transportId,
    457                         static_cast<TransportLayer::State>(state));
    458  }
    459  return ipc::IPCResult::Ok();
    460 }
    461 
    462 mozilla::ipc::IPCResult MediaTransportChild::RecvOnRtcpStateChange(
    463    const string& transportId, const int& state) {
    464  MutexAutoLock lock(mMutex);
    465  if (mUser) {
    466    mUser->OnRtcpStateChange(transportId,
    467                             static_cast<TransportLayer::State>(state));
    468  }
    469  return ipc::IPCResult::Ok();
    470 }
    471 
    472 void MediaTransportChild::Shutdown() {
    473  MutexAutoLock lock(mMutex);
    474  mUser = nullptr;
    475 }
    476 
    477 }  // namespace mozilla