Bug 1425901: Use nsITimerCallback for DTMF timers. r?drno draft
authorByron Campen [:bwc] <docfaraday@gmail.com>
Mon, 18 Dec 2017 12:36:23 -0600
changeset 712766 11e4e1aef89f19a0941fccc8aee46cbb300164cf
parent 712645 5572465c08a9ce0671dcd01c721f9356fcd53a65
child 744132 85486bfbcf2aeffdf1859ad6715bc8027c4505ca
push id93420
push userbcampen@mozilla.com
push dateMon, 18 Dec 2017 18:40:20 +0000
reviewersdrno
bugs1425901
milestone59.0a1
Bug 1425901: Use nsITimerCallback for DTMF timers. r?drno MozReview-Commit-ID: 2IlDknNhlAG
media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
@@ -2327,18 +2327,18 @@ PeerConnectionImpl::RemoveTrack(MediaStr
     mMedia->GetTransceivers();
 
   nsresult rv = NS_ERROR_INVALID_ARG;
 
   for (RefPtr<TransceiverImpl>& transceiver : transceivers) {
     if (transceiver->HasSendTrack(&aTrack)) {
       // TODO(bug 1401983): Move DTMF stuff to TransceiverImpl
       for (size_t i = 0; i < mDTMFStates.Length(); ++i) {
-        if (mDTMFStates[i].mTransceiver.get() == transceiver.get()) {
-          mDTMFStates[i].mSendTimer->Cancel();
+        if (mDTMFStates[i]->mTransceiver.get() == transceiver.get()) {
+          mDTMFStates[i]->mSendTimer->Cancel();
           mDTMFStates.RemoveElementAt(i);
           break;
         }
       }
 
       rv = transceiver->UpdateSendTrack(nullptr);
       break;
     }
@@ -2430,40 +2430,38 @@ PeerConnectionImpl::InsertDTMF(Transceiv
   MOZ_ASSERT(duration >= 40, "duration must be at least 40");
   MOZ_ASSERT(duration <= 6000, "duration must be at most 6000");
   MOZ_ASSERT(interToneGap >= 30, "interToneGap must be at least 30");
 
   JSErrorResult jrv;
 
   // TODO(bug 1401983): Move DTMF stuff to TransceiverImpl
   // Attempt to locate state for the DTMFSender
-  DTMFState* state = nullptr;
+  RefPtr<DTMFState> state;
   for (auto& dtmfState : mDTMFStates) {
-    if (dtmfState.mTransceiver.get() == &transceiver) {
-      state = &dtmfState;
+    if (dtmfState->mTransceiver.get() == &transceiver) {
+      state = dtmfState;
       break;
     }
   }
 
   // No state yet, create a new one
   if (!state) {
-    state = mDTMFStates.AppendElement();
+    state = *mDTMFStates.AppendElement(new DTMFState);
     state->mPCObserver = mPCObserver;
     state->mTransceiver = &transceiver;
     state->mSendTimer = NS_NewTimer();
   }
   MOZ_ASSERT(state);
 
   state->mTones = tones;
   state->mDuration = duration;
   state->mInterToneGap = interToneGap;
   if (!state->mTones.IsEmpty()) {
-    state->mSendTimer->InitWithNamedFuncCallback(DTMFSendTimerCallback_m, state, 0,
-                                                 nsITimer::TYPE_ONE_SHOT,
-                                                 "DTMFSendTimerCallback_m");
+    state->mSendTimer->InitWithCallback(state, 0, nsITimer::TYPE_ONE_SHOT);
   }
   return NS_OK;
 }
 
 
 NS_IMETHODIMP
 PeerConnectionImpl::GetDTMFToneBuffer(mozilla::dom::RTCRtpSender& sender,
                                       nsAString& outToneBuffer) {
@@ -2476,18 +2474,18 @@ PeerConnectionImpl::GetDTMFToneBuffer(mo
   if (jrv.Failed()) {
     NS_WARNING("Failed to retrieve track for RTCRtpSender!");
     return jrv.StealNSResult();
   }
 
   // TODO(bug 1401983): Move DTMF stuff to TransceiverImpl
   // Attempt to locate state for the DTMFSender
   for (auto& dtmfState : mDTMFStates) {
-    if (dtmfState.mTransceiver->HasSendTrack(mst)) {
-      outToneBuffer = dtmfState.mTones;
+    if (dtmfState->mTransceiver->HasSendTrack(mst)) {
+      outToneBuffer = dtmfState->mTones;
       break;
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -2505,18 +2503,18 @@ PeerConnectionImpl::ReplaceTrackNoRenego
   if (NS_FAILED(rv)) {
     CSFLogError(LOGTAG,
                 "Failed to update transceiver: %d", static_cast<int>(rv));
     return rv;
   }
 
   // TODO(bug 1401983): Move DTMF stuff to TransceiverImpl
   for (size_t i = 0; i < mDTMFStates.Length(); ++i) {
-    if (mDTMFStates[i].mTransceiver.get() == &aTransceiver) {
-      mDTMFStates[i].mSendTimer->Cancel();
+    if (mDTMFStates[i]->mTransceiver.get() == &aTransceiver) {
+      mDTMFStates[i]->mSendTimer->Cancel();
       mDTMFStates.RemoveElementAt(i);
       break;
     }
   }
 
   if (aWithTrack) {
     aWithTrack->AddPrincipalChangeObserver(this);
     PrincipalChanged(aWithTrack);
@@ -2795,17 +2793,17 @@ PeerConnectionImpl::RecordEndOfCallTelem
 
 nsresult
 PeerConnectionImpl::CloseInt()
 {
   PC_AUTO_ENTER_API_CALL_NO_CHECK();
 
   // TODO(bug 1401983): Move DTMF stuff to TransceiverImpl
   for (auto& dtmfState : mDTMFStates) {
-    dtmfState.mSendTimer->Cancel();
+    dtmfState->mSendTimer->Cancel();
   }
 
   // We do this at the end of the call because we want to make sure we've waited
   // for all trickle ICE candidates to come in; this can happen well after we've
   // transitioned to connected. As a bonus, this allows us to detect race
   // conditions where a stats dispatch happens right as the PC closes.
   if (!mPrivateWindow) {
     RecordLongtermICEStatistics();
@@ -3772,60 +3770,58 @@ PeerConnectionImpl::startCallTelem() {
   // Start time for calls
   mStartTime = TimeStamp::Now();
 
   // Increment session call counter
   // If we want to track Loop calls independently here, we need two histograms.
   Telemetry::Accumulate(Telemetry::WEBRTC_CALL_COUNT_2, 1);
 }
 
-void
-PeerConnectionImpl::DTMFSendTimerCallback_m(nsITimer* timer, void* closure)
+nsresult
+PeerConnectionImpl::DTMFState::Notify(nsITimer* timer)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  auto state = static_cast<DTMFState*>(closure);
-
   nsString eventTone;
-  if (!state->mTones.IsEmpty()) {
-    uint16_t toneChar = state->mTones.CharAt(0);
+  if (!mTones.IsEmpty()) {
+    uint16_t toneChar = mTones.CharAt(0);
     int tone = GetDTMFToneCode(toneChar);
 
     eventTone.Assign(toneChar);
 
-    state->mTones.Cut(0, 1);
+    mTones.Cut(0, 1);
 
     if (tone == -1) {
-      state->mSendTimer->InitWithNamedFuncCallback(DTMFSendTimerCallback_m, state,
-                                                   2000, nsITimer::TYPE_ONE_SHOT,
-                                                   "DTMFSendTimerCallback_m");
+      mSendTimer->InitWithCallback(this, 2000, nsITimer::TYPE_ONE_SHOT);
     } else {
       // Reset delay if necessary
-      state->mSendTimer->InitWithNamedFuncCallback(DTMFSendTimerCallback_m, state,
-                                                   state->mDuration + state->mInterToneGap,
-                                                   nsITimer::TYPE_ONE_SHOT,
-                                                   "DTMFSendTimerCallback_m");
-
-      state->mTransceiver->InsertDTMFTone(tone, state->mDuration);
+      mSendTimer->InitWithCallback(this,
+                                   mDuration + mInterToneGap,
+                                   nsITimer::TYPE_ONE_SHOT);
+
+      mTransceiver->InsertDTMFTone(tone, mDuration);
     }
   } else {
-    state->mSendTimer->Cancel();
+    mSendTimer->Cancel();
   }
 
-  RefPtr<PeerConnectionObserver> pco = do_QueryObjectReferent(state->mPCObserver);
+  RefPtr<PeerConnectionObserver> pco = do_QueryObjectReferent(mPCObserver);
   if (!pco) {
     NS_WARNING("Failed to dispatch the RTCDTMFToneChange event!");
-    return;
+    return NS_OK; // Return is ignored anyhow
   }
 
   JSErrorResult jrv;
-  pco->OnDTMFToneChange(*state->mTransceiver->GetSendTrack(), eventTone, jrv);
+  pco->OnDTMFToneChange(*mTransceiver->GetSendTrack(), eventTone, jrv);
 
   if (jrv.Failed()) {
     NS_WARNING("Failed to dispatch the RTCDTMFToneChange event!");
-    return;
   }
+
+  return NS_OK;
 }
 
 PeerConnectionImpl::DTMFState::DTMFState() = default;
 PeerConnectionImpl::DTMFState::~DTMFState() = default;
 
+NS_IMPL_ISUPPORTS(PeerConnectionImpl::DTMFState, nsITimerCallback)
+
 }  // end mozilla namespace
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.h
@@ -822,32 +822,34 @@ private:
   // Whether this PeerConnection is being counted as active by mWindow
   bool mActiveOnWindow;
 
   // storage for Telemetry data
   uint16_t mMaxReceiving[SdpMediaSection::kMediaTypes];
   uint16_t mMaxSending[SdpMediaSection::kMediaTypes];
 
   // DTMF
-  struct DTMFState {
-    DTMFState();
-    ~DTMFState();
-    nsWeakPtr mPCObserver;
-    RefPtr<TransceiverImpl> mTransceiver;
-    nsCOMPtr<nsITimer> mSendTimer;
-    nsString mTones;
-    uint32_t mDuration;
-    uint32_t mInterToneGap;
+  class DTMFState : public nsITimerCallback {
+      virtual ~DTMFState();
+    public:
+      DTMFState();
+
+      NS_DECL_NSITIMERCALLBACK
+      NS_DECL_THREADSAFE_ISUPPORTS
+
+      nsWeakPtr mPCObserver;
+      RefPtr<TransceiverImpl> mTransceiver;
+      nsCOMPtr<nsITimer> mSendTimer;
+      nsString mTones;
+      uint32_t mDuration;
+      uint32_t mInterToneGap;
   };
 
-  static void
-  DTMFSendTimerCallback_m(nsITimer* timer, void*);
-
   // TODO(bug 1401983): Move DTMF stuff to TransceiverImpl
-  nsTArray<DTMFState> mDTMFStates;
+  nsTArray<RefPtr<DTMFState>> mDTMFStates;
 
   std::vector<unsigned> mSendPacketDumpFlags;
   std::vector<unsigned> mRecvPacketDumpFlags;
   Atomic<bool> mPacketDumpEnabled;
   mutable Mutex mPacketDumpFlagsMutex;
 
 public:
   //these are temporary until the DataChannel Listen/Connect API is removed