Merging BaseSession code into WebRtcSession.

After the TransportController CL, BaseSession does little more than
hold a state and an error, and act as an intermediary for the
TransportController. So it doesn't make sense for it to be its own
class.

Review URL: https://codereview.webrtc.org/1397973002

Cr-Commit-Position: refs/heads/master@{#10281}
diff --git a/talk/app/webrtc/peerconnection.cc b/talk/app/webrtc/peerconnection.cc
index 4df6790..e7b33c4 100644
--- a/talk/app/webrtc/peerconnection.cc
+++ b/talk/app/webrtc/peerconnection.cc
@@ -1163,32 +1163,31 @@
   // streams before the channels are closed.
   stats_->UpdateStats(kStatsOutputLevelStandard);
 
-  session_->Terminate();
+  session_->Close();
 }
 
-void PeerConnection::OnSessionStateChange(cricket::BaseSession* /*session*/,
-                                          cricket::BaseSession::State state) {
+void PeerConnection::OnSessionStateChange(WebRtcSession* /*session*/,
+                                          WebRtcSession::State state) {
   switch (state) {
-    case cricket::BaseSession::STATE_INIT:
+    case WebRtcSession::STATE_INIT:
       ChangeSignalingState(PeerConnectionInterface::kStable);
       break;
-    case cricket::BaseSession::STATE_SENTINITIATE:
+    case WebRtcSession::STATE_SENTOFFER:
       ChangeSignalingState(PeerConnectionInterface::kHaveLocalOffer);
       break;
-    case cricket::BaseSession::STATE_SENTPRACCEPT:
+    case WebRtcSession::STATE_SENTPRANSWER:
       ChangeSignalingState(PeerConnectionInterface::kHaveLocalPrAnswer);
       break;
-    case cricket::BaseSession::STATE_RECEIVEDINITIATE:
+    case WebRtcSession::STATE_RECEIVEDOFFER:
       ChangeSignalingState(PeerConnectionInterface::kHaveRemoteOffer);
       break;
-    case cricket::BaseSession::STATE_RECEIVEDPRACCEPT:
+    case WebRtcSession::STATE_RECEIVEDPRANSWER:
       ChangeSignalingState(PeerConnectionInterface::kHaveRemotePrAnswer);
       break;
-    case cricket::BaseSession::STATE_SENTACCEPT:
-    case cricket::BaseSession::STATE_RECEIVEDACCEPT:
+    case WebRtcSession::STATE_INPROGRESS:
       ChangeSignalingState(PeerConnectionInterface::kStable);
       break;
-    case cricket::BaseSession::STATE_RECEIVEDTERMINATE:
+    case WebRtcSession::STATE_CLOSED:
       ChangeSignalingState(PeerConnectionInterface::kClosed);
       break;
     default:
diff --git a/talk/app/webrtc/peerconnection.h b/talk/app/webrtc/peerconnection.h
index 0c04898..6a66497 100644
--- a/talk/app/webrtc/peerconnection.h
+++ b/talk/app/webrtc/peerconnection.h
@@ -209,8 +209,7 @@
   void OnIceConnectionReceivingChange(bool receiving) override;
 
   // Signals from WebRtcSession.
-  void OnSessionStateChange(cricket::BaseSession* session,
-                            cricket::BaseSession::State state);
+  void OnSessionStateChange(WebRtcSession* session, WebRtcSession::State state);
   void ChangeSignalingState(SignalingState signaling_state);
 
   rtc::Thread* signaling_thread() const {
diff --git a/talk/app/webrtc/statscollector.cc b/talk/app/webrtc/statscollector.cc
index 9ba7da8..347a846 100644
--- a/talk/app/webrtc/statscollector.cc
+++ b/talk/app/webrtc/statscollector.cc
@@ -70,12 +70,13 @@
 typedef TypeForAdd<int64_t> Int64ForAdd;
 typedef TypeForAdd<int> IntForAdd;
 
-StatsReport::Id GetTransportIdFromProxy(const cricket::ProxyTransportMap& map,
+StatsReport::Id GetTransportIdFromProxy(const ProxyTransportMap& map,
                                         const std::string& proxy) {
   RTC_DCHECK(!proxy.empty());
-  cricket::ProxyTransportMap::const_iterator found = map.find(proxy);
-  if (found == map.end())
+  auto found = map.find(proxy);
+  if (found == map.end()) {
     return StatsReport::Id();
+  }
 
   return StatsReport::NewComponentId(
       found->second, cricket::ICE_CANDIDATE_COMPONENT_RTP);
@@ -677,9 +678,9 @@
   StatsReport* report = reports_.ReplaceOrAddNew(id);
   report->set_timestamp(stats_gathering_started_);
   report->AddBoolean(StatsReport::kStatsValueNameInitiator,
-                     pc_->session()->initiator());
+                     pc_->session()->initial_offerer());
 
-  cricket::SessionStats stats;
+  SessionStats stats;
   if (!pc_->session()->GetTransportStats(&stats)) {
     return;
   }
diff --git a/talk/app/webrtc/statscollector.h b/talk/app/webrtc/statscollector.h
index 714f15a..18a345d 100644
--- a/talk/app/webrtc/statscollector.h
+++ b/talk/app/webrtc/statscollector.h
@@ -156,7 +156,7 @@
   // Raw pointer to the peer connection the statistics are gathered from.
   PeerConnection* const pc_;
   double stats_gathering_started_;
-  cricket::ProxyTransportMap proxy_to_transport_;
+  ProxyTransportMap proxy_to_transport_;
 
   // TODO(tommi): We appear to be holding on to raw pointers to reference
   // counted objects?  We should be using scoped_refptr here.
diff --git a/talk/app/webrtc/statscollector_unittest.cc b/talk/app/webrtc/statscollector_unittest.cc
index 49b992c..8b0a9ed 100644
--- a/talk/app/webrtc/statscollector_unittest.cc
+++ b/talk/app/webrtc/statscollector_unittest.cc
@@ -95,7 +95,7 @@
   // track.
   MOCK_METHOD2(GetLocalTrackIdBySsrc, bool(uint32_t, std::string*));
   MOCK_METHOD2(GetRemoteTrackIdBySsrc, bool(uint32_t, std::string*));
-  MOCK_METHOD1(GetTransportStats, bool(cricket::SessionStats*));
+  MOCK_METHOD1(GetTransportStats, bool(SessionStats*));
   MOCK_METHOD2(GetLocalCertificate,
                bool(const std::string& transport_name,
                     rtc::scoped_refptr<rtc::RTCCertificate>* certificate));
@@ -687,7 +687,7 @@
     transport_stats.transport_name = "audio";
     transport_stats.channel_stats.push_back(channel_stats);
 
-    cricket::SessionStats session_stats;
+    SessionStats session_stats;
     session_stats.transport_stats[transport_stats.transport_name] =
         transport_stats;
 
@@ -763,7 +763,7 @@
   MockWebRtcSession session_;
   MockPeerConnection pc_;
   FakeDataChannelProvider data_channel_provider_;
-  cricket::SessionStats session_stats_;
+  SessionStats session_stats_;
   rtc::scoped_refptr<webrtc::MediaStream> stream_;
   rtc::scoped_refptr<webrtc::VideoTrack> track_;
   rtc::scoped_refptr<FakeAudioTrack> audio_track_;
@@ -1376,7 +1376,7 @@
   transport_stats.transport_name = "audio";
   transport_stats.channel_stats.push_back(channel_stats);
 
-  cricket::SessionStats session_stats;
+  SessionStats session_stats;
   session_stats.transport_stats[transport_stats.transport_name] =
       transport_stats;
 
@@ -1435,7 +1435,7 @@
   transport_stats.transport_name = "audio";
   transport_stats.channel_stats.push_back(channel_stats);
 
-  cricket::SessionStats session_stats;
+  SessionStats session_stats;
   session_stats.transport_stats[transport_stats.transport_name] =
       transport_stats;
 
diff --git a/talk/app/webrtc/webrtcsession.cc b/talk/app/webrtc/webrtcsession.cc
index 1a5751a..f17dd34 100644
--- a/talk/app/webrtc/webrtcsession.cc
+++ b/talk/app/webrtc/webrtcsession.cc
@@ -331,7 +331,11 @@
                    const std::string& reason,
                    std::string* err_desc) {
   std::ostringstream desc;
-  desc << "Failed to set " << source << " " << type << " sdp: " << reason;
+  desc << "Failed to set " << source;
+  if (!type.empty()) {
+    desc << " " << type;
+  }
+  desc << " sdp: " << reason;
 
   if (err_desc) {
     *err_desc = desc.str();
@@ -382,30 +386,21 @@
   return BadSdp(source, SessionDescriptionInterface::kAnswer, reason, err_desc);
 }
 
-#define GET_STRING_OF_STATE(state)  \
-  case cricket::BaseSession::state:  \
-    result = #state;  \
+#define GET_STRING_OF_STATE(state)   \
+  case webrtc::WebRtcSession::state: \
+    result = #state;                 \
     break;
 
-static std::string GetStateString(cricket::BaseSession::State state) {
+static std::string GetStateString(webrtc::WebRtcSession::State state) {
   std::string result;
   switch (state) {
     GET_STRING_OF_STATE(STATE_INIT)
-    GET_STRING_OF_STATE(STATE_SENTINITIATE)
-    GET_STRING_OF_STATE(STATE_RECEIVEDINITIATE)
-    GET_STRING_OF_STATE(STATE_SENTPRACCEPT)
-    GET_STRING_OF_STATE(STATE_SENTACCEPT)
-    GET_STRING_OF_STATE(STATE_RECEIVEDPRACCEPT)
-    GET_STRING_OF_STATE(STATE_RECEIVEDACCEPT)
-    GET_STRING_OF_STATE(STATE_SENTMODIFY)
-    GET_STRING_OF_STATE(STATE_RECEIVEDMODIFY)
-    GET_STRING_OF_STATE(STATE_SENTREJECT)
-    GET_STRING_OF_STATE(STATE_RECEIVEDREJECT)
-    GET_STRING_OF_STATE(STATE_SENTREDIRECT)
-    GET_STRING_OF_STATE(STATE_SENTTERMINATE)
-    GET_STRING_OF_STATE(STATE_RECEIVEDTERMINATE)
+    GET_STRING_OF_STATE(STATE_SENTOFFER)
+    GET_STRING_OF_STATE(STATE_RECEIVEDOFFER)
+    GET_STRING_OF_STATE(STATE_SENTPRANSWER)
+    GET_STRING_OF_STATE(STATE_RECEIVEDPRANSWER)
     GET_STRING_OF_STATE(STATE_INPROGRESS)
-    GET_STRING_OF_STATE(STATE_DEINIT)
+    GET_STRING_OF_STATE(STATE_CLOSED)
     default:
       ASSERT(false);
       break;
@@ -413,22 +408,19 @@
   return result;
 }
 
-#define GET_STRING_OF_ERROR_CODE(err)  \
-  case cricket::BaseSession::err:  \
-    result = #err;  \
+#define GET_STRING_OF_ERROR_CODE(err) \
+  case webrtc::WebRtcSession::err:    \
+    result = #err;                    \
     break;
 
-static std::string GetErrorCodeString(cricket::BaseSession::Error err) {
+static std::string GetErrorCodeString(webrtc::WebRtcSession::Error err) {
   std::string result;
   switch (err) {
     GET_STRING_OF_ERROR_CODE(ERROR_NONE)
-    GET_STRING_OF_ERROR_CODE(ERROR_TIME)
-    GET_STRING_OF_ERROR_CODE(ERROR_RESPONSE)
-    GET_STRING_OF_ERROR_CODE(ERROR_NETWORK)
     GET_STRING_OF_ERROR_CODE(ERROR_CONTENT)
     GET_STRING_OF_ERROR_CODE(ERROR_TRANSPORT)
     default:
-      ASSERT(false);
+      RTC_DCHECK(false);
       break;
   }
   return result;
@@ -541,14 +533,16 @@
                              rtc::Thread* signaling_thread,
                              rtc::Thread* worker_thread,
                              cricket::PortAllocator* port_allocator)
-    : cricket::BaseSession(signaling_thread,
-                           worker_thread,
-                           port_allocator,
-                           rtc::ToString(rtc::CreateRandomId64() & LLONG_MAX),
-                           false),
+    : signaling_thread_(signaling_thread),
+      worker_thread_(worker_thread),
+      port_allocator_(port_allocator),
       // RFC 3264: The numeric value of the session id and version in the
       // o line MUST be representable with a "64 bit signed integer".
       // Due to this constraint session id |sid_| is max limited to LLONG_MAX.
+      sid_(rtc::ToString(rtc::CreateRandomId64() & LLONG_MAX)),
+      transport_controller_(new cricket::TransportController(signaling_thread,
+                                                             worker_thread,
+                                                             port_allocator)),
       channel_manager_(channel_manager),
       ice_observer_(NULL),
       ice_connection_state_(PeerConnectionInterface::kIceConnectionNew),
@@ -558,13 +552,14 @@
       data_channel_type_(cricket::DCT_NONE),
       ice_restart_latch_(new IceRestartAnswerLatch),
       metrics_observer_(NULL) {
-  transport_controller()->SignalConnectionState.connect(
+  transport_controller_->SetIceRole(cricket::ICEROLE_CONTROLLED);
+  transport_controller_->SignalConnectionState.connect(
       this, &WebRtcSession::OnTransportControllerConnectionState);
-  transport_controller()->SignalReceiving.connect(
+  transport_controller_->SignalReceiving.connect(
       this, &WebRtcSession::OnTransportControllerReceiving);
-  transport_controller()->SignalGatheringState.connect(
+  transport_controller_->SignalGatheringState.connect(
       this, &WebRtcSession::OnTransportControllerGatheringState);
-  transport_controller()->SignalCandidatesGathered.connect(
+  transport_controller_->SignalCandidatesGathered.connect(
       this, &WebRtcSession::OnTransportControllerCandidatesGathered);
 }
 
@@ -584,9 +579,8 @@
     SignalDataChannelDestroyed();
     channel_manager_->DestroyDataChannel(data_channel_.release());
   }
-  for (size_t i = 0; i < saved_candidates_.size(); ++i) {
-    delete saved_candidates_[i];
-  }
+
+  LOG(LS_INFO) << "Session: " << id() << " is destroyed.";
 }
 
 bool WebRtcSession::Initialize(
@@ -596,7 +590,7 @@
     const PeerConnectionInterface::RTCConfiguration& rtc_configuration) {
   bundle_policy_ = rtc_configuration.bundle_policy;
   rtcp_mux_policy_ = rtc_configuration.rtcp_mux_policy;
-  transport_controller()->SetSslMaxProtocolVersion(options.ssl_max_version);
+  transport_controller_->SetSslMaxProtocolVersion(options.ssl_max_version);
 
   // Obtain a certificate from RTCConfiguration if any were provided (optional).
   rtc::scoped_refptr<rtc::RTCCertificate> certificate;
@@ -775,18 +769,9 @@
   return true;
 }
 
-cricket::IceConfig WebRtcSession::ParseIceConfig(
-    const PeerConnectionInterface::RTCConfiguration& config) const {
-  cricket::IceConfig ice_config;
-  ice_config.receiving_timeout_ms = config.ice_connection_receiving_timeout;
-  ice_config.gather_continually = (config.continual_gathering_policy ==
-                                   PeerConnectionInterface::GATHER_CONTINUALLY);
-  return ice_config;
-}
-
-void WebRtcSession::Terminate() {
-  SetState(STATE_RECEIVEDTERMINATE);
-  RemoveUnusedChannels(NULL);
+void WebRtcSession::Close() {
+  SetState(STATE_CLOSED);
+  RemoveUnusedChannels(nullptr);
   ASSERT(!voice_channel_);
   ASSERT(!video_channel_);
   ASSERT(!data_channel_);
@@ -801,13 +786,13 @@
 }
 
 bool WebRtcSession::GetSslRole(rtc::SSLRole* role) {
-  if (local_description() == NULL || remote_description() == NULL) {
+  if (!local_desc_ || !remote_desc_) {
     LOG(LS_INFO) << "Local and Remote descriptions must be applied to get "
                  << "SSL Role of the session.";
     return false;
   }
 
-  return transport_controller()->GetSslRole(role);
+  return transport_controller_->GetSslRole(role);
 }
 
 void WebRtcSession::CreateOffer(
@@ -837,10 +822,11 @@
     return false;
   }
 
-  // Update the initiator flag if this session is the initiator.
+  // Update the initial_offerer flag if this session is the initial_offerer.
   Action action = GetAction(desc->type());
   if (state() == STATE_INIT && action == kOffer) {
-    set_initiator(true);
+    initial_offerer_ = true;
+    transport_controller_->SetIceRole(cricket::ICEROLE_CONTROLLING);
   }
 
   cricket::SecurePolicy sdes_policy =
@@ -851,7 +837,6 @@
   // Update the MediaContentDescription crypto settings as per the policy set.
   UpdateSessionDescriptionSecurePolicy(crypto_required, desc->description());
 
-  set_local_description(desc->description()->Copy());
   local_desc_.reset(desc_temp.release());
 
   // Transport and Media channels will be created only when offer is set.
@@ -868,19 +853,12 @@
     return false;
   }
 
-  if (remote_description()) {
-    // Now that we have a local description, we can push down remote candidates
-    // that we stored, and those from the remote description.
-    if (!saved_candidates_.empty()) {
-      // If there are saved candidates which arrived before the local
-      // description was set, copy those to the remote description.
-      CopySavedCandidates(remote_desc_.get());
-    }
-    // Push remote candidates in remote description to transport channels.
+  if (remote_desc_) {
+    // Now that we have a local description, we can push down remote candidates.
     UseCandidatesInSessionDescription(remote_desc_.get());
   }
 
-  if (error() != cricket::BaseSession::ERROR_NONE) {
+  if (error() != ERROR_NONE) {
     return BadLocalSdp(desc->type(), GetSessionErrorMsg(), err_desc);
   }
   return true;
@@ -898,6 +876,10 @@
     return false;
   }
 
+  rtc::scoped_ptr<SessionDescriptionInterface> old_remote_desc(
+      remote_desc_.release());
+  remote_desc_.reset(desc_temp.release());
+
   // Transport and Media channels will be created only when offer is set.
   Action action = GetAction(desc->type());
   if (action == kOffer && !CreateChannels(desc->description())) {
@@ -911,33 +893,31 @@
 
   // NOTE: Candidates allocation will be initiated only when SetLocalDescription
   // is called.
-  set_remote_description(desc->description()->Copy());
   if (!UpdateSessionState(action, cricket::CS_REMOTE, err_desc)) {
     return false;
   }
 
-  if (local_description() && !UseCandidatesInSessionDescription(desc)) {
+  if (local_desc_ && !UseCandidatesInSessionDescription(desc)) {
     return BadRemoteSdp(desc->type(), kInvalidCandidates, err_desc);
   }
 
-  // Copy all saved candidates.
-  CopySavedCandidates(desc);
-
   // Check if this new SessionDescription contains new ice ufrag and password
   // that indicates the remote peer requests ice restart.
   bool ice_restart =
-      ice_restart_latch_->CheckForRemoteIceRestart(remote_desc_.get(), desc);
+      ice_restart_latch_->CheckForRemoteIceRestart(old_remote_desc.get(), desc);
   // We retain all received candidates only if ICE is not restarted.
   // When ICE is restarted, all previous candidates belong to an old generation
   // and should not be kept.
+  // TODO(deadbeef): This goes against the W3C spec which says the remote
+  // description should only contain candidates from the last set remote
+  // description plus any candidates added since then. We should remove this
+  // once we're sure it won't break anything.
   if (!ice_restart) {
     WebRtcSessionDescriptionFactory::CopyCandidatesFromSessionDescription(
-        remote_desc_.get(), desc);
+        old_remote_desc.get(), desc);
   }
 
-  remote_desc_.reset(desc_temp.release());
-
-  if (error() != cricket::BaseSession::ERROR_NONE) {
+  if (error() != ERROR_NONE) {
     return BadRemoteSdp(desc->type(), GetSessionErrorMsg(), err_desc);
   }
 
@@ -956,6 +936,29 @@
   return true;
 }
 
+void WebRtcSession::LogState(State old_state, State new_state) {
+  LOG(LS_INFO) << "Session:" << id()
+               << " Old state:" << GetStateString(old_state)
+               << " New state:" << GetStateString(new_state);
+}
+
+void WebRtcSession::SetState(State state) {
+  ASSERT(signaling_thread_->IsCurrent());
+  if (state != state_) {
+    LogState(state_, state);
+    state_ = state;
+    SignalState(this, state_);
+  }
+}
+
+void WebRtcSession::SetError(Error error, const std::string& error_desc) {
+  ASSERT(signaling_thread_->IsCurrent());
+  if (error != error_) {
+    error_ = error;
+    error_desc_ = error_desc;
+  }
+}
+
 bool WebRtcSession::UpdateSessionState(
     Action action, cricket::ContentSource source,
     std::string* err_desc) {
@@ -963,18 +966,18 @@
 
   // If there's already a pending error then no state transition should happen.
   // But all call-sites should be verifying this before calling us!
-  ASSERT(error() == cricket::BaseSession::ERROR_NONE);
+  ASSERT(error() == ERROR_NONE);
   std::string td_err;
   if (action == kOffer) {
     if (!PushdownTransportDescription(source, cricket::CA_OFFER, &td_err)) {
       return BadOfferSdp(source, MakeTdErrorString(td_err), err_desc);
     }
-    SetState(source == cricket::CS_LOCAL ?
-        STATE_SENTINITIATE : STATE_RECEIVEDINITIATE);
+    SetState(source == cricket::CS_LOCAL ? STATE_SENTOFFER
+                                         : STATE_RECEIVEDOFFER);
     if (!PushdownMediaDescription(cricket::CA_OFFER, source, err_desc)) {
-      SetError(BaseSession::ERROR_CONTENT, *err_desc);
+      SetError(ERROR_CONTENT, *err_desc);
     }
-    if (error() != cricket::BaseSession::ERROR_NONE) {
+    if (error() != ERROR_NONE) {
       return BadOfferSdp(source, GetSessionErrorMsg(), err_desc);
     }
   } else if (action == kPrAnswer) {
@@ -982,12 +985,12 @@
       return BadPranswerSdp(source, MakeTdErrorString(td_err), err_desc);
     }
     EnableChannels();
-    SetState(source == cricket::CS_LOCAL ?
-        STATE_SENTPRACCEPT : STATE_RECEIVEDPRACCEPT);
+    SetState(source == cricket::CS_LOCAL ? STATE_SENTPRANSWER
+                                         : STATE_RECEIVEDPRANSWER);
     if (!PushdownMediaDescription(cricket::CA_PRANSWER, source, err_desc)) {
-      SetError(BaseSession::ERROR_CONTENT, *err_desc);
+      SetError(ERROR_CONTENT, *err_desc);
     }
-    if (error() != cricket::BaseSession::ERROR_NONE) {
+    if (error() != ERROR_NONE) {
       return BadPranswerSdp(source, GetSessionErrorMsg(), err_desc);
     }
   } else if (action == kAnswer) {
@@ -995,11 +998,9 @@
       return BadAnswerSdp(source, MakeTdErrorString(td_err), err_desc);
     }
     const cricket::ContentGroup* local_bundle =
-        BaseSession::local_description()->GetGroupByName(
-            cricket::GROUP_TYPE_BUNDLE);
+        local_desc_->description()->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
     const cricket::ContentGroup* remote_bundle =
-        BaseSession::remote_description()->GetGroupByName(
-            cricket::GROUP_TYPE_BUNDLE);
+        remote_desc_->description()->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
     if (local_bundle && remote_bundle) {
       // The answerer decides the transport to bundle on
       const cricket::ContentGroup* answer_bundle =
@@ -1010,39 +1011,17 @@
       }
     }
     EnableChannels();
-    SetState(source == cricket::CS_LOCAL ?
-        STATE_SENTACCEPT : STATE_RECEIVEDACCEPT);
+    SetState(STATE_INPROGRESS);
     if (!PushdownMediaDescription(cricket::CA_ANSWER, source, err_desc)) {
-      SetError(BaseSession::ERROR_CONTENT, *err_desc);
+      SetError(ERROR_CONTENT, *err_desc);
     }
-    if (error() != cricket::BaseSession::ERROR_NONE) {
+    if (error() != ERROR_NONE) {
       return BadAnswerSdp(source, GetSessionErrorMsg(), err_desc);
     }
   }
   return true;
 }
 
-bool WebRtcSession::PushdownMediaDescription(
-    cricket::ContentAction action,
-    cricket::ContentSource source,
-    std::string* err) {
-  auto set_content = [this, action, source, err](cricket::BaseChannel* ch) {
-    if (!ch) {
-      return true;
-    } else if (source == cricket::CS_LOCAL) {
-      return ch->PushdownLocalDescription(
-          base_local_description(), action, err);
-    } else {
-      return ch->PushdownRemoteDescription(
-          base_remote_description(), action, err);
-    }
-  };
-
-  return (set_content(voice_channel()) &&
-          set_content(video_channel()) &&
-          set_content(data_channel()));
-}
-
 WebRtcSession::Action WebRtcSession::GetAction(const std::string& type) {
   if (type == SessionDescriptionInterface::kOffer) {
     return WebRtcSession::kOffer;
@@ -1055,7 +1034,97 @@
   return WebRtcSession::kOffer;
 }
 
-bool WebRtcSession::GetTransportStats(cricket::SessionStats* stats) {
+bool WebRtcSession::PushdownMediaDescription(
+    cricket::ContentAction action,
+    cricket::ContentSource source,
+    std::string* err) {
+  auto set_content = [this, action, source, err](cricket::BaseChannel* ch) {
+    if (!ch) {
+      return true;
+    } else if (source == cricket::CS_LOCAL) {
+      return ch->PushdownLocalDescription(local_desc_->description(), action,
+                                          err);
+    } else {
+      return ch->PushdownRemoteDescription(remote_desc_->description(), action,
+                                           err);
+    }
+  };
+
+  return (set_content(voice_channel()) &&
+          set_content(video_channel()) &&
+          set_content(data_channel()));
+}
+
+bool WebRtcSession::PushdownTransportDescription(cricket::ContentSource source,
+                                                 cricket::ContentAction action,
+                                                 std::string* error_desc) {
+  RTC_DCHECK(signaling_thread()->IsCurrent());
+
+  if (source == cricket::CS_LOCAL) {
+    return PushdownLocalTransportDescription(local_desc_->description(), action,
+                                             error_desc);
+  }
+  return PushdownRemoteTransportDescription(remote_desc_->description(), action,
+                                            error_desc);
+}
+
+bool WebRtcSession::PushdownLocalTransportDescription(
+    const SessionDescription* sdesc,
+    cricket::ContentAction action,
+    std::string* err) {
+  RTC_DCHECK(signaling_thread()->IsCurrent());
+
+  if (!sdesc) {
+    return false;
+  }
+
+  for (const TransportInfo& tinfo : sdesc->transport_infos()) {
+    if (!transport_controller_->SetLocalTransportDescription(
+            tinfo.content_name, tinfo.description, action, err)) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+bool WebRtcSession::PushdownRemoteTransportDescription(
+    const SessionDescription* sdesc,
+    cricket::ContentAction action,
+    std::string* err) {
+  RTC_DCHECK(signaling_thread()->IsCurrent());
+
+  if (!sdesc) {
+    return false;
+  }
+
+  for (const TransportInfo& tinfo : sdesc->transport_infos()) {
+    if (!transport_controller_->SetRemoteTransportDescription(
+            tinfo.content_name, tinfo.description, action, err)) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+bool WebRtcSession::GetTransportDescription(
+    const SessionDescription* description,
+    const std::string& content_name,
+    cricket::TransportDescription* tdesc) {
+  if (!description || !tdesc) {
+    return false;
+  }
+  const TransportInfo* transport_info =
+      description->GetTransportInfoByName(content_name);
+  if (!transport_info) {
+    return false;
+  }
+  *tdesc = transport_info->description;
+  return true;
+}
+
+bool WebRtcSession::GetTransportStats(SessionStats* stats) {
   ASSERT(signaling_thread()->IsCurrent());
   return (GetChannelTransportStats(voice_channel(), stats) &&
           GetChannelTransportStats(video_channel(), stats) &&
@@ -1063,7 +1132,7 @@
 }
 
 bool WebRtcSession::GetChannelTransportStats(cricket::BaseChannel* ch,
-                                             cricket::SessionStats* stats) {
+                                             SessionStats* stats) {
   ASSERT(signaling_thread()->IsCurrent());
   if (!ch) {
     // Not using this channel.
@@ -1080,7 +1149,7 @@
   }
 
   cricket::TransportStats tstats;
-  if (!transport_controller()->GetStats(transport_name, &tstats)) {
+  if (!transport_controller_->GetStats(transport_name, &tstats)) {
     return false;
   }
 
@@ -1092,14 +1161,14 @@
     const std::string& transport_name,
     rtc::scoped_refptr<rtc::RTCCertificate>* certificate) {
   ASSERT(signaling_thread()->IsCurrent());
-  return transport_controller()->GetLocalCertificate(transport_name,
-                                                     certificate);
+  return transport_controller_->GetLocalCertificate(transport_name,
+                                                    certificate);
 }
 
 bool WebRtcSession::GetRemoteSSLCertificate(const std::string& transport_name,
                                             rtc::SSLCertificate** cert) {
   ASSERT(signaling_thread()->IsCurrent());
-  return transport_controller()->GetRemoteSSLCertificate(transport_name, cert);
+  return transport_controller_->GetRemoteSSLCertificate(transport_name, cert);
 }
 
 cricket::BaseChannel* WebRtcSession::GetChannel(
@@ -1156,37 +1225,35 @@
 }
 
 bool WebRtcSession::ProcessIceMessage(const IceCandidateInterface* candidate) {
-  if (state() == STATE_INIT) {
-     LOG(LS_ERROR) << "ProcessIceMessage: ICE candidates can't be added "
-                   << "without any offer (local or remote) "
-                   << "session description.";
+  if (!remote_desc_) {
+    LOG(LS_ERROR) << "ProcessIceMessage: ICE candidates can't be added "
+                  << "without any remote session description.";
      return false;
   }
 
   if (!candidate) {
-    LOG(LS_ERROR) << "ProcessIceMessage: Candidate is NULL";
+    LOG(LS_ERROR) << "ProcessIceMessage: Candidate is NULL.";
     return false;
   }
 
   bool valid = false;
-  if (!ReadyToUseRemoteCandidate(candidate, NULL, &valid)) {
-    if (valid) {
-      LOG(LS_INFO) << "ProcessIceMessage: Candidate saved";
-      saved_candidates_.push_back(
-          new JsepIceCandidate(candidate->sdp_mid(),
-                               candidate->sdp_mline_index(),
-                               candidate->candidate()));
-    }
-    return valid;
+  bool ready = ReadyToUseRemoteCandidate(candidate, NULL, &valid);
+  if (!valid) {
+    return false;
   }
 
   // Add this candidate to the remote session description.
   if (!remote_desc_->AddCandidate(candidate)) {
-    LOG(LS_ERROR) << "ProcessIceMessage: Candidate cannot be used";
+    LOG(LS_ERROR) << "ProcessIceMessage: Candidate cannot be used.";
     return false;
   }
 
-  return UseCandidate(candidate);
+  if (ready) {
+    return UseCandidate(candidate);
+  } else {
+    LOG(LS_INFO) << "ProcessIceMessage: Not ready to use candidate.";
+    return true;
+  }
 }
 
 bool WebRtcSession::SetIceTransports(
@@ -1195,18 +1262,37 @@
         ConvertIceTransportTypeToCandidateFilter(type));
 }
 
+cricket::IceConfig WebRtcSession::ParseIceConfig(
+    const PeerConnectionInterface::RTCConfiguration& config) const {
+  cricket::IceConfig ice_config;
+  ice_config.receiving_timeout_ms = config.ice_connection_receiving_timeout;
+  ice_config.gather_continually = (config.continual_gathering_policy ==
+                                   PeerConnectionInterface::GATHER_CONTINUALLY);
+  return ice_config;
+}
+
+void WebRtcSession::SetIceConfig(const cricket::IceConfig& config) {
+  transport_controller_->SetIceConfig(config);
+}
+
+void WebRtcSession::MaybeStartGathering() {
+  transport_controller_->MaybeStartGathering();
+}
+
 bool WebRtcSession::GetLocalTrackIdBySsrc(uint32_t ssrc,
                                           std::string* track_id) {
-  if (!base_local_description())
+  if (!local_desc_) {
     return false;
-  return webrtc::GetTrackIdBySsrc(base_local_description(), ssrc, track_id);
+  }
+  return webrtc::GetTrackIdBySsrc(local_desc_->description(), ssrc, track_id);
 }
 
 bool WebRtcSession::GetRemoteTrackIdBySsrc(uint32_t ssrc,
                                            std::string* track_id) {
-  if (!base_remote_description())
+  if (!remote_desc_) {
     return false;
-  return webrtc::GetTrackIdBySsrc(base_remote_description(), ssrc, track_id);
+  }
+  return webrtc::GetTrackIdBySsrc(remote_desc_->description(), ssrc, track_id);
 }
 
 std::string WebRtcSession::BadStateErrMsg(State state) {
@@ -1317,7 +1403,8 @@
   uint32_t send_ssrc = 0;
   // The Dtmf is negotiated per channel not ssrc, so we only check if the ssrc
   // exists.
-  if (!GetAudioSsrcByTrackId(base_local_description(), track_id,
+  if (!local_desc_ ||
+      !GetAudioSsrcByTrackId(local_desc_->description(), track_id,
                              &send_ssrc)) {
     LOG(LS_ERROR) << "CanInsertDtmf: Track does not exist: " << track_id;
     return false;
@@ -1333,8 +1420,8 @@
     return false;
   }
   uint32_t send_ssrc = 0;
-  if (!VERIFY(GetAudioSsrcByTrackId(base_local_description(),
-                                    track_id, &send_ssrc))) {
+  if (!VERIFY(local_desc_ && GetAudioSsrcByTrackId(local_desc_->description(),
+                                                   track_id, &send_ssrc))) {
     LOG(LS_ERROR) << "InsertDtmf: Track does not exist: " << track_id;
     return false;
   }
@@ -1421,7 +1508,7 @@
 
 void WebRtcSession::OnCertificateReady(
     const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
-  transport_controller()->SetLocalCertificate(certificate);
+  transport_controller_->SetLocalCertificate(certificate);
 }
 
 bool WebRtcSession::waiting_for_certificate_for_testing() const {
@@ -1430,7 +1517,7 @@
 
 const rtc::scoped_refptr<rtc::RTCCertificate>&
 WebRtcSession::certificate_for_testing() {
-  return transport_controller()->certificate_for_testing();
+  return transport_controller_->certificate_for_testing();
 }
 
 void WebRtcSession::SetIceConnectionState(
@@ -1583,11 +1670,12 @@
 // Returns the media index for a local ice candidate given the content name.
 bool WebRtcSession::GetLocalCandidateMediaIndex(const std::string& content_name,
                                                 int* sdp_mline_index) {
-  if (!base_local_description() || !sdp_mline_index)
+  if (!local_desc_ || !sdp_mline_index) {
     return false;
+  }
 
   bool content_found = false;
-  const ContentInfos& contents = base_local_description()->contents();
+  const ContentInfos& contents = local_desc_->description()->contents();
   for (size_t index = 0; index < contents.size(); ++index) {
     if (contents[index].name == content_name) {
       *sdp_mline_index = static_cast<int>(index);
@@ -1600,28 +1688,27 @@
 
 bool WebRtcSession::UseCandidatesInSessionDescription(
     const SessionDescriptionInterface* remote_desc) {
-  if (!remote_desc)
+  if (!remote_desc) {
     return true;
+  }
   bool ret = true;
 
   for (size_t m = 0; m < remote_desc->number_of_mediasections(); ++m) {
     const IceCandidateCollection* candidates = remote_desc->candidates(m);
-    for  (size_t n = 0; n < candidates->count(); ++n) {
+    for (size_t n = 0; n < candidates->count(); ++n) {
       const IceCandidateInterface* candidate = candidates->at(n);
       bool valid = false;
       if (!ReadyToUseRemoteCandidate(candidate, remote_desc, &valid)) {
         if (valid) {
-          LOG(LS_INFO) << "UseCandidatesInSessionDescription: Candidate saved.";
-          saved_candidates_.push_back(
-              new JsepIceCandidate(candidate->sdp_mid(),
-                                   candidate->sdp_mline_index(),
-                                   candidate->candidate()));
+          LOG(LS_INFO) << "UseCandidatesInSessionDescription: Not ready to use "
+                       << "candidate.";
         }
         continue;
       }
       ret = UseCandidate(candidate);
-      if (!ret)
+      if (!ret) {
         break;
+      }
     }
   }
   return ret;
@@ -1631,7 +1718,7 @@
     const IceCandidateInterface* candidate) {
 
   size_t mediacontent_index = static_cast<size_t>(candidate->sdp_mline_index());
-  size_t remote_content_size = base_remote_description()->contents().size();
+  size_t remote_content_size = remote_desc_->description()->contents().size();
   if (mediacontent_index >= remote_content_size) {
     LOG(LS_ERROR)
         << "UseRemoteCandidateInSession: Invalid candidate media index.";
@@ -1639,13 +1726,13 @@
   }
 
   cricket::ContentInfo content =
-      base_remote_description()->contents()[mediacontent_index];
+      remote_desc_->description()->contents()[mediacontent_index];
   std::vector<cricket::Candidate> candidates;
   candidates.push_back(candidate->candidate());
   // Invoking BaseSession method to handle remote candidates.
   std::string error;
-  if (transport_controller()->AddRemoteCandidates(content.name, candidates,
-                                                  &error)) {
+  if (transport_controller_->AddRemoteCandidates(content.name, candidates,
+                                                 &error)) {
     // Candidates successfully submitted for checking.
     if (ice_connection_state_ == PeerConnectionInterface::kIceConnectionNew ||
         ice_connection_state_ ==
@@ -1757,7 +1844,7 @@
 
 bool WebRtcSession::CreateVoiceChannel(const cricket::ContentInfo* content) {
   voice_channel_.reset(channel_manager_->CreateVoiceChannel(
-      media_controller_.get(), transport_controller(), content->name, true,
+      media_controller_.get(), transport_controller_.get(), content->name, true,
       audio_options_));
   if (!voice_channel_) {
     return false;
@@ -1772,7 +1859,7 @@
 
 bool WebRtcSession::CreateVideoChannel(const cricket::ContentInfo* content) {
   video_channel_.reset(channel_manager_->CreateVideoChannel(
-      media_controller_.get(), transport_controller(), content->name, true,
+      media_controller_.get(), transport_controller_.get(), content->name, true,
       video_options_));
   if (!video_channel_) {
     return false;
@@ -1788,7 +1875,7 @@
 bool WebRtcSession::CreateDataChannel(const cricket::ContentInfo* content) {
   bool sctp = (data_channel_type_ == cricket::DCT_SCTP);
   data_channel_.reset(channel_manager_->CreateDataChannel(
-      transport_controller(), content->name, !sctp, data_channel_type_));
+      transport_controller_.get(), content->name, !sctp, data_channel_type_));
   if (!data_channel_) {
     return false;
   }
@@ -1806,21 +1893,8 @@
 }
 
 void WebRtcSession::OnDtlsSetupFailure(cricket::BaseChannel*, bool rtcp) {
-  SetError(BaseSession::ERROR_TRANSPORT, rtcp ? kDtlsSetupFailureRtcp :
-           kDtlsSetupFailureRtp);
-}
-
-void WebRtcSession::CopySavedCandidates(
-    SessionDescriptionInterface* dest_desc) {
-  if (!dest_desc) {
-    ASSERT(false);
-    return;
-  }
-  for (size_t i = 0; i < saved_candidates_.size(); ++i) {
-    dest_desc->AddCandidate(saved_candidates_[i]);
-    delete saved_candidates_[i];
-  }
-  saved_candidates_.clear();
+  SetError(ERROR_TRANSPORT,
+           rtcp ? kDtlsSetupFailureRtcp : kDtlsSetupFailureRtp);
 }
 
 void WebRtcSession::OnDataChannelMessageReceived(
@@ -1881,7 +1955,7 @@
     const SessionDescriptionInterface* sdesc,
     cricket::ContentSource source, std::string* err_desc) {
   std::string type;
-  if (error() != cricket::BaseSession::ERROR_NONE) {
+  if (error() != ERROR_NONE) {
     return BadSdp(source, type, GetSessionErrorMsg(), err_desc);
   }
 
@@ -1919,8 +1993,8 @@
   // Verify m-lines in Answer when compared against Offer.
   if (action == kAnswer) {
     const cricket::SessionDescription* offer_desc =
-        (source == cricket::CS_LOCAL) ? remote_description()->description() :
-            local_description()->description();
+        (source == cricket::CS_LOCAL) ? remote_desc_->description()
+                                      : local_desc_->description();
     if (!VerifyMediaDescriptions(sdesc->description(), offer_desc)) {
       return BadAnswerSdp(source, kMlineMismatch, err_desc);
     }
@@ -1932,31 +2006,27 @@
 bool WebRtcSession::ExpectSetLocalDescription(Action action) {
   return ((action == kOffer && state() == STATE_INIT) ||
           // update local offer
-          (action == kOffer && state() == STATE_SENTINITIATE) ||
+          (action == kOffer && state() == STATE_SENTOFFER) ||
           // update the current ongoing session.
-          (action == kOffer && state() == STATE_RECEIVEDACCEPT) ||
-          (action == kOffer && state() == STATE_SENTACCEPT) ||
           (action == kOffer && state() == STATE_INPROGRESS) ||
           // accept remote offer
-          (action == kAnswer && state() == STATE_RECEIVEDINITIATE) ||
-          (action == kAnswer && state() == STATE_SENTPRACCEPT) ||
-          (action == kPrAnswer && state() == STATE_RECEIVEDINITIATE) ||
-          (action == kPrAnswer && state() == STATE_SENTPRACCEPT));
+          (action == kAnswer && state() == STATE_RECEIVEDOFFER) ||
+          (action == kAnswer && state() == STATE_SENTPRANSWER) ||
+          (action == kPrAnswer && state() == STATE_RECEIVEDOFFER) ||
+          (action == kPrAnswer && state() == STATE_SENTPRANSWER));
 }
 
 bool WebRtcSession::ExpectSetRemoteDescription(Action action) {
   return ((action == kOffer && state() == STATE_INIT) ||
           // update remote offer
-          (action == kOffer && state() == STATE_RECEIVEDINITIATE) ||
+          (action == kOffer && state() == STATE_RECEIVEDOFFER) ||
           // update the current ongoing session
-          (action == kOffer && state() == STATE_RECEIVEDACCEPT) ||
-          (action == kOffer && state() == STATE_SENTACCEPT) ||
           (action == kOffer && state() == STATE_INPROGRESS) ||
           // accept local offer
-          (action == kAnswer && state() == STATE_SENTINITIATE) ||
-          (action == kAnswer && state() == STATE_RECEIVEDPRACCEPT) ||
-          (action == kPrAnswer && state() == STATE_SENTINITIATE) ||
-          (action == kPrAnswer && state() == STATE_RECEIVEDPRACCEPT));
+          (action == kAnswer && state() == STATE_SENTOFFER) ||
+          (action == kAnswer && state() == STATE_RECEIVEDPRANSWER) ||
+          (action == kPrAnswer && state() == STATE_SENTOFFER) ||
+          (action == kPrAnswer && state() == STATE_RECEIVEDPRANSWER));
 }
 
 std::string WebRtcSession::GetSessionErrorMsg() {
@@ -1978,10 +2048,11 @@
   *valid = true;;
 
   const SessionDescriptionInterface* current_remote_desc =
-      remote_desc ? remote_desc : remote_description();
+      remote_desc ? remote_desc : remote_desc_.get();
 
-  if (!current_remote_desc)
+  if (!current_remote_desc) {
     return false;
+  }
 
   size_t mediacontent_index =
       static_cast<size_t>(candidate->sdp_mline_index());
@@ -2002,7 +2073,7 @@
     return false;
   }
 
-  return transport_controller()->ReadyForRemoteCandidates(
+  return transport_controller_->ReadyForRemoteCandidates(
       channel->transport_name());
 }
 
@@ -2038,7 +2109,7 @@
   }
   for (const auto& name : transport_names) {
     cricket::TransportStats stats;
-    if (transport_controller()->GetStats(name, &stats)) {
+    if (transport_controller_->GetStats(name, &stats)) {
       ReportBestConnectionState(stats);
       ReportNegotiatedCiphers(stats);
     }
diff --git a/talk/app/webrtc/webrtcsession.h b/talk/app/webrtc/webrtcsession.h
index 8dcc85f..f3dd602 100644
--- a/talk/app/webrtc/webrtcsession.h
+++ b/talk/app/webrtc/webrtcsession.h
@@ -38,7 +38,7 @@
 #include "talk/app/webrtc/peerconnectioninterface.h"
 #include "talk/app/webrtc/statstypes.h"
 #include "talk/media/base/mediachannel.h"
-#include "webrtc/p2p/base/session.h"
+#include "webrtc/p2p/base/transportcontroller.h"
 #include "talk/session/media/mediasession.h"
 #include "webrtc/base/sigslot.h"
 #include "webrtc/base/sslidentity.h"
@@ -46,7 +46,6 @@
 
 namespace cricket {
 
-class BaseChannel;
 class ChannelManager;
 class DataChannel;
 class StatsReport;
@@ -112,26 +111,80 @@
   RTC_DISALLOW_COPY_AND_ASSIGN(IceObserver);
 };
 
-class WebRtcSession : public cricket::BaseSession,
-                      public AudioProviderInterface,
+// Statistics for all the transports of the session.
+typedef std::map<std::string, cricket::TransportStats> TransportStatsMap;
+typedef std::map<std::string, std::string> ProxyTransportMap;
+
+// TODO(pthatcher): Think of a better name for this.  We already have
+// a TransportStats in transport.h.  Perhaps TransportsStats?
+struct SessionStats {
+  ProxyTransportMap proxy_to_transport;
+  TransportStatsMap transport_stats;
+};
+
+// A WebRtcSession manages general session state. This includes negotiation
+// of both the application-level and network-level protocols:  the former
+// defines what will be sent and the latter defines how it will be sent.  Each
+// network-level protocol is represented by a Transport object.  Each Transport
+// participates in the network-level negotiation.  The individual streams of
+// packets are represented by TransportChannels.  The application-level protocol
+// is represented by SessionDecription objects.
+class WebRtcSession : public AudioProviderInterface,
                       public VideoProviderInterface,
                       public DtmfProviderInterface,
-                      public DataChannelProviderInterface {
+                      public DataChannelProviderInterface,
+                      public sigslot::has_slots<> {
  public:
+  enum State {
+    STATE_INIT = 0,
+    STATE_SENTOFFER,         // Sent offer, waiting for answer.
+    STATE_RECEIVEDOFFER,     // Received an offer. Need to send answer.
+    STATE_SENTPRANSWER,      // Sent provisional answer. Need to send answer.
+    STATE_RECEIVEDPRANSWER,  // Received provisional answer, waiting for answer.
+    STATE_INPROGRESS,        // Offer/answer exchange completed.
+    STATE_CLOSED,            // Close() was called.
+  };
+
+  enum Error {
+    ERROR_NONE = 0,       // no error
+    ERROR_CONTENT = 1,    // channel errors in SetLocalContent/SetRemoteContent
+    ERROR_TRANSPORT = 2,  // transport error of some kind
+  };
+
   WebRtcSession(cricket::ChannelManager* channel_manager,
                 rtc::Thread* signaling_thread,
                 rtc::Thread* worker_thread,
                 cricket::PortAllocator* port_allocator);
   virtual ~WebRtcSession();
 
+  // These are const to allow them to be called from const methods.
+  rtc::Thread* signaling_thread() const { return signaling_thread_; }
+  rtc::Thread* worker_thread() const { return worker_thread_; }
+  cricket::PortAllocator* port_allocator() const { return port_allocator_; }
+
+  // The ID of this session.
+  const std::string& id() const { return sid_; }
+
   bool Initialize(
       const PeerConnectionFactoryInterface::Options& options,
       const MediaConstraintsInterface* constraints,
       rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store,
       const PeerConnectionInterface::RTCConfiguration& rtc_configuration);
   // Deletes the voice, video and data channel and changes the session state
-  // to STATE_RECEIVEDTERMINATE.
-  void Terminate();
+  // to STATE_CLOSED.
+  void Close();
+
+  // Returns true if we were the initial offerer.
+  bool initial_offerer() const { return initial_offerer_; }
+
+  // Returns the current state of the session. See the enum above for details.
+  // Each time the state changes, we will fire this signal.
+  State state() const { return state_; }
+  sigslot::signal2<WebRtcSession*, State> SignalState;
+
+  // Returns the last error in the session. See the enum above for details.
+  Error error() const { return error_; }
+  const std::string& error_desc() const { return error_desc_; }
 
   void RegisterIceObserver(IceObserver* observer) {
     ice_observer_ = observer;
@@ -153,10 +206,6 @@
   // Get current ssl role from transport.
   bool GetSslRole(rtc::SSLRole* role);
 
-  // Generic error message callback from WebRtcSession.
-  // TODO - It may be necessary to supply error code as well.
-  sigslot::signal0<> SignalError;
-
   void CreateOffer(
       CreateSessionDescriptionObserver* observer,
       const PeerConnectionInterface::RTCOfferAnswerOptions& options,
@@ -177,21 +226,18 @@
   cricket::IceConfig ParseIceConfig(
       const PeerConnectionInterface::RTCConfiguration& config) const;
 
+  void SetIceConfig(const cricket::IceConfig& ice_config);
+
+  // Start gathering candidates for any new transports, or transports doing an
+  // ICE restart.
+  void MaybeStartGathering();
+
   const SessionDescriptionInterface* local_description() const {
     return local_desc_.get();
   }
   const SessionDescriptionInterface* remote_description() const {
     return remote_desc_.get();
   }
-  // TODO(pthatcher): Cleanup the distinction between
-  // SessionDescription and SessionDescriptionInterface and remove
-  // these if possible.
-  const cricket::SessionDescription* base_local_description() const {
-    return BaseSession::local_description();
-  }
-  const cricket::SessionDescription* base_remote_description() const {
-    return BaseSession::remote_description();
-  }
 
   // Get the id used as a media stream track's "id" field from ssrc.
   virtual bool GetLocalTrackIdBySsrc(uint32_t ssrc, std::string* track_id);
@@ -232,11 +278,10 @@
 
   // Returns stats for all channels of all transports.
   // This avoids exposing the internal structures used to track them.
-  virtual bool GetTransportStats(cricket::SessionStats* stats);
+  virtual bool GetTransportStats(SessionStats* stats);
 
   // Get stats for a specific channel
-  bool GetChannelTransportStats(cricket::BaseChannel* ch,
-                                cricket::SessionStats* stats);
+  bool GetChannelTransportStats(cricket::BaseChannel* ch, SessionStats* stats);
 
   // virtual so it can be mocked in unit tests
   virtual bool GetLocalCertificate(
@@ -291,6 +336,16 @@
     kAnswer,
   };
 
+  // Log session state.
+  void LogState(State old_state, State new_state);
+
+  // Updates the state, signaling if necessary.
+  virtual void SetState(State state);
+
+  // Updates the error state, signaling if necessary.
+  // TODO(ronghuawu): remove the SetError method that doesn't take |error_desc|.
+  virtual void SetError(Error error, const std::string& error_desc);
+
   bool UpdateSessionState(Action action, cricket::ContentSource source,
                           std::string* err_desc);
   static Action GetAction(const std::string& type);
@@ -300,6 +355,27 @@
                                 cricket::ContentSource source,
                                 std::string* error_desc);
 
+  bool PushdownTransportDescription(cricket::ContentSource source,
+                                    cricket::ContentAction action,
+                                    std::string* error_desc);
+
+  // Helper methods to push local and remote transport descriptions.
+  bool PushdownLocalTransportDescription(
+      const cricket::SessionDescription* sdesc,
+      cricket::ContentAction action,
+      std::string* error_desc);
+  bool PushdownRemoteTransportDescription(
+      const cricket::SessionDescription* sdesc,
+      cricket::ContentAction action,
+      std::string* error_desc);
+
+  // Returns true and the TransportInfo of the given |content_name|
+  // from |description|. Returns false if it's not available.
+  static bool GetTransportDescription(
+      const cricket::SessionDescription* description,
+      const std::string& content_name,
+      cricket::TransportDescription* info);
+
   cricket::BaseChannel* GetChannel(const std::string& content_name);
   // Cause all the BaseChannels in the bundle group to have the same
   // transport channel.
@@ -331,10 +407,6 @@
   bool CreateVideoChannel(const cricket::ContentInfo* content);
   bool CreateDataChannel(const cricket::ContentInfo* content);
 
-  // Copy the candidates from |saved_candidates_| to |dest_desc|.
-  // The |saved_candidates_| will be cleared after this function call.
-  void CopySavedCandidates(SessionDescriptionInterface* dest_desc);
-
   // Listens to SCTP CONTROL messages on unused SIDs and process them as OPEN
   // messages.
   void OnDataChannelMessageReceived(cricket::DataChannel* channel,
@@ -386,6 +458,18 @@
 
   void ReportNegotiatedCiphers(const cricket::TransportStats& stats);
 
+  rtc::Thread* const signaling_thread_;
+  rtc::Thread* const worker_thread_;
+  cricket::PortAllocator* const port_allocator_;
+
+  State state_ = STATE_INIT;
+  Error error_ = ERROR_NONE;
+  std::string error_desc_;
+
+  const std::string sid_;
+  bool initial_offerer_ = false;
+
+  rtc::scoped_ptr<cricket::TransportController> transport_controller_;
   rtc::scoped_ptr<MediaControllerInterface> media_controller_;
   rtc::scoped_ptr<cricket::VoiceChannel> voice_channel_;
   rtc::scoped_ptr<cricket::VideoChannel> video_channel_;
@@ -396,8 +480,6 @@
   bool ice_connection_receiving_;
   rtc::scoped_ptr<SessionDescriptionInterface> local_desc_;
   rtc::scoped_ptr<SessionDescriptionInterface> remote_desc_;
-  // Candidates that arrived before the remote description was set.
-  std::vector<IceCandidateInterface*> saved_candidates_;
   // If the remote peer is using a older version of implementation.
   bool older_version_remote_peer_;
   bool dtls_enabled_;
diff --git a/talk/app/webrtc/webrtcsession_unittest.cc b/talk/app/webrtc/webrtcsession_unittest.cc
index f0558ee..f998ca8 100644
--- a/talk/app/webrtc/webrtcsession_unittest.cc
+++ b/talk/app/webrtc/webrtcsession_unittest.cc
@@ -70,7 +70,6 @@
     return;                                         \
   }
 
-using cricket::BaseSession;
 using cricket::DF_PLAY;
 using cricket::DF_SEND;
 using cricket::FakeVoiceMediaChannel;
@@ -92,6 +91,7 @@
 using webrtc::PeerConnectionFactoryInterface;
 using webrtc::PeerConnectionInterface;
 using webrtc::SessionDescriptionInterface;
+using webrtc::SessionStats;
 using webrtc::StreamCollection;
 using webrtc::WebRtcSession;
 using webrtc::kBundleWithoutRtcpMux;
@@ -857,7 +857,7 @@
     session_->MaybeStartGathering();
   }
   void SetLocalDescriptionExpectState(SessionDescriptionInterface* desc,
-                                      BaseSession::State expected_state) {
+                                      WebRtcSession::State expected_state) {
     SetLocalDescriptionWithoutError(desc);
     EXPECT_EQ(expected_state, session_->state());
   }
@@ -885,7 +885,7 @@
     EXPECT_TRUE(session_->SetRemoteDescription(desc, NULL));
   }
   void SetRemoteDescriptionExpectState(SessionDescriptionInterface* desc,
-                                       BaseSession::State expected_state) {
+                                       WebRtcSession::State expected_state) {
     SetRemoteDescriptionWithoutError(desc);
     EXPECT_EQ(expected_state, session_->state());
   }
@@ -1946,8 +1946,8 @@
   SessionDescriptionInterface* offer = CreateOffer();
   SetLocalDescriptionWithoutError(offer);
   offer = CreateOffer();
-  SetRemoteDescriptionOfferExpectError(
-      "Called in wrong state: STATE_SENTINITIATE", offer);
+  SetRemoteDescriptionOfferExpectError("Called in wrong state: STATE_SENTOFFER",
+                                       offer);
 }
 
 TEST_F(WebRtcSessionTest, TestSetRemoteAndLocalOffer) {
@@ -1957,44 +1957,44 @@
   SetRemoteDescriptionWithoutError(offer);
   offer = CreateOffer();
   SetLocalDescriptionOfferExpectError(
-      "Called in wrong state: STATE_RECEIVEDINITIATE", offer);
+      "Called in wrong state: STATE_RECEIVEDOFFER", offer);
 }
 
 TEST_F(WebRtcSessionTest, TestSetLocalPrAnswer) {
   Init();
   SendNothing();
   SessionDescriptionInterface* offer = CreateRemoteOffer();
-  SetRemoteDescriptionExpectState(offer, BaseSession::STATE_RECEIVEDINITIATE);
+  SetRemoteDescriptionExpectState(offer, WebRtcSession::STATE_RECEIVEDOFFER);
 
   JsepSessionDescription* pranswer = static_cast<JsepSessionDescription*>(
       CreateAnswer(NULL));
   pranswer->set_type(SessionDescriptionInterface::kPrAnswer);
-  SetLocalDescriptionExpectState(pranswer, BaseSession::STATE_SENTPRACCEPT);
+  SetLocalDescriptionExpectState(pranswer, WebRtcSession::STATE_SENTPRANSWER);
 
   SendAudioVideoStream1();
   JsepSessionDescription* pranswer2 = static_cast<JsepSessionDescription*>(
       CreateAnswer(NULL));
   pranswer2->set_type(SessionDescriptionInterface::kPrAnswer);
 
-  SetLocalDescriptionExpectState(pranswer2, BaseSession::STATE_SENTPRACCEPT);
+  SetLocalDescriptionExpectState(pranswer2, WebRtcSession::STATE_SENTPRANSWER);
 
   SendAudioVideoStream2();
   SessionDescriptionInterface* answer = CreateAnswer(NULL);
-  SetLocalDescriptionExpectState(answer, BaseSession::STATE_SENTACCEPT);
+  SetLocalDescriptionExpectState(answer, WebRtcSession::STATE_INPROGRESS);
 }
 
 TEST_F(WebRtcSessionTest, TestSetRemotePrAnswer) {
   Init();
   SendNothing();
   SessionDescriptionInterface* offer = CreateOffer();
-  SetLocalDescriptionExpectState(offer, BaseSession::STATE_SENTINITIATE);
+  SetLocalDescriptionExpectState(offer, WebRtcSession::STATE_SENTOFFER);
 
   JsepSessionDescription* pranswer =
       CreateRemoteAnswer(session_->local_description());
   pranswer->set_type(SessionDescriptionInterface::kPrAnswer);
 
   SetRemoteDescriptionExpectState(pranswer,
-                                  BaseSession::STATE_RECEIVEDPRACCEPT);
+                                  WebRtcSession::STATE_RECEIVEDPRANSWER);
 
   SendAudioVideoStream1();
   JsepSessionDescription* pranswer2 =
@@ -2002,12 +2002,12 @@
   pranswer2->set_type(SessionDescriptionInterface::kPrAnswer);
 
   SetRemoteDescriptionExpectState(pranswer2,
-                                  BaseSession::STATE_RECEIVEDPRACCEPT);
+                                  WebRtcSession::STATE_RECEIVEDPRANSWER);
 
   SendAudioVideoStream2();
   SessionDescriptionInterface* answer =
       CreateRemoteAnswer(session_->local_description());
-  SetRemoteDescriptionExpectState(answer, BaseSession::STATE_RECEIVEDACCEPT);
+  SetRemoteDescriptionExpectState(answer, WebRtcSession::STATE_INPROGRESS);
 }
 
 TEST_F(WebRtcSessionTest, TestSetLocalAnswerWithoutOffer) {
@@ -2040,21 +2040,24 @@
   candidate.set_component(1);
   JsepIceCandidate ice_candidate1(kMediaContentName0, 0, candidate);
 
-  // Fail since we have not set a offer description.
+  // Fail since we have not set a remote description.
   EXPECT_FALSE(session_->ProcessIceMessage(&ice_candidate1));
 
   SessionDescriptionInterface* offer = CreateOffer();
   SetLocalDescriptionWithoutError(offer);
-  // Candidate should be allowed to add before remote description.
-  EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
-  candidate.set_component(2);
-  JsepIceCandidate ice_candidate2(kMediaContentName0, 0, candidate);
-  EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2));
+
+  // Fail since we have not set a remote description.
+  EXPECT_FALSE(session_->ProcessIceMessage(&ice_candidate1));
 
   SessionDescriptionInterface* answer = CreateRemoteAnswer(
       session_->local_description());
   SetRemoteDescriptionWithoutError(answer);
 
+  EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1));
+  candidate.set_component(2);
+  JsepIceCandidate ice_candidate2(kMediaContentName0, 0, candidate);
+  EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2));
+
   // Verifying the candidates are copied properly from internal vector.
   const SessionDescriptionInterface* remote_desc =
       session_->remote_description();
@@ -2231,8 +2234,9 @@
   rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer());
 
   // CreateOffer creates session description with the content names "audio" and
-  // "video". Goal is to modify these content names and verify transport channel
-  // proxy in the BaseSession, as proxies are created with the content names
+  // "video". Goal is to modify these content names and verify transport
+  // channels
+  // in the WebRtcSession, as channels are created with the content names
   // present in SDP.
   std::string sdp;
   EXPECT_TRUE(offer->ToString(&sdp));
@@ -2812,7 +2816,7 @@
 }
 
 // Test that candidates sent to the "video" transport do not get pushed down to
-// the "audio" transport channel when bundling using TransportProxy.
+// the "audio" transport channel when bundling.
 TEST_F(WebRtcSessionTest, TestIgnoreCandidatesForUnusedTransportWhenBundling) {
   AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort));
 
@@ -2837,7 +2841,7 @@
   // Checks if one of the transport channels contains a connection using a given
   // port.
   auto connection_with_remote_port = [this, voice_channel](int port) {
-    cricket::SessionStats stats;
+    SessionStats stats;
     session_->GetChannelTransportStats(voice_channel, &stats);
     for (auto& kv : stats.transport_stats) {
       for (auto& chan_stat : kv.second.channel_stats) {
@@ -2996,14 +3000,14 @@
       CreateRemoteAnswer(session_->local_description(), recv_options);
   SetRemoteDescriptionWithoutError(answer);
 
-  EXPECT_TRUE(NULL == session_->voice_channel());
-  EXPECT_TRUE(NULL != session_->video_rtp_transport_channel());
+  EXPECT_TRUE(nullptr == session_->voice_channel());
+  EXPECT_TRUE(nullptr != session_->video_rtp_transport_channel());
 
-  session_->Terminate();
-  EXPECT_TRUE(NULL == session_->voice_rtp_transport_channel());
-  EXPECT_TRUE(NULL == session_->voice_rtcp_transport_channel());
-  EXPECT_TRUE(NULL == session_->video_rtp_transport_channel());
-  EXPECT_TRUE(NULL == session_->video_rtcp_transport_channel());
+  session_->Close();
+  EXPECT_TRUE(nullptr == session_->voice_rtp_transport_channel());
+  EXPECT_TRUE(nullptr == session_->voice_rtcp_transport_channel());
+  EXPECT_TRUE(nullptr == session_->video_rtp_transport_channel());
+  EXPECT_TRUE(nullptr == session_->video_rtcp_transport_channel());
 }
 
 // kBundlePolicyMaxBundle policy but no BUNDLE in the answer.
@@ -3349,29 +3353,30 @@
                               expected_duration, expected_flags));
 }
 
-// This test verifies the |initiator| flag when session initiates the call.
+// This test verifies the |initial_offerer| flag when session initiates the
+// call.
 TEST_F(WebRtcSessionTest, TestInitiatorFlagAsOriginator) {
   Init();
-  EXPECT_FALSE(session_->initiator());
+  EXPECT_FALSE(session_->initial_offerer());
   SessionDescriptionInterface* offer = CreateOffer();
   SessionDescriptionInterface* answer = CreateRemoteAnswer(offer);
   SetLocalDescriptionWithoutError(offer);
-  EXPECT_TRUE(session_->initiator());
+  EXPECT_TRUE(session_->initial_offerer());
   SetRemoteDescriptionWithoutError(answer);
-  EXPECT_TRUE(session_->initiator());
+  EXPECT_TRUE(session_->initial_offerer());
 }
 
-// This test verifies the |initiator| flag when session receives the call.
+// This test verifies the |initial_offerer| flag when session receives the call.
 TEST_F(WebRtcSessionTest, TestInitiatorFlagAsReceiver) {
   Init();
-  EXPECT_FALSE(session_->initiator());
+  EXPECT_FALSE(session_->initial_offerer());
   SessionDescriptionInterface* offer = CreateRemoteOffer();
   SetRemoteDescriptionWithoutError(offer);
   SessionDescriptionInterface* answer = CreateAnswer(NULL);
 
-  EXPECT_FALSE(session_->initiator());
+  EXPECT_FALSE(session_->initial_offerer());
   SetLocalDescriptionWithoutError(answer);
-  EXPECT_FALSE(session_->initiator());
+  EXPECT_FALSE(session_->initial_offerer());
 }
 
 // Verifing local offer and remote answer have matching m-lines as per RFC 3264.
@@ -3583,10 +3588,17 @@
   video_channel_ = media_engine_->GetVideoChannel(0);
   video_channel_->set_fail_set_send_codecs(true);
 
-  SendAudioVideoStream2();
   SessionDescriptionInterface* answer =
       CreateRemoteAnswer(session_->local_description());
   SetRemoteDescriptionAnswerExpectError("ERROR_CONTENT", answer);
+
+  // Test that after a content error, setting any description will
+  // result in an error.
+  video_channel_->set_fail_set_send_codecs(false);
+  answer = CreateRemoteAnswer(session_->local_description());
+  SetRemoteDescriptionExpectError("", "ERROR_CONTENT", answer);
+  offer = CreateRemoteOffer();
+  SetLocalDescriptionExpectError("", "ERROR_CONTENT", offer);
 }
 
 // Runs the loopback call test with BUNDLE and STUN disabled.
@@ -3620,28 +3632,6 @@
   TestLoopbackCall();
 }
 
-TEST_F(WebRtcSessionTest, SetSdpFailedOnSessionError) {
-  Init();
-  cricket::MediaSessionOptions options;
-  options.recv_video = true;
-
-  cricket::BaseSession::Error error_code = cricket::BaseSession::ERROR_CONTENT;
-  std::string error_code_str = "ERROR_CONTENT";
-  std::string error_desc = "Fake session error description.";
-  session_->SetError(error_code, error_desc);
-
-  SessionDescriptionInterface* offer = CreateRemoteOffer(options);
-  SessionDescriptionInterface* answer =
-      CreateRemoteAnswer(offer, options);
-
-  std::string action;
-  std::ostringstream session_error_msg;
-  session_error_msg << kSessionError << error_code_str << ". ";
-  session_error_msg << kSessionErrorDesc << error_desc << ".";
-  SetRemoteDescriptionExpectError(action, session_error_msg.str(), offer);
-  SetLocalDescriptionExpectError(action, session_error_msg.str(), answer);
-}
-
 TEST_F(WebRtcSessionTest, TestRtpDataChannel) {
   constraints_.reset(new FakeConstraints());
   constraints_->AddOptional(
diff --git a/talk/app/webrtc/webrtcsessiondescriptionfactory.cc b/talk/app/webrtc/webrtcsessiondescriptionfactory.cc
index d391020..25965af 100644
--- a/talk/app/webrtc/webrtcsessiondescriptionfactory.cc
+++ b/talk/app/webrtc/webrtcsessiondescriptionfactory.cc
@@ -366,10 +366,10 @@
 
 void WebRtcSessionDescriptionFactory::InternalCreateOffer(
     CreateSessionDescriptionRequest request) {
-  cricket::SessionDescription* desc(
-      session_desc_factory_.CreateOffer(
-          request.options,
-          static_cast<cricket::BaseSession*>(session_)->local_description()));
+  cricket::SessionDescription* desc(session_desc_factory_.CreateOffer(
+      request.options, session_->local_description()
+                           ? session_->local_description()->description()
+                           : nullptr));
   // RFC 3264
   // When issuing an offer that modifies the session,
   // the "o=" line of the new SDP MUST be identical to that in the
@@ -413,9 +413,12 @@
   }
 
   cricket::SessionDescription* desc(session_desc_factory_.CreateAnswer(
-      static_cast<cricket::BaseSession*>(session_)->remote_description(),
-      request.options,
-      static_cast<cricket::BaseSession*>(session_)->local_description()));
+      session_->remote_description()
+          ? session_->remote_description()->description()
+          : nullptr,
+      request.options, session_->local_description()
+                           ? session_->local_description()->description()
+                           : nullptr));
   // RFC 3264
   // If the answer is different from the offer in any way (different IP
   // addresses, ports, etc.), the origin line MUST be different in the answer.
diff --git a/talk/session/media/channelmanager.h b/talk/session/media/channelmanager.h
index e0a0fb2..c17a60f 100644
--- a/talk/session/media/channelmanager.h
+++ b/talk/session/media/channelmanager.h
@@ -33,7 +33,6 @@
 
 #include "talk/media/base/capturemanager.h"
 #include "talk/media/base/mediaengine.h"
-#include "webrtc/p2p/base/session.h"
 #include "talk/session/media/voicechannel.h"
 #include "webrtc/base/criticalsection.h"
 #include "webrtc/base/fileutils.h"
diff --git a/talk/session/media/currentspeakermonitor.cc b/talk/session/media/currentspeakermonitor.cc
index 5cfab26..52a0d0c 100644
--- a/talk/session/media/currentspeakermonitor.cc
+++ b/talk/session/media/currentspeakermonitor.cc
@@ -41,14 +41,12 @@
 }
 
 CurrentSpeakerMonitor::CurrentSpeakerMonitor(
-    AudioSourceContext* audio_source_context, BaseSession* session)
+    AudioSourceContext* audio_source_context)
     : started_(false),
       audio_source_context_(audio_source_context),
-      session_(session),
       current_speaker_ssrc_(0),
       earliest_permitted_switch_time_(0),
-      min_time_between_switches_(kDefaultMinTimeBetweenSwitches) {
-}
+      min_time_between_switches_(kDefaultMinTimeBetweenSwitches) {}
 
 CurrentSpeakerMonitor::~CurrentSpeakerMonitor() {
   Stop();
@@ -193,10 +191,10 @@
 }
 
 void CurrentSpeakerMonitor::OnMediaStreamsUpdate(
-    AudioSourceContext* audio_source_context, BaseSession* session,
-    const MediaStreams& added, const MediaStreams& removed) {
-
-  if (audio_source_context == audio_source_context_ && session == session_) {
+    AudioSourceContext* audio_source_context,
+    const MediaStreams& added,
+    const MediaStreams& removed) {
+  if (audio_source_context == audio_source_context_) {
     // Update the speaking state map based on added and removed streams.
     for (std::vector<cricket::StreamParams>::const_iterator
            it = removed.audio().begin(); it != removed.audio().end(); ++it) {
@@ -211,8 +209,8 @@
 }
 
 void CurrentSpeakerMonitor::OnMediaStreamsReset(
-    AudioSourceContext* audio_source_context, BaseSession* session) {
-  if (audio_source_context == audio_source_context_ && session == session_) {
+    AudioSourceContext* audio_source_context) {
+  if (audio_source_context == audio_source_context_) {
     ssrc_to_speaking_state_map_.clear();
   }
 }
diff --git a/talk/session/media/currentspeakermonitor.h b/talk/session/media/currentspeakermonitor.h
index 4dfe6f0..cef8b73 100644
--- a/talk/session/media/currentspeakermonitor.h
+++ b/talk/session/media/currentspeakermonitor.h
@@ -38,7 +38,6 @@
 
 namespace cricket {
 
-class BaseSession;
 struct AudioInfo;
 struct MediaStreams;
 
@@ -46,11 +45,10 @@
  public:
   sigslot::signal2<AudioSourceContext*, const cricket::AudioInfo&>
       SignalAudioMonitor;
-  sigslot::signal2<AudioSourceContext*, cricket::BaseSession*>
-      SignalMediaStreamsReset;
-  sigslot::signal4<AudioSourceContext*, cricket::BaseSession*,
-      const cricket::MediaStreams&, const cricket::MediaStreams&>
-          SignalMediaStreamsUpdate;
+  sigslot::signal1<AudioSourceContext*> SignalMediaStreamsReset;
+  sigslot::signal3<AudioSourceContext*,
+                   const cricket::MediaStreams&,
+                   const cricket::MediaStreams&> SignalMediaStreamsUpdate;
 };
 
 // CurrentSpeakerMonitor can be used to monitor the audio-levels from
@@ -64,12 +62,9 @@
 // It's recommended that the audio monitor be started with a 100 ms period.
 class CurrentSpeakerMonitor : public sigslot::has_slots<> {
  public:
-  CurrentSpeakerMonitor(AudioSourceContext* audio_source_context,
-                        BaseSession* session);
+  CurrentSpeakerMonitor(AudioSourceContext* audio_source_context);
   ~CurrentSpeakerMonitor();
 
-  BaseSession* session() const { return session_; }
-
   void Start();
   void Stop();
 
@@ -87,11 +82,9 @@
   void OnAudioMonitor(AudioSourceContext* audio_source_context,
                       const AudioInfo& info);
   void OnMediaStreamsUpdate(AudioSourceContext* audio_source_context,
-                            BaseSession* session,
                             const MediaStreams& added,
                             const MediaStreams& removed);
-  void OnMediaStreamsReset(AudioSourceContext* audio_source_context,
-                           BaseSession* session);
+  void OnMediaStreamsReset(AudioSourceContext* audio_source_context);
 
   // These are states that a participant will pass through so that we gradually
   // recognize that they have started and stopped speaking.  This avoids
@@ -106,7 +99,6 @@
 
   bool started_;
   AudioSourceContext* audio_source_context_;
-  BaseSession* session_;
   std::map<uint32_t, SpeakingState> ssrc_to_speaking_state_map_;
   uint32_t current_speaker_ssrc_;
   // To prevent overswitching, switching is disabled for some time after a
diff --git a/talk/session/media/currentspeakermonitor_unittest.cc b/talk/session/media/currentspeakermonitor_unittest.cc
index 7970cea..fa2a3ce 100644
--- a/talk/session/media/currentspeakermonitor_unittest.cc
+++ b/talk/session/media/currentspeakermonitor_unittest.cc
@@ -46,7 +46,7 @@
     public sigslot::has_slots<> {
  public:
   CurrentSpeakerMonitorTest() {
-    monitor_ = new CurrentSpeakerMonitor(&source_, NULL);
+    monitor_ = new CurrentSpeakerMonitor(&source_);
     // Shrink the minimum time betweeen switches to 10 ms so we don't have to
     // slow down our tests.
     monitor_->set_min_time_between_switches(kMinTimeBetweenSwitches);
diff --git a/webrtc/p2p/base/session.cc b/webrtc/p2p/base/session.cc
index 5e5a88f..1a23f83 100644
--- a/webrtc/p2p/base/session.cc
+++ b/webrtc/p2p/base/session.cc
@@ -8,254 +8,5 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "webrtc/p2p/base/session.h"
-
-#include "webrtc/base/bind.h"
-#include "webrtc/base/common.h"
-#include "webrtc/base/helpers.h"
-#include "webrtc/base/logging.h"
-#include "webrtc/base/scoped_ptr.h"
-#include "webrtc/base/stringencode.h"
-#include "webrtc/base/sslstreamadapter.h"
-#include "webrtc/p2p/base/transport.h"
-#include "webrtc/p2p/base/transportinfo.h"
-#include "webrtc/p2p/base/transportcontroller.h"
-#include "webrtc/p2p/base/constants.h"
-
-namespace cricket {
-
-using rtc::Bind;
-
-std::string BaseSession::StateToString(State state) {
-  switch (state) {
-    case STATE_INIT:
-      return "STATE_INIT";
-    case STATE_SENTINITIATE:
-      return "STATE_SENTINITIATE";
-    case STATE_RECEIVEDINITIATE:
-      return "STATE_RECEIVEDINITIATE";
-    case STATE_SENTPRACCEPT:
-      return "STATE_SENTPRACCEPT";
-    case STATE_SENTACCEPT:
-      return "STATE_SENTACCEPT";
-    case STATE_RECEIVEDPRACCEPT:
-      return "STATE_RECEIVEDPRACCEPT";
-    case STATE_RECEIVEDACCEPT:
-      return "STATE_RECEIVEDACCEPT";
-    case STATE_SENTMODIFY:
-      return "STATE_SENTMODIFY";
-    case STATE_RECEIVEDMODIFY:
-      return "STATE_RECEIVEDMODIFY";
-    case STATE_SENTREJECT:
-      return "STATE_SENTREJECT";
-    case STATE_RECEIVEDREJECT:
-      return "STATE_RECEIVEDREJECT";
-    case STATE_SENTREDIRECT:
-      return "STATE_SENTREDIRECT";
-    case STATE_SENTTERMINATE:
-      return "STATE_SENTTERMINATE";
-    case STATE_RECEIVEDTERMINATE:
-      return "STATE_RECEIVEDTERMINATE";
-    case STATE_INPROGRESS:
-      return "STATE_INPROGRESS";
-    case STATE_DEINIT:
-      return "STATE_DEINIT";
-    default:
-      break;
-  }
-  return "STATE_" + rtc::ToString(state);
-}
-
-BaseSession::BaseSession(rtc::Thread* signaling_thread,
-                         rtc::Thread* worker_thread,
-                         PortAllocator* port_allocator,
-                         const std::string& sid,
-                         bool initiator)
-    : state_(STATE_INIT),
-      error_(ERROR_NONE),
-      signaling_thread_(signaling_thread),
-      worker_thread_(worker_thread),
-      port_allocator_(port_allocator),
-      sid_(sid),
-      transport_controller_(new TransportController(signaling_thread,
-                                                    worker_thread,
-                                                    port_allocator)) {
-  ASSERT(signaling_thread->IsCurrent());
-  set_initiator(initiator);
-}
-
-BaseSession::~BaseSession() {
-  ASSERT(signaling_thread()->IsCurrent());
-
-  ASSERT(state_ != STATE_DEINIT);
-  LogState(state_, STATE_DEINIT);
-  state_ = STATE_DEINIT;
-  SignalState(this, state_);
-}
-
-const SessionDescription* BaseSession::local_description() const {
-  // TODO(tommi): Assert on thread correctness.
-  return local_description_.get();
-}
-
-const SessionDescription* BaseSession::remote_description() const {
-  // TODO(tommi): Assert on thread correctness.
-  return remote_description_.get();
-}
-
-SessionDescription* BaseSession::remote_description() {
-  // TODO(tommi): Assert on thread correctness.
-  return remote_description_.get();
-}
-
-void BaseSession::set_local_description(const SessionDescription* sdesc) {
-  // TODO(tommi): Assert on thread correctness.
-  if (sdesc != local_description_.get())
-    local_description_.reset(sdesc);
-}
-
-void BaseSession::set_remote_description(SessionDescription* sdesc) {
-  // TODO(tommi): Assert on thread correctness.
-  if (sdesc != remote_description_)
-    remote_description_.reset(sdesc);
-}
-
-void BaseSession::set_initiator(bool initiator) {
-  initiator_ = initiator;
-
-  IceRole ice_role = initiator ? ICEROLE_CONTROLLING : ICEROLE_CONTROLLED;
-  transport_controller_->SetIceRole(ice_role);
-}
-
-const SessionDescription* BaseSession::initiator_description() const {
-  // TODO(tommi): Assert on thread correctness.
-  return initiator_ ? local_description_.get() : remote_description_.get();
-}
-
-bool BaseSession::PushdownTransportDescription(ContentSource source,
-                                               ContentAction action,
-                                               std::string* error_desc) {
-  ASSERT(signaling_thread()->IsCurrent());
-
-  if (source == CS_LOCAL) {
-    return PushdownLocalTransportDescription(local_description(),
-                                             action,
-                                             error_desc);
-  }
-  return PushdownRemoteTransportDescription(remote_description(),
-                                            action,
-                                            error_desc);
-}
-
-bool BaseSession::PushdownLocalTransportDescription(
-    const SessionDescription* sdesc,
-    ContentAction action,
-    std::string* err) {
-  ASSERT(signaling_thread()->IsCurrent());
-
-  if (!sdesc) {
-    return false;
-  }
-
-  for (const TransportInfo& tinfo : sdesc->transport_infos()) {
-    if (!transport_controller_->SetLocalTransportDescription(
-            tinfo.content_name, tinfo.description, action, err)) {
-      return false;
-    }
-  }
-
-  return true;
-}
-
-bool BaseSession::PushdownRemoteTransportDescription(
-    const SessionDescription* sdesc,
-    ContentAction action,
-    std::string* err) {
-  ASSERT(signaling_thread()->IsCurrent());
-
-  if (!sdesc) {
-    return false;
-  }
-
-  for (const TransportInfo& tinfo : sdesc->transport_infos()) {
-    if (!transport_controller_->SetRemoteTransportDescription(
-            tinfo.content_name, tinfo.description, action, err)) {
-      return false;
-    }
-  }
-
-  return true;
-}
-
-void BaseSession::SetState(State state) {
-  ASSERT(signaling_thread_->IsCurrent());
-  if (state != state_) {
-    LogState(state_, state);
-    state_ = state;
-    SignalState(this, state_);
-    signaling_thread_->Post(this, MSG_STATE);
-  }
-}
-
-void BaseSession::SetError(Error error, const std::string& error_desc) {
-  ASSERT(signaling_thread_->IsCurrent());
-  if (error != error_) {
-    error_ = error;
-    error_desc_ = error_desc;
-    SignalError(this, error);
-  }
-}
-
-void BaseSession::SetIceConfig(const IceConfig& config) {
-  transport_controller_->SetIceConfig(config);
-}
-
-void BaseSession::MaybeStartGathering() {
-  transport_controller_->MaybeStartGathering();
-}
-
-void BaseSession::LogState(State old_state, State new_state) {
-  LOG(LS_INFO) << "Session:" << id()
-               << " Old state:" << StateToString(old_state)
-               << " New state:" << StateToString(new_state);
-}
-
-// static
-bool BaseSession::GetTransportDescription(const SessionDescription* description,
-                                          const std::string& content_name,
-                                          TransportDescription* tdesc) {
-  if (!description || !tdesc) {
-    return false;
-  }
-  const TransportInfo* transport_info =
-      description->GetTransportInfoByName(content_name);
-  if (!transport_info) {
-    return false;
-  }
-  *tdesc = transport_info->description;
-  return true;
-}
-
-void BaseSession::OnMessage(rtc::Message *pmsg) {
-  switch (pmsg->message_id) {
-  case MSG_TIMEOUT:
-    // Session timeout has occured.
-    SetError(ERROR_TIME, "Session timeout has occured.");
-    break;
-
-  case MSG_STATE:
-    switch (state_) {
-    case STATE_SENTACCEPT:
-    case STATE_RECEIVEDACCEPT:
-      SetState(STATE_INPROGRESS);
-      break;
-
-    default:
-      // Explicitly ignoring some states here.
-      break;
-    }
-    break;
-  }
-}
-
-}  // namespace cricket
+// TODO(deadbeef): Remove this file when Chrome build files no longer reference
+// it.
diff --git a/webrtc/p2p/base/session.h b/webrtc/p2p/base/session.h
index 2cf8c8a..a98a5ef 100644
--- a/webrtc/p2p/base/session.h
+++ b/webrtc/p2p/base/session.h
@@ -8,195 +8,6 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef WEBRTC_P2P_BASE_SESSION_H_
-#define WEBRTC_P2P_BASE_SESSION_H_
-
-#include <list>
-#include <map>
-#include <string>
-#include <vector>
-
-#include "webrtc/base/refcount.h"
-#include "webrtc/base/rtccertificate.h"
-#include "webrtc/base/scoped_ptr.h"
-#include "webrtc/base/scoped_ref_ptr.h"
-#include "webrtc/base/socketaddress.h"
-#include "webrtc/p2p/base/candidate.h"
-#include "webrtc/p2p/base/port.h"
-#include "webrtc/p2p/base/transport.h"
-
-namespace cricket {
-
-class BaseSession;
-class P2PTransportChannel;
-class Transport;
-class TransportChannel;
-class TransportChannelImpl;
-class TransportController;
-
-// Statistics for all the transports of this session.
-typedef std::map<std::string, TransportStats> TransportStatsMap;
-typedef std::map<std::string, std::string> ProxyTransportMap;
-
-// TODO(pthatcher): Think of a better name for this.  We already have
-// a TransportStats in transport.h.  Perhaps TransportsStats?
-struct SessionStats {
-  ProxyTransportMap proxy_to_transport;
-  TransportStatsMap transport_stats;
-};
-
-// A BaseSession manages general session state. This includes negotiation
-// of both the application-level and network-level protocols:  the former
-// defines what will be sent and the latter defines how it will be sent.  Each
-// network-level protocol is represented by a Transport object.  Each Transport
-// participates in the network-level negotiation.  The individual streams of
-// packets are represented by TransportChannels.  The application-level protocol
-// is represented by SessionDecription objects.
-class BaseSession : public sigslot::has_slots<>,
-                    public rtc::MessageHandler {
- public:
-  enum {
-    MSG_TIMEOUT = 0,
-    MSG_ERROR,
-    MSG_STATE,
-  };
-
-  enum State {
-    STATE_INIT = 0,
-    STATE_SENTINITIATE,       // sent initiate, waiting for Accept or Reject
-    STATE_RECEIVEDINITIATE,   // received an initiate. Call Accept or Reject
-    STATE_SENTPRACCEPT,       // sent provisional Accept
-    STATE_SENTACCEPT,         // sent accept. begin connecting transport
-    STATE_RECEIVEDPRACCEPT,   // received provisional Accept, waiting for Accept
-    STATE_RECEIVEDACCEPT,     // received accept. begin connecting transport
-    STATE_SENTMODIFY,         // sent modify, waiting for Accept or Reject
-    STATE_RECEIVEDMODIFY,     // received modify, call Accept or Reject
-    STATE_SENTREJECT,         // sent reject after receiving initiate
-    STATE_RECEIVEDREJECT,     // received reject after sending initiate
-    STATE_SENTREDIRECT,       // sent direct after receiving initiate
-    STATE_SENTTERMINATE,      // sent terminate (any time / either side)
-    STATE_RECEIVEDTERMINATE,  // received terminate (any time / either side)
-    STATE_INPROGRESS,         // session accepted and in progress
-    STATE_DEINIT,             // session is being destroyed
-  };
-
-  enum Error {
-    ERROR_NONE = 0,       // no error
-    ERROR_TIME = 1,       // no response to signaling
-    ERROR_RESPONSE = 2,   // error during signaling
-    ERROR_NETWORK = 3,    // network error, could not allocate network resources
-    ERROR_CONTENT = 4,    // channel errors in SetLocalContent/SetRemoteContent
-    ERROR_TRANSPORT = 5,  // transport error of some kind
-  };
-
-  // Convert State to a readable string.
-  static std::string StateToString(State state);
-
-  BaseSession(rtc::Thread* signaling_thread,
-              rtc::Thread* worker_thread,
-              PortAllocator* port_allocator,
-              const std::string& sid,
-              bool initiator);
-  virtual ~BaseSession();
-
-  // These are const to allow them to be called from const methods.
-  rtc::Thread* signaling_thread() const { return signaling_thread_; }
-  rtc::Thread* worker_thread() const { return worker_thread_; }
-  PortAllocator* port_allocator() const { return port_allocator_; }
-
-  // The ID of this session.
-  const std::string& id() const { return sid_; }
-
-  // Returns the application-level description given by our client.
-  // If we are the recipient, this will be NULL until we send an accept.
-  const SessionDescription* local_description() const;
-
-  // Returns the application-level description given by the other client.
-  // If we are the initiator, this will be NULL until we receive an accept.
-  const SessionDescription* remote_description() const;
-
-  SessionDescription* remote_description();
-
-  // Takes ownership of SessionDescription*
-  void set_local_description(const SessionDescription* sdesc);
-
-  // Takes ownership of SessionDescription*
-  void set_remote_description(SessionDescription* sdesc);
-
-  void set_initiator(bool initiator);
-  bool initiator() const { return initiator_; }
-
-  const SessionDescription* initiator_description() const;
-
-  // Returns the current state of the session.  See the enum above for details.
-  // Each time the state changes, we will fire this signal.
-  State state() const { return state_; }
-  sigslot::signal2<BaseSession* , State> SignalState;
-
-  // Returns the last error in the session.  See the enum above for details.
-  // Each time the an error occurs, we will fire this signal.
-  Error error() const { return error_; }
-  const std::string& error_desc() const { return error_desc_; }
-  sigslot::signal2<BaseSession* , Error> SignalError;
-
-  // Updates the state, signaling if necessary.
-  virtual void SetState(State state);
-
-  // Updates the error state, signaling if necessary.
-  // TODO(ronghuawu): remove the SetError method that doesn't take |error_desc|.
-  virtual void SetError(Error error, const std::string& error_desc);
-
-  void SetIceConfig(const IceConfig& ice_config);
-
-  // Start gathering candidates for any new transports, or transports doing an
-  // ICE restart.
-  void MaybeStartGathering();
-
- protected:
-  bool PushdownTransportDescription(ContentSource source,
-                                    ContentAction action,
-                                    std::string* error_desc);
-
-  // Handles messages posted to us.
-  virtual void OnMessage(rtc::Message *pmsg);
-
-  TransportController* transport_controller() {
-    return transport_controller_.get();
-  }
-
- protected:
-  State state_;
-  Error error_;
-  std::string error_desc_;
-
- private:
-  // Helper methods to push local and remote transport descriptions.
-  bool PushdownLocalTransportDescription(
-      const SessionDescription* sdesc, ContentAction action,
-      std::string* error_desc);
-  bool PushdownRemoteTransportDescription(
-      const SessionDescription* sdesc, ContentAction action,
-      std::string* error_desc);
-
-  // Log session state.
-  void LogState(State old_state, State new_state);
-
-  // Returns true and the TransportInfo of the given |content_name|
-  // from |description|. Returns false if it's not available.
-  static bool GetTransportDescription(const SessionDescription* description,
-                                      const std::string& content_name,
-                                      TransportDescription* info);
-
-  rtc::Thread* const signaling_thread_;
-  rtc::Thread* const worker_thread_;
-  PortAllocator* const port_allocator_;
-  const std::string sid_;
-  bool initiator_;
-  rtc::scoped_ptr<TransportController> transport_controller_;
-  rtc::scoped_ptr<const SessionDescription> local_description_;
-  rtc::scoped_ptr<SessionDescription> remote_description_;
-};
-
-}  // namespace cricket
-
-#endif  // WEBRTC_P2P_BASE_SESSION_H_
+// TODO(deadbeef): Remove this file when Chrome build files no longer reference
+// it.
+#error "DONT INCLUDE THIS"
diff --git a/webrtc/p2p/p2p.gyp b/webrtc/p2p/p2p.gyp
index b5409f4..490cfbf 100644
--- a/webrtc/p2p/p2p.gyp
+++ b/webrtc/p2p/p2p.gyp
@@ -46,8 +46,6 @@
         'base/relayport.h',
         'base/relayserver.cc',
         'base/relayserver.h',
-        'base/session.cc',
-        'base/session.h',
         'base/sessiondescription.cc',
         'base/sessiondescription.h',
         'base/sessionid.h',