Prepare WebRtcSession to be merged into PeerConnection

This commit prepares WebRtcSession so that it can be cleanly
copy & pasted into PeerConnection in the next commit. To accomplish
this, the following was done:
1. Added a pointer to the owning PeerConnection to WebRtcSession.
2. Replace WebRtcSession state enum with signaling state.
3. All signals/observers only observed by PeerConnection were
   replaced with direct calls to PeerConnection methods.
4. All duplicated fields were moved to PeerConnection.
5. The remaining tests that still use WebRtcSession for mocks were
   updated to minimize dependence on WebRtcSession construction.

Bug: webrtc:8323
Change-Id: Ifc1a4ee819dcc9beca5363291012f7d5563ff7b1
Reviewed-on: https://webrtc-review.googlesource.com/9020
Commit-Queue: Steve Anton <steveanton@webrtc.org>
Reviewed-by: Peter Thatcher <pthatcher@webrtc.org>
Reviewed-by: Zhi Huang <zhihuang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20573}
diff --git a/pc/peerconnection.cc b/pc/peerconnection.cc
index 89452c0..3889222 100644
--- a/pc/peerconnection.cc
+++ b/pc/peerconnection.cc
@@ -45,6 +45,8 @@
 #include "system_wrappers/include/clock.h"
 #include "system_wrappers/include/field_trial.h"
 
+namespace webrtc {
+
 namespace {
 
 using webrtc::DataChannel;
@@ -241,7 +243,25 @@
 
 }  // namespace
 
-namespace webrtc {
+std::string GetSignalingStateString(
+    PeerConnectionInterface::SignalingState state) {
+  switch (state) {
+    case PeerConnectionInterface::kStable:
+      return "kStable";
+    case PeerConnectionInterface::kHaveLocalOffer:
+      return "kHaveLocalOffer";
+    case PeerConnectionInterface::kHaveLocalPrAnswer:
+      return "kHavePrAnswer";
+    case PeerConnectionInterface::kHaveRemoteOffer:
+      return "kHaveRemoteOffer";
+    case PeerConnectionInterface::kHaveRemotePrAnswer:
+      return "kHaveRemotePrAnswer";
+    case PeerConnectionInterface::kClosed:
+      return "kClosed";
+  }
+  RTC_NOTREACHED();
+  return "";
+}
 
 bool PeerConnectionInterface::RTCConfiguration::operator==(
     const PeerConnectionInterface::RTCConfiguration& o) const {
@@ -393,12 +413,7 @@
                                std::unique_ptr<RtcEventLog> event_log,
                                std::unique_ptr<Call> call)
     : factory_(factory),
-      observer_(NULL),
-      uma_observer_(NULL),
       event_log_(std::move(event_log)),
-      signaling_state_(kStable),
-      ice_connection_state_(kIceConnectionNew),
-      ice_gathering_state_(kIceGatheringNew),
       rtcp_cname_(GenerateRtcpCname()),
       local_streams_(StreamCollection::Create()),
       remote_streams_(StreamCollection::Create()),
@@ -472,44 +487,26 @@
     return false;
   }
 
-  owned_session_.reset(new WebRtcSession(
-      call_.get(), factory_->channel_manager(), configuration.media_config,
-      event_log_.get(), network_thread(), worker_thread(), signaling_thread(),
-      port_allocator_.get(),
-      std::unique_ptr<cricket::TransportController>(
-          factory_->CreateTransportController(
-              port_allocator_.get(),
-              configuration.redetermine_role_on_ice_restart)),
-      factory_->CreateSctpTransportInternalFactory()));
+  owned_session_.reset(
+      new WebRtcSession(this,
+                        std::unique_ptr<cricket::TransportController>(
+                            factory_->CreateTransportController(
+                                port_allocator_.get(),
+                                configuration.redetermine_role_on_ice_restart)),
+                        factory_->CreateSctpTransportInternalFactory()));
   session_ = owned_session_.get();
 
   stats_.reset(new StatsCollector(this));
   stats_collector_ = RTCStatsCollector::Create(this);
 
+  // Need to set configuration before initializing WebRtcSession because it will
+  // reach back to fetch the media config.
+  configuration_ = configuration;
+
   // Initialize the WebRtcSession. It creates transport channels etc.
   session_->Initialize(factory_->options(), std::move(cert_generator),
                        configuration, this);
 
-  // Register PeerConnection as receiver of local ice candidates.
-  // All the callbacks will be posted to the application from PeerConnection.
-  session_->RegisterIceObserver(this);
-  session_->SignalState.connect(this, &PeerConnection::OnSessionStateChange);
-  session_->SignalVoiceChannelCreated.connect(
-      this, &PeerConnection::OnVoiceChannelCreated);
-  session_->SignalVoiceChannelDestroyed.connect(
-      this, &PeerConnection::OnVoiceChannelDestroyed);
-  session_->SignalVideoChannelCreated.connect(
-      this, &PeerConnection::OnVideoChannelCreated);
-  session_->SignalVideoChannelDestroyed.connect(
-      this, &PeerConnection::OnVideoChannelDestroyed);
-  session_->SignalDataChannelCreated.connect(
-      this, &PeerConnection::OnDataChannelCreated);
-  session_->SignalDataChannelDestroyed.connect(
-      this, &PeerConnection::OnDataChannelDestroyed);
-  session_->SignalDataChannelOpenMessage.connect(
-      this, &PeerConnection::OnDataChannelOpenMessage);
-
-  configuration_ = configuration;
   return true;
 }
 
@@ -1240,7 +1237,7 @@
   uma_observer_ = observer;
 
   if (session_) {
-    session_->set_metrics_observer(uma_observer_);
+    session_->transport_controller()->SetMetricsObserver(uma_observer_);
   }
 
   // Send information about IPv4/IPv6 status.
@@ -1433,35 +1430,6 @@
   });
 }
 
-void PeerConnection::OnSessionStateChange(WebRtcSession* /*session*/,
-                                          WebRtcSession::State state) {
-  switch (state) {
-    case WebRtcSession::STATE_INIT:
-      ChangeSignalingState(PeerConnectionInterface::kStable);
-      break;
-    case WebRtcSession::STATE_SENTOFFER:
-      ChangeSignalingState(PeerConnectionInterface::kHaveLocalOffer);
-      break;
-    case WebRtcSession::STATE_SENTPRANSWER:
-      ChangeSignalingState(PeerConnectionInterface::kHaveLocalPrAnswer);
-      break;
-    case WebRtcSession::STATE_RECEIVEDOFFER:
-      ChangeSignalingState(PeerConnectionInterface::kHaveRemoteOffer);
-      break;
-    case WebRtcSession::STATE_RECEIVEDPRANSWER:
-      ChangeSignalingState(PeerConnectionInterface::kHaveRemotePrAnswer);
-      break;
-    case WebRtcSession::STATE_INPROGRESS:
-      ChangeSignalingState(PeerConnectionInterface::kStable);
-      break;
-    case WebRtcSession::STATE_CLOSED:
-      ChangeSignalingState(PeerConnectionInterface::kClosed);
-      break;
-    default:
-      break;
-  }
-}
-
 void PeerConnection::OnMessage(rtc::Message* msg) {
   switch (msg->message_id) {
     case MSG_SET_SESSIONDESCRIPTION_SUCCESS: {
@@ -1633,14 +1601,23 @@
   senders_.erase(sender);
 }
 
-void PeerConnection::OnIceConnectionStateChange(
-    PeerConnectionInterface::IceConnectionState new_state) {
+void PeerConnection::SetIceConnectionState(IceConnectionState new_state) {
   RTC_DCHECK(signaling_thread()->IsCurrent());
+  if (ice_connection_state_ == new_state) {
+    return;
+  }
+
   // After transitioning to "closed", ignore any additional states from
-  // WebRtcSession (such as "disconnected").
+  // TransportController (such as "disconnected").
   if (IsClosed()) {
     return;
   }
+
+  LOG(LS_INFO) << "Changing IceConnectionState " << ice_connection_state_
+               << " => " << new_state;
+  RTC_DCHECK(ice_connection_state_ !=
+             PeerConnectionInterface::kIceConnectionClosed);
+
   ice_connection_state_ = new_state;
   observer_->OnIceConnectionChange(ice_connection_state_);
 }
@@ -1673,16 +1650,15 @@
   observer_->OnIceCandidatesRemoved(candidates);
 }
 
-void PeerConnection::OnIceConnectionReceivingChange(bool receiving) {
-  RTC_DCHECK(signaling_thread()->IsCurrent());
-  if (IsClosed()) {
-    return;
-  }
-  observer_->OnIceConnectionReceivingChange(receiving);
-}
-
 void PeerConnection::ChangeSignalingState(
     PeerConnectionInterface::SignalingState signaling_state) {
+  RTC_DCHECK(signaling_thread()->IsCurrent());
+  if (signaling_state_ == signaling_state) {
+    return;
+  }
+  LOG(LS_INFO) << "Session: " << session_id()
+               << " Old state: " << GetSignalingStateString(signaling_state_)
+               << " New state: " << GetSignalingStateString(signaling_state);
   signaling_state_ = signaling_state;
   if (signaling_state == kClosed) {
     ice_connection_state_ = kIceConnectionClosed;
@@ -2609,6 +2585,14 @@
       turn_customizer);
 }
 
+cricket::ChannelManager* PeerConnection::channel_manager() const {
+  return factory_->channel_manager();
+}
+
+MetricsObserverInterface* PeerConnection::metrics_observer() const {
+  return uma_observer_;
+}
+
 bool PeerConnection::StartRtcEventLog_w(
     std::unique_ptr<RtcEventLogOutput> output) {
   if (!event_log_) {
diff --git a/pc/peerconnection.h b/pc/peerconnection.h
index 97068b9..2afb17c 100644
--- a/pc/peerconnection.h
+++ b/pc/peerconnection.h
@@ -33,13 +33,19 @@
 class VideoRtpReceiver;
 class RtcEventLog;
 
+// TODO(steveanton): Remove once WebRtcSession is merged into PeerConnection.
+std::string GetSignalingStateString(
+    PeerConnectionInterface::SignalingState state);
+
 // PeerConnection implements the PeerConnectionInterface interface.
 // It uses WebRtcSession to implement the PeerConnection functionality.
 class PeerConnection : public PeerConnectionInterface,
-                       public IceObserver,
                        public rtc::MessageHandler,
                        public sigslot::has_slots<> {
  public:
+  // TODO(steveanton): Remove once WebRtcSession is merged into PeerConnection.
+  friend class WebRtcSession;
+
   explicit PeerConnection(PeerConnectionFactory* factory,
                           std::unique_ptr<RtcEventLog> event_log,
                           std::unique_ptr<Call> call);
@@ -171,15 +177,17 @@
   rtc::Thread* network_thread() const { return factory_->network_thread(); }
   rtc::Thread* worker_thread() const { return factory_->worker_thread(); }
   rtc::Thread* signaling_thread() const { return factory_->signaling_thread(); }
-  virtual const std::string& session_id() const { return session_->id(); }
+  virtual const std::string& session_id() const {
+    return session_->session_id();
+  }
   virtual bool session_created() const { return session_ != nullptr; }
   virtual bool initial_offerer() const { return session_->initial_offerer(); }
   virtual std::unique_ptr<SessionStats> GetSessionStats_s() {
-    return session_->GetStats_s();
+    return session_->GetSessionStats_s();
   }
   virtual std::unique_ptr<SessionStats> GetSessionStats(
       const ChannelNamePairs& channel_name_pairs) {
-    return session_->GetStats(channel_name_pairs);
+    return session_->GetSessionStats(channel_name_pairs);
   }
   virtual bool GetLocalCertificate(
       const std::string& transport_name,
@@ -270,17 +278,16 @@
   void RemoveVideoTrack(VideoTrackInterface* track,
                         MediaStreamInterface* stream);
 
-  // Implements IceObserver
-  void OnIceConnectionStateChange(IceConnectionState new_state) override;
-  void OnIceGatheringChange(IceGatheringState new_state) override;
-  void OnIceCandidate(
-      std::unique_ptr<IceCandidateInterface> candidate) override;
+  void SetIceConnectionState(IceConnectionState new_state);
+  // Called any time the IceGatheringState changes
+  void OnIceGatheringChange(IceGatheringState new_state);
+  // New ICE candidate has been gathered.
+  void OnIceCandidate(std::unique_ptr<IceCandidateInterface> candidate);
+  // Some local ICE candidates have been removed.
   void OnIceCandidatesRemoved(
-      const std::vector<cricket::Candidate>& candidates) override;
-  void OnIceConnectionReceivingChange(bool receiving) override;
+      const std::vector<cricket::Candidate>& candidates);
 
-  // Signals from WebRtcSession.
-  void OnSessionStateChange(WebRtcSession* session, WebRtcSession::State state);
+  // Update the state, signaling if necessary.
   void ChangeSignalingState(SignalingState signaling_state);
 
   // Signals from MediaStreamObserver.
@@ -408,15 +415,16 @@
   void AllocateSctpSids(rtc::SSLRole role);
   void OnSctpDataChannelClosed(DataChannel* channel);
 
-  // Notifications from WebRtcSession relating to BaseChannels.
+  // Called when voice_channel_, video_channel_ and
+  // rtp_data_channel_/sctp_transport_ are created and destroyed. As a result
+  // of, for example, setting a new description.
   void OnVoiceChannelCreated();
   void OnVoiceChannelDestroyed();
   void OnVideoChannelCreated();
   void OnVideoChannelDestroyed();
   void OnDataChannelCreated();
   void OnDataChannelDestroyed();
-  // Called when the cricket::DataChannel receives a message indicating that a
-  // webrtc::DataChannel should be opened.
+  // Called when a valid data channel OPEN message is received.
   void OnDataChannelOpenMessage(const std::string& label,
                                 const InternalDataChannelInit& config);
 
@@ -466,6 +474,9 @@
   // Returns RTCError::OK() if there are no issues.
   RTCError ValidateConfiguration(const RTCConfiguration& config) const;
 
+  cricket::ChannelManager* channel_manager() const;
+  MetricsObserverInterface* metrics_observer() const;
+
   // Storing the factory as a scoped reference pointer ensures that the memory
   // in the PeerConnectionFactoryImpl remains available as long as the
   // PeerConnection is running. It is passed to PeerConnection as a raw pointer.
@@ -473,15 +484,15 @@
   // PeerConnectionFactoryInterface all instances created using the raw pointer
   // will refer to the same reference count.
   rtc::scoped_refptr<PeerConnectionFactory> factory_;
-  PeerConnectionObserver* observer_;
-  UMAObserver* uma_observer_;
+  PeerConnectionObserver* observer_ = nullptr;
+  UMAObserver* uma_observer_ = nullptr;
 
   // The EventLog needs to outlive |call_| (and any other object that uses it).
   std::unique_ptr<RtcEventLog> event_log_;
 
-  SignalingState signaling_state_;
-  IceConnectionState ice_connection_state_;
-  IceGatheringState ice_gathering_state_;
+  SignalingState signaling_state_ = kStable;
+  IceConnectionState ice_connection_state_ = kIceConnectionNew;
+  IceGatheringState ice_gathering_state_ = kIceGatheringNew;
   PeerConnectionInterface::RTCConfiguration configuration_;
 
   std::unique_ptr<cricket::PortAllocator> port_allocator_;
@@ -512,7 +523,7 @@
   bool remote_peer_supports_msid_ = false;
 
   std::unique_ptr<Call> call_;
-  WebRtcSession* session_;
+  WebRtcSession* session_ = nullptr;
   std::unique_ptr<WebRtcSession> owned_session_;
   std::unique_ptr<StatsCollector> stats_;  // A pointer is passed to senders_
   rtc::scoped_refptr<RTCStatsCollector> stats_collector_;
diff --git a/pc/rtcstatscollector_unittest.cc b/pc/rtcstatscollector_unittest.cc
index 71b3797..44a462a 100644
--- a/pc/rtcstatscollector_unittest.cc
+++ b/pc/rtcstatscollector_unittest.cc
@@ -279,12 +279,10 @@
         network_thread_(rtc::Thread::Current()),
         signaling_thread_(rtc::Thread::Current()),
         media_engine_(new cricket::FakeMediaEngine()),
-        channel_manager_(new cricket::ChannelManager(
-            std::unique_ptr<cricket::MediaEngineInterface>(media_engine_),
-            worker_thread_,
-            network_thread_)),
-        session_(channel_manager_.get(), cricket::MediaConfig()),
-        pc_() {
+        pc_factory_(new FakePeerConnectionFactory(
+            std::unique_ptr<cricket::MediaEngineInterface>(media_engine_))),
+        pc_(pc_factory_),
+        session_(&pc_) {
     pc_.set_session_for_testing(&session_);
     // Default return values for mocks.
     EXPECT_CALL(pc_, local_streams()).WillRepeatedly(Return(nullptr));
@@ -297,7 +295,7 @@
         ReturnRef(data_channels_));
     EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
     EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
-    EXPECT_CALL(session_, GetStats(_)).WillRepeatedly(ReturnNull());
+    EXPECT_CALL(session_, GetSessionStats(_)).WillRepeatedly(ReturnNull());
     EXPECT_CALL(session_, GetLocalCertificate(_, _)).WillRepeatedly(
         Return(false));
     EXPECT_CALL(session_, GetRemoteSSLCertificate_ReturnsRawPointer(_))
@@ -487,11 +485,11 @@
   rtc::Thread* const worker_thread_;
   rtc::Thread* const network_thread_;
   rtc::Thread* const signaling_thread_;
-  // |media_engine_| is actually owned by |channel_manager_|.
+  // |media_engine_| is actually owned by |pc_factory_|.
   cricket::FakeMediaEngine* media_engine_;
-  std::unique_ptr<cricket::ChannelManager> channel_manager_;
-  MockWebRtcSession session_;
+  rtc::scoped_refptr<FakePeerConnectionFactory> pc_factory_;
   MockPeerConnection pc_;
+  MockWebRtcSession session_;
 
   std::vector<rtc::scoped_refptr<DataChannel>> data_channels_;
   std::unique_ptr<cricket::VoiceChannel> voice_channel_;
@@ -714,8 +712,8 @@
           std::vector<std::string>({ "(remote) single certificate" }));
 
   // Mock the session to return the local and remote certificates.
-  EXPECT_CALL(test_->session(), GetStats(_)).WillRepeatedly(Invoke(
-      [](const ChannelNamePairs&) {
+  EXPECT_CALL(test_->session(), GetSessionStats(_))
+      .WillRepeatedly(Invoke([](const ChannelNamePairs&) {
         std::unique_ptr<SessionStats> stats(new SessionStats());
         stats->transport_stats["transport"].transport_name = "transport";
         return stats;
@@ -805,8 +803,8 @@
   session_stats.transport_stats["TransportName"].transport_name =
       "TransportName";
 
-  EXPECT_CALL(test_->session(), GetStats(_)).WillRepeatedly(Invoke(
-      [&session_stats](const ChannelNamePairs&) {
+  EXPECT_CALL(test_->session(), GetSessionStats(_))
+      .WillRepeatedly(Invoke([&session_stats](const ChannelNamePairs&) {
         return std::unique_ptr<SessionStats>(new SessionStats(session_stats));
       }));
   EXPECT_CALL(test_->session(), voice_channel())
@@ -885,8 +883,8 @@
       video_remote_certinfo->ders);
 
   // Mock the session to return the local and remote certificates.
-  EXPECT_CALL(test_->session(), GetStats(_)).WillRepeatedly(Invoke(
-      [](const ChannelNamePairs&) {
+  EXPECT_CALL(test_->session(), GetSessionStats(_))
+      .WillRepeatedly(Invoke([](const ChannelNamePairs&) {
         std::unique_ptr<SessionStats> stats(new SessionStats());
         stats->transport_stats["audio"].transport_name = "audio";
         stats->transport_stats["video"].transport_name = "video";
@@ -945,8 +943,8 @@
       CreateFakeCertificateAndInfoFromDers(remote_ders);
 
   // Mock the session to return the local and remote certificates.
-  EXPECT_CALL(test_->session(), GetStats(_)).WillRepeatedly(Invoke(
-      [](const ChannelNamePairs&) {
+  EXPECT_CALL(test_->session(), GetSessionStats(_))
+      .WillRepeatedly(Invoke([](const ChannelNamePairs&) {
         std::unique_ptr<SessionStats> stats(new SessionStats());
         stats->transport_stats["transport"].transport_name = "transport";
         return stats;
@@ -1178,8 +1176,8 @@
       b_transport_channel_stats);
 
   // Mock the session to return the desired candidates.
-  EXPECT_CALL(test_->session(), GetStats(_)).WillRepeatedly(Invoke(
-      [&session_stats](const ChannelNamePairs&) {
+  EXPECT_CALL(test_->session(), GetSessionStats(_))
+      .WillRepeatedly(Invoke([&session_stats](const ChannelNamePairs&) {
         return std::unique_ptr<SessionStats>(new SessionStats(session_stats));
       }));
 
@@ -1254,8 +1252,8 @@
       transport_channel_stats);
 
   // Mock the session to return the desired candidates.
-  EXPECT_CALL(test_->session(), GetStats(_)).WillRepeatedly(Invoke(
-      [&session_stats](const ChannelNamePairs&) {
+  EXPECT_CALL(test_->session(), GetSessionStats(_))
+      .WillRepeatedly(Invoke([&session_stats](const ChannelNamePairs&) {
         return std::unique_ptr<SessionStats>(new SessionStats(session_stats));
       }));
 
@@ -1853,8 +1851,8 @@
   session_stats.transport_stats["TransportName"].channel_stats.push_back(
       channel_stats);
 
-  EXPECT_CALL(test_->session(), GetStats(_)).WillRepeatedly(Invoke(
-      [&session_stats](const ChannelNamePairs&) {
+  EXPECT_CALL(test_->session(), GetSessionStats(_))
+      .WillRepeatedly(Invoke([&session_stats](const ChannelNamePairs&) {
         return std::unique_ptr<SessionStats>(new SessionStats(session_stats));
       }));
   EXPECT_CALL(test_->session(), voice_channel())
@@ -1936,8 +1934,8 @@
   session_stats.transport_stats["TransportName"].channel_stats.push_back(
       channel_stats);
 
-  EXPECT_CALL(test_->session(), GetStats(_)).WillRepeatedly(Invoke(
-      [&session_stats](const ChannelNamePairs&) {
+  EXPECT_CALL(test_->session(), GetSessionStats(_))
+      .WillRepeatedly(Invoke([&session_stats](const ChannelNamePairs&) {
         return std::unique_ptr<SessionStats>(new SessionStats(session_stats));
       }));
   EXPECT_CALL(test_->session(), video_channel())
@@ -2029,8 +2027,8 @@
   session_stats.transport_stats["TransportName"].channel_stats.push_back(
       channel_stats);
 
-  EXPECT_CALL(test_->session(), GetStats(_)).WillRepeatedly(Invoke(
-      [&session_stats](const ChannelNamePairs&) {
+  EXPECT_CALL(test_->session(), GetSessionStats(_))
+      .WillRepeatedly(Invoke([&session_stats](const ChannelNamePairs&) {
         return std::unique_ptr<SessionStats>(new SessionStats(session_stats));
       }));
   EXPECT_CALL(test_->session(), voice_channel())
@@ -2111,8 +2109,8 @@
   session_stats.transport_stats["TransportName"].channel_stats.push_back(
       channel_stats);
 
-  EXPECT_CALL(test_->session(), GetStats(_)).WillRepeatedly(Invoke(
-      [&session_stats](const ChannelNamePairs&) {
+  EXPECT_CALL(test_->session(), GetSessionStats(_))
+      .WillRepeatedly(Invoke([&session_stats](const ChannelNamePairs&) {
         return std::unique_ptr<SessionStats>(new SessionStats(session_stats));
       }));
   EXPECT_CALL(test_->session(), video_channel())
@@ -2192,8 +2190,8 @@
 
 
   // Mock the session to return the desired candidates.
-  EXPECT_CALL(test_->session(), GetStats(_)).WillRepeatedly(Invoke(
-      [&session_stats](const ChannelNamePairs&) {
+  EXPECT_CALL(test_->session(), GetSessionStats(_))
+      .WillRepeatedly(Invoke([&session_stats](const ChannelNamePairs&) {
         return std::unique_ptr<SessionStats>(new SessionStats(session_stats));
       }));
 
diff --git a/pc/statscollector_unittest.cc b/pc/statscollector_unittest.cc
index 48e8959..76e9006 100644
--- a/pc/statscollector_unittest.cc
+++ b/pc/statscollector_unittest.cc
@@ -568,15 +568,13 @@
       : worker_thread_(rtc::Thread::Current()),
         network_thread_(rtc::Thread::Current()),
         media_engine_(new cricket::FakeMediaEngine()),
-        channel_manager_(new cricket::ChannelManager(
-            std::unique_ptr<cricket::MediaEngineInterface>(media_engine_),
-            worker_thread_,
-            network_thread_)),
-
-        session_(channel_manager_.get(), cricket::MediaConfig()) {
+        pc_factory_(new FakePeerConnectionFactory(
+            std::unique_ptr<cricket::MediaEngineInterface>(media_engine_))),
+        pc_(pc_factory_),
+        session_(&pc_) {
     pc_.set_session_for_testing(&session_);
     // By default, we ignore session GetStats calls.
-    EXPECT_CALL(session_, GetStats(_)).WillRepeatedly(ReturnNull());
+    EXPECT_CALL(session_, GetSessionStats(_)).WillRepeatedly(ReturnNull());
     // Add default returns for mock classes.
     EXPECT_CALL(session_, video_channel()).WillRepeatedly(ReturnNull());
     EXPECT_CALL(session_, voice_channel()).WillRepeatedly(ReturnNull());
@@ -684,8 +682,8 @@
 
     // Instruct the session to return stats containing the transport channel.
     InitSessionStats(vc_name);
-    EXPECT_CALL(session_, GetStats(_)).WillRepeatedly(Invoke(
-        [this](const ChannelNamePairs&) {
+    EXPECT_CALL(session_, GetSessionStats(_))
+        .WillRepeatedly(Invoke([this](const ChannelNamePairs&) {
           return std::unique_ptr<SessionStats>(
               new SessionStats(session_stats_));
         }));
@@ -786,8 +784,8 @@
     EXPECT_CALL(session_, GetRemoteSSLCertificate_ReturnsRawPointer(
                               transport_stats.transport_name))
         .WillOnce(Return(remote_cert.release()));
-    EXPECT_CALL(session_, GetStats(_)).WillOnce(Invoke(
-        [&session_stats](const ChannelNamePairs&) {
+    EXPECT_CALL(session_, GetSessionStats(_))
+        .WillOnce(Invoke([&session_stats](const ChannelNamePairs&) {
           return std::unique_ptr<SessionStats>(
               new SessionStats(session_stats));
         }));
@@ -843,11 +841,11 @@
   webrtc::RtcEventLogNullImpl event_log_;
   rtc::Thread* const worker_thread_;
   rtc::Thread* const network_thread_;
-  // |media_engine_| is actually owned by |channel_manager_|.
+  // |media_engine_| is actually owned by |pc_factory_|.
   cricket::FakeMediaEngine* media_engine_;
-  std::unique_ptr<cricket::ChannelManager> channel_manager_;
-  MockWebRtcSession session_;
+  rtc::scoped_refptr<FakePeerConnectionFactory> pc_factory_;
   MockPeerConnection pc_;
+  MockWebRtcSession session_;
   FakeDataChannelProvider data_channel_provider_;
   SessionStats session_stats_;
   rtc::scoped_refptr<webrtc::MediaStream> stream_;
@@ -929,8 +927,8 @@
   const char kVideoChannelName[] = "video";
 
   InitSessionStats(kVideoChannelName);
-  EXPECT_CALL(session_, GetStats(_)).WillRepeatedly(Invoke(
-      [this](const ChannelNamePairs&) {
+  EXPECT_CALL(session_, GetSessionStats(_))
+      .WillRepeatedly(Invoke([this](const ChannelNamePairs&) {
         return std::unique_ptr<SessionStats>(
             new SessionStats(session_stats_));
       }));
@@ -978,7 +976,7 @@
   const char kAudioChannelName[] = "audio";
 
   InitSessionStats(kAudioChannelName);
-  EXPECT_CALL(session_, GetStats(_))
+  EXPECT_CALL(session_, GetSessionStats(_))
       .WillRepeatedly(Invoke([this](const ChannelNamePairs&) {
         return std::unique_ptr<SessionStats>(new SessionStats(session_stats_));
       }));
@@ -1045,8 +1043,8 @@
   const char kVideoChannelName[] = "video";
 
   InitSessionStats(kVideoChannelName);
-  EXPECT_CALL(session_, GetStats(_)).WillRepeatedly(Invoke(
-      [this](const ChannelNamePairs&) {
+  EXPECT_CALL(session_, GetSessionStats(_))
+      .WillRepeatedly(Invoke([this](const ChannelNamePairs&) {
         return std::unique_ptr<SessionStats>(
             new SessionStats(session_stats_));
       }));
@@ -1169,8 +1167,8 @@
 
   const char kVideoChannelName[] = "video";
   InitSessionStats(kVideoChannelName);
-  EXPECT_CALL(session_, GetStats(_)).WillRepeatedly(Invoke(
-      [this](const ChannelNamePairs&) {
+  EXPECT_CALL(session_, GetSessionStats(_))
+      .WillRepeatedly(Invoke([this](const ChannelNamePairs&) {
         return std::unique_ptr<SessionStats>(
             new SessionStats(session_stats_));
       }));
@@ -1268,8 +1266,8 @@
                           Return(true)));
 
   InitSessionStats(kVcName);
-  EXPECT_CALL(session_, GetStats(_)).WillRepeatedly(Invoke(
-      [this](const ChannelNamePairs&) {
+  EXPECT_CALL(session_, GetSessionStats(_))
+      .WillRepeatedly(Invoke([this](const ChannelNamePairs&) {
         return std::unique_ptr<SessionStats>(
             new SessionStats(session_stats_));
       }));
@@ -1341,8 +1339,8 @@
 
   // Instruct the session to return stats containing the transport channel.
   InitSessionStats(kVcName);
-  EXPECT_CALL(session_, GetStats(_)).WillRepeatedly(Invoke(
-      [this](const ChannelNamePairs&) {
+  EXPECT_CALL(session_, GetSessionStats(_))
+      .WillRepeatedly(Invoke([this](const ChannelNamePairs&) {
         return std::unique_ptr<SessionStats>(
             new SessionStats(session_stats_));
       }));
@@ -1386,8 +1384,8 @@
 
   const char kVideoChannelName[] = "video";
   InitSessionStats(kVideoChannelName);
-  EXPECT_CALL(session_, GetStats(_)).WillRepeatedly(Invoke(
-      [this](const ChannelNamePairs&) {
+  EXPECT_CALL(session_, GetSessionStats(_))
+      .WillRepeatedly(Invoke([this](const ChannelNamePairs&) {
         return std::unique_ptr<SessionStats>(
             new SessionStats(session_stats_));
       }));
@@ -1594,8 +1592,8 @@
       transport_stats;
 
   // Configure MockWebRtcSession
-  EXPECT_CALL(session_, GetStats(_)).WillRepeatedly(Invoke(
-      [&session_stats](const ChannelNamePairs&) {
+  EXPECT_CALL(session_, GetSessionStats(_))
+      .WillRepeatedly(Invoke([&session_stats](const ChannelNamePairs&) {
         return std::unique_ptr<SessionStats>(
             new SessionStats(session_stats));
       }));
@@ -1653,8 +1651,8 @@
       transport_stats;
 
   // Configure MockWebRtcSession
-  EXPECT_CALL(session_, GetStats(_)).WillRepeatedly(Invoke(
-      [&session_stats](const ChannelNamePairs&) {
+  EXPECT_CALL(session_, GetSessionStats(_))
+      .WillRepeatedly(Invoke([&session_stats](const ChannelNamePairs&) {
         return std::unique_ptr<SessionStats>(
             new SessionStats(session_stats));
       }));
@@ -1734,8 +1732,8 @@
 
   // Instruct the session to return stats containing the transport channel.
   InitSessionStats(kVcName);
-  EXPECT_CALL(session_, GetStats(_)).WillRepeatedly(Invoke(
-      [this](const ChannelNamePairs&) {
+  EXPECT_CALL(session_, GetSessionStats(_))
+      .WillRepeatedly(Invoke([this](const ChannelNamePairs&) {
         return std::unique_ptr<SessionStats>(
             new SessionStats(session_stats_));
       }));
@@ -1891,8 +1889,8 @@
 
   // Instruct the session to return stats containing the transport channel.
   InitSessionStats(kVcName);
-  EXPECT_CALL(session_, GetStats(_)).WillRepeatedly(Invoke(
-      [this](const ChannelNamePairs&) {
+  EXPECT_CALL(session_, GetSessionStats(_))
+      .WillRepeatedly(Invoke([this](const ChannelNamePairs&) {
         return std::unique_ptr<SessionStats>(
             new SessionStats(session_stats_));
       }));
@@ -1967,8 +1965,8 @@
 
   // Instruct the session to return stats containing the transport channel.
   InitSessionStats(kVcName);
-  EXPECT_CALL(session_, GetStats(_)).WillRepeatedly(Invoke(
-      [this](const ChannelNamePairs&) {
+  EXPECT_CALL(session_, GetSessionStats(_))
+      .WillRepeatedly(Invoke([this](const ChannelNamePairs&) {
         return std::unique_ptr<SessionStats>(
             new SessionStats(session_stats_));
       }));
@@ -2090,8 +2088,8 @@
   const char kVideoChannelName[] = "video";
 
   InitSessionStats(kVideoChannelName);
-  EXPECT_CALL(session_, GetStats(_)).WillRepeatedly(Invoke(
-      [this](const ChannelNamePairs&) {
+  EXPECT_CALL(session_, GetSessionStats(_))
+      .WillRepeatedly(Invoke([this](const ChannelNamePairs&) {
         return std::unique_ptr<SessionStats>(
             new SessionStats(session_stats_));
       }));
@@ -2138,8 +2136,8 @@
   const char kVideoChannelName[] = "video";
 
   InitSessionStats(kVideoChannelName);
-  EXPECT_CALL(session_, GetStats(_)).WillRepeatedly(Invoke(
-      [this](const ChannelNamePairs&) {
+  EXPECT_CALL(session_, GetSessionStats(_))
+      .WillRepeatedly(Invoke([this](const ChannelNamePairs&) {
         return std::unique_ptr<SessionStats>(
             new SessionStats(session_stats_));
       }));
diff --git a/pc/test/mock_peerconnection.h b/pc/test/mock_peerconnection.h
index d57ada8..032adb9 100644
--- a/pc/test/mock_peerconnection.h
+++ b/pc/test/mock_peerconnection.h
@@ -12,6 +12,7 @@
 #define PC_TEST_MOCK_PEERCONNECTION_H_
 
 #include <memory>
+#include <utility>
 #include <vector>
 
 #include "call/call.h"
@@ -26,12 +27,13 @@
 class FakePeerConnectionFactory
     : public rtc::RefCountedObject<webrtc::PeerConnectionFactory> {
  public:
-  FakePeerConnectionFactory()
+  FakePeerConnectionFactory(
+      std::unique_ptr<cricket::MediaEngineInterface> media_engine)
       : rtc::RefCountedObject<webrtc::PeerConnectionFactory>(
             rtc::Thread::Current(),
             rtc::Thread::Current(),
             rtc::Thread::Current(),
-            std::unique_ptr<cricket::MediaEngineInterface>(),
+            std::move(media_engine),
             std::unique_ptr<webrtc::CallFactoryInterface>(),
             std::unique_ptr<RtcEventLogFactoryInterface>()) {}
 };
@@ -39,9 +41,9 @@
 class MockPeerConnection
     : public rtc::RefCountedObject<webrtc::PeerConnection> {
  public:
-  MockPeerConnection()
+  explicit MockPeerConnection(PeerConnectionFactory* factory)
       : rtc::RefCountedObject<webrtc::PeerConnection>(
-            new FakePeerConnectionFactory(),
+            factory,
             std::unique_ptr<RtcEventLog>(),
             std::unique_ptr<Call>()) {}
   MOCK_METHOD0(local_streams,
diff --git a/pc/test/mock_webrtcsession.h b/pc/test/mock_webrtcsession.h
index e027d0b..e965464 100644
--- a/pc/test/mock_webrtcsession.h
+++ b/pc/test/mock_webrtcsession.h
@@ -14,8 +14,9 @@
 #include <memory>
 #include <string>
 
-#include "pc/webrtcsession.h"
 #include "media/sctp/sctptransportinternal.h"
+#include "pc/test/mock_peerconnection.h"
+#include "pc/webrtcsession.h"
 #include "test/gmock.h"
 
 namespace webrtc {
@@ -26,17 +27,9 @@
   // methods don't use any override declarations, and we want to avoid
   // warnings from -Winconsistent-missing-override. See
   // http://crbug.com/428099.
-  explicit MockWebRtcSession(cricket::ChannelManager* channel_manager,
-                             const cricket::MediaConfig& media_config)
+  explicit MockWebRtcSession(PeerConnection* pc)
       : WebRtcSession(
-            nullptr,  // call
-            channel_manager,
-            media_config,
-            nullptr,  // event_log
-            rtc::Thread::Current(),
-            rtc::Thread::Current(),
-            rtc::Thread::Current(),
-            nullptr,
+            pc,
             std::unique_ptr<cricket::TransportController>(
                 new cricket::TransportController(
                     rtc::Thread::Current(),
@@ -52,7 +45,7 @@
   MOCK_METHOD2(GetLocalTrackIdBySsrc, bool(uint32_t, std::string*));
   MOCK_METHOD2(GetRemoteTrackIdBySsrc, bool(uint32_t, std::string*));
   MOCK_METHOD0(GetCallStats, Call::Stats());
-  MOCK_METHOD1(GetStats,
+  MOCK_METHOD1(GetSessionStats,
                std::unique_ptr<SessionStats>(const ChannelNamePairs&));
   MOCK_METHOD2(GetLocalCertificate,
                bool(const std::string& transport_name,
diff --git a/pc/webrtcsession.cc b/pc/webrtcsession.cc
index 477b1ff..cbed1bc 100644
--- a/pc/webrtcsession.cc
+++ b/pc/webrtcsession.cc
@@ -28,6 +28,7 @@
 #include "pc/channel.h"
 #include "pc/channelmanager.h"
 #include "pc/mediasession.h"
+#include "pc/peerconnection.h"
 #include "pc/sctputils.h"
 #include "pc/webrtcsessiondescriptionfactory.h"
 #include "rtc_base/basictypes.h"
@@ -390,26 +391,11 @@
   return BadSdp(source, SessionDescriptionInterface::kAnswer, reason, err_desc);
 }
 
-#define GET_STRING_OF_STATE(state)   \
-  case webrtc::WebRtcSession::state: \
-    result = #state;                 \
-    break;
-
-static std::string GetStateString(webrtc::WebRtcSession::State state) {
-  std::string result;
-  switch (state) {
-    GET_STRING_OF_STATE(STATE_INIT)
-    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_CLOSED)
-    default:
-      RTC_NOTREACHED();
-      break;
-  }
-  return result;
+static std::string BadStateErrMsg(
+    PeerConnectionInterface::SignalingState state) {
+  std::ostringstream desc;
+  desc << "Called in wrong state: " << GetSignalingStateString(state);
+  return desc.str();
 }
 
 #define GET_STRING_OF_ERROR_CODE(err) \
@@ -474,41 +460,22 @@
 }
 
 WebRtcSession::WebRtcSession(
-    Call* call,
-    cricket::ChannelManager* channel_manager,
-    const cricket::MediaConfig& media_config,
-    RtcEventLog* event_log,
-    rtc::Thread* network_thread,
-    rtc::Thread* worker_thread,
-    rtc::Thread* signaling_thread,
-    cricket::PortAllocator* port_allocator,
+    PeerConnection* pc,
     std::unique_ptr<cricket::TransportController> transport_controller,
     std::unique_ptr<cricket::SctpTransportInternalFactory> sctp_factory)
-    : network_thread_(network_thread),
-      worker_thread_(worker_thread),
-      signaling_thread_(signaling_thread),
+    : pc_(pc),
       // 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)),
+      // Due to this constraint session id |session_id| is max limited to
+      // LLONG_MAX.
+      session_id_(rtc::ToString(rtc::CreateRandomId64() & LLONG_MAX)),
       transport_controller_(std::move(transport_controller)),
       sctp_factory_(std::move(sctp_factory)),
-      media_config_(media_config),
-      event_log_(event_log),
-      call_(call),
-      channel_manager_(channel_manager),
-      ice_observer_(NULL),
-      ice_connection_state_(PeerConnectionInterface::kIceConnectionNew),
-      ice_connection_receiving_(true),
-      older_version_remote_peer_(false),
       dtls_enabled_(false),
-      data_channel_type_(cricket::DCT_NONE),
-      metrics_observer_(NULL) {
+      data_channel_type_(cricket::DCT_NONE) {
   transport_controller_->SetIceRole(cricket::ICEROLE_CONTROLLED);
   transport_controller_->SignalConnectionState.connect(
       this, &WebRtcSession::OnTransportControllerConnectionState);
-  transport_controller_->SignalReceiving.connect(
-      this, &WebRtcSession::OnTransportControllerReceiving);
   transport_controller_->SignalGatheringState.connect(
       this, &WebRtcSession::OnTransportControllerGatheringState);
   transport_controller_->SignalCandidatesGathered.connect(
@@ -533,12 +500,12 @@
     DestroyDataChannel();
   }
   if (sctp_transport_) {
-    SignalDataChannelDestroyed();
-    network_thread_->Invoke<void>(
+    pc_->OnDataChannelDestroyed();
+    network_thread()->Invoke<void>(
         RTC_FROM_HERE, rtc::Bind(&WebRtcSession::DestroySctpTransport_n, this));
   }
 
-  LOG(LS_INFO) << "Session: " << id() << " is destroyed.";
+  LOG(LS_INFO) << "Session: " << session_id() << " is destroyed.";
 }
 
 void WebRtcSession::Initialize(
@@ -546,8 +513,6 @@
     std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator,
     const PeerConnectionInterface::RTCConfiguration& rtc_configuration,
     PeerConnection* pc) {
-  bundle_policy_ = rtc_configuration.bundle_policy;
-  rtcp_mux_policy_ = rtc_configuration.rtcp_mux_policy;
   transport_controller_->SetSslMaxProtocolVersion(options.ssl_max_version);
 
   // Obtain a certificate from RTCConfiguration if any were provided (optional).
@@ -607,8 +572,8 @@
   }
 
   webrtc_session_desc_factory_.reset(new WebRtcSessionDescriptionFactory(
-      signaling_thread(), channel_manager_, pc, id(), std::move(cert_generator),
-      certificate));
+      signaling_thread(), pc_->channel_manager(), pc, session_id(),
+      std::move(cert_generator), certificate));
   webrtc_session_desc_factory_->SignalCertificateReady.connect(
       this, &WebRtcSession::OnCertificateReady);
 
@@ -621,9 +586,8 @@
 }
 
 void WebRtcSession::Close() {
-  SetState(STATE_CLOSED);
+  pc_->ChangeSignalingState(PeerConnectionInterface::kClosed);
   RemoveUnusedChannels(nullptr);
-  call_ = nullptr;
   RTC_DCHECK(voice_channels_.empty());
   RTC_DCHECK(video_channels_.empty());
   RTC_DCHECK(!rtp_data_channel_);
@@ -645,6 +609,16 @@
   return nullptr;
 }
 
+rtc::Thread* WebRtcSession::network_thread() const {
+  return pc_->network_thread();
+}
+rtc::Thread* WebRtcSession::worker_thread() const {
+  return pc_->worker_thread();
+}
+rtc::Thread* WebRtcSession::signaling_thread() const {
+  return pc_->signaling_thread();
+}
+
 bool WebRtcSession::GetSctpSslRole(rtc::SSLRole* role) {
   if (!local_description() || !remote_description()) {
     LOG(LS_INFO) << "Local and Remote descriptions must be applied to get the "
@@ -697,9 +671,13 @@
 
   // Update the initial_offerer flag if this session is the initial_offerer.
   Action action = GetAction(desc->type());
-  if (state() == STATE_INIT && action == kOffer) {
-    initial_offerer_ = true;
-    transport_controller_->SetIceRole(cricket::ICEROLE_CONTROLLING);
+  if (!initial_offerer_.has_value()) {
+    initial_offerer_.emplace(action == kOffer);
+    if (*initial_offerer_) {
+      transport_controller_->SetIceRole(cricket::ICEROLE_CONTROLLING);
+    } else {
+      transport_controller_->SetIceRole(cricket::ICEROLE_CONTROLLED);
+    }
   }
 
   if (action == kAnswer) {
@@ -833,8 +811,9 @@
   // read to determine the current checking state. The existing SignalConnecting
   // actually means "gathering candidates", so cannot be be used here.
   if (remote_description()->type() != SessionDescriptionInterface::kOffer &&
-      ice_connection_state_ == PeerConnectionInterface::kIceConnectionNew) {
-    SetIceConnectionState(PeerConnectionInterface::kIceConnectionChecking);
+      pc_->ice_connection_state() ==
+          PeerConnectionInterface::kIceConnectionNew) {
+    pc_->SetIceConnectionState(PeerConnectionInterface::kIceConnectionChecking);
   }
   return true;
 }
@@ -849,28 +828,13 @@
   channels.insert(channels.end(), video_channels_.begin(),
                   video_channels_.end());
   if (rtp_data_channel_) {
-    channels.push_back(rtp_data_channel_.get());
+    channels.push_back(rtp_data_channel_);
   }
   return channels;
 }
 
-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) {
-  RTC_DCHECK(signaling_thread_->IsCurrent());
-  if (state != state_) {
-    LogState(state_, state);
-    state_ = state;
-    SignalState(this, state_);
-  }
-}
-
 void WebRtcSession::SetError(Error error, const std::string& error_desc) {
-  RTC_DCHECK(signaling_thread_->IsCurrent());
+  RTC_DCHECK(signaling_thread()->IsCurrent());
   if (error != error_) {
     error_ = error;
     error_desc_ = error_desc;
@@ -890,8 +854,9 @@
     if (!PushdownTransportDescription(source, cricket::CA_OFFER, &td_err)) {
       return BadOfferSdp(source, MakeTdErrorString(td_err), err_desc);
     }
-    SetState(source == cricket::CS_LOCAL ? STATE_SENTOFFER
-                                         : STATE_RECEIVEDOFFER);
+    pc_->ChangeSignalingState(source == cricket::CS_LOCAL
+                                  ? PeerConnectionInterface::kHaveLocalOffer
+                                  : PeerConnectionInterface::kHaveRemoteOffer);
     if (!PushdownMediaDescription(cricket::CA_OFFER, source, err_desc)) {
       SetError(ERROR_CONTENT, *err_desc);
     }
@@ -903,8 +868,10 @@
       return BadPranswerSdp(source, MakeTdErrorString(td_err), err_desc);
     }
     EnableChannels();
-    SetState(source == cricket::CS_LOCAL ? STATE_SENTPRANSWER
-                                         : STATE_RECEIVEDPRANSWER);
+    pc_->ChangeSignalingState(
+        source == cricket::CS_LOCAL
+            ? PeerConnectionInterface::kHaveLocalPrAnswer
+            : PeerConnectionInterface::kHaveRemotePrAnswer);
     if (!PushdownMediaDescription(cricket::CA_PRANSWER, source, err_desc)) {
       SetError(ERROR_CONTENT, *err_desc);
     }
@@ -933,7 +900,7 @@
       return BadAnswerSdp(source, MakeTdErrorString(td_err), err_desc);
     }
     EnableChannels();
-    SetState(STATE_INPROGRESS);
+    pc_->ChangeSignalingState(PeerConnectionInterface::kStable);
     if (!PushdownMediaDescription(cricket::CA_ANSWER, source, err_desc)) {
       SetError(ERROR_CONTENT, *err_desc);
     }
@@ -989,7 +956,7 @@
   if (sctp_transport_ && local_description() && remote_description() &&
       cricket::GetFirstDataContent(local_description()->description()) &&
       cricket::GetFirstDataContent(remote_description()->description())) {
-    all_success &= network_thread_->Invoke<bool>(
+    all_success &= network_thread()->Invoke<bool>(
         RTC_FROM_HERE,
         rtc::Bind(&WebRtcSession::PushdownSctpParameters_n, this, source));
   }
@@ -997,7 +964,7 @@
 }
 
 bool WebRtcSession::PushdownSctpParameters_n(cricket::ContentSource source) {
-  RTC_DCHECK(network_thread_->IsCurrent());
+  RTC_DCHECK(network_thread()->IsCurrent());
   RTC_DCHECK(local_description());
   RTC_DCHECK(remote_description());
   // Apply the SCTP port (which is hidden inside a DataCodec structure...)
@@ -1133,7 +1100,7 @@
     RTC_DCHECK(sctp_content_name_);
     if (transport_name != *sctp_transport_name_ &&
         bundle.HasContentName(*sctp_content_name_)) {
-      network_thread_->Invoke<void>(
+      network_thread()->Invoke<void>(
           RTC_FROM_HERE, rtc::Bind(&WebRtcSession::ChangeSctpTransport_n, this,
                                    transport_name));
     }
@@ -1261,12 +1228,6 @@
                                   track_id);
 }
 
-std::string WebRtcSession::BadStateErrMsg(State state) {
-  std::ostringstream desc;
-  desc << "Called in wrong state: " << GetStateString(state);
-  return desc.str();
-}
-
 bool WebRtcSession::SendData(const cricket::SendDataParams& params,
                              const rtc::CopyOnWriteBuffer& payload,
                              cricket::SendDataResult* result) {
@@ -1277,7 +1238,7 @@
   }
   return rtp_data_channel_
              ? rtp_data_channel_->SendData(params, payload, result)
-             : network_thread_->Invoke<bool>(
+             : network_thread()->Invoke<bool>(
                    RTC_FROM_HERE,
                    Bind(&cricket::SctpTransportInternal::SendData,
                         sctp_transport_.get(), params, payload, result));
@@ -1327,7 +1288,7 @@
     LOG(LS_ERROR) << "AddSctpDataStream called when sctp_transport_ is NULL.";
     return;
   }
-  network_thread_->Invoke<void>(
+  network_thread()->Invoke<void>(
       RTC_FROM_HERE, rtc::Bind(&cricket::SctpTransportInternal::OpenStream,
                                sctp_transport_.get(), sid));
 }
@@ -1338,7 +1299,7 @@
                   << "NULL.";
     return;
   }
-  network_thread_->Invoke<void>(
+  network_thread()->Invoke<void>(
       RTC_FROM_HERE, rtc::Bind(&cricket::SctpTransportInternal::ResetStream,
                                sctp_transport_.get(), sid));
 }
@@ -1348,7 +1309,7 @@
          sctp_ready_to_send_data_;
 }
 
-std::unique_ptr<SessionStats> WebRtcSession::GetStats_s() {
+std::unique_ptr<SessionStats> WebRtcSession::GetSessionStats_s() {
   RTC_DCHECK(signaling_thread()->IsCurrent());
   ChannelNamePairs channel_name_pairs;
   if (voice_channel()) {
@@ -1370,17 +1331,17 @@
     channel_name_pairs.data = rtc::Optional<ChannelNamePair>(
         ChannelNamePair(*sctp_content_name_, *sctp_transport_name_));
   }
-  return GetStats(channel_name_pairs);
+  return GetSessionStats(channel_name_pairs);
 }
 
-std::unique_ptr<SessionStats> WebRtcSession::GetStats(
+std::unique_ptr<SessionStats> WebRtcSession::GetSessionStats(
     const ChannelNamePairs& channel_name_pairs) {
   if (network_thread()->IsCurrent()) {
-    return GetStats_n(channel_name_pairs);
+    return GetSessionStats_n(channel_name_pairs);
   }
   return network_thread()->Invoke<std::unique_ptr<SessionStats>>(
       RTC_FROM_HERE,
-      rtc::Bind(&WebRtcSession::GetStats_n, this, channel_name_pairs));
+      rtc::Bind(&WebRtcSession::GetSessionStats_n, this, channel_name_pairs));
 }
 
 bool WebRtcSession::GetLocalCertificate(
@@ -1422,31 +1383,6 @@
            rtcp ? kDtlsSrtpSetupFailureRtcp : kDtlsSrtpSetupFailureRtp);
 }
 
-bool WebRtcSession::waiting_for_certificate_for_testing() const {
-  return webrtc_session_desc_factory_->waiting_for_certificate_for_testing();
-}
-
-const rtc::scoped_refptr<rtc::RTCCertificate>&
-WebRtcSession::certificate_for_testing() {
-  return transport_controller_->certificate_for_testing();
-}
-
-void WebRtcSession::SetIceConnectionState(
-      PeerConnectionInterface::IceConnectionState state) {
-  if (ice_connection_state_ == state) {
-    return;
-  }
-
-  LOG(LS_INFO) << "Changing IceConnectionState " << ice_connection_state_
-               << " => " << state;
-  RTC_DCHECK(ice_connection_state_ !=
-             PeerConnectionInterface::kIceConnectionClosed);
-  ice_connection_state_ = state;
-  if (ice_observer_) {
-    ice_observer_->OnIceConnectionStateChange(ice_connection_state_);
-  }
-}
-
 void WebRtcSession::OnTransportControllerConnectionState(
     cricket::IceConnectionState state) {
   switch (state) {
@@ -1457,33 +1393,36 @@
       // kIceConnectionConnecting is currently used as the default,
       // un-connected state by the TransportController, so its only use is
       // detecting disconnections.
-      if (ice_connection_state_ ==
+      if (pc_->ice_connection_state_ ==
               PeerConnectionInterface::kIceConnectionConnected ||
-          ice_connection_state_ ==
+          pc_->ice_connection_state_ ==
               PeerConnectionInterface::kIceConnectionCompleted) {
-        SetIceConnectionState(
+        pc_->SetIceConnectionState(
             PeerConnectionInterface::kIceConnectionDisconnected);
       }
       break;
     case cricket::kIceConnectionFailed:
-      SetIceConnectionState(PeerConnectionInterface::kIceConnectionFailed);
+      pc_->SetIceConnectionState(PeerConnectionInterface::kIceConnectionFailed);
       break;
     case cricket::kIceConnectionConnected:
       LOG(LS_INFO) << "Changing to ICE connected state because "
                    << "all transports are writable.";
-      SetIceConnectionState(PeerConnectionInterface::kIceConnectionConnected);
+      pc_->SetIceConnectionState(
+          PeerConnectionInterface::kIceConnectionConnected);
       break;
     case cricket::kIceConnectionCompleted:
       LOG(LS_INFO) << "Changing to ICE completed state because "
                    << "all transports are complete.";
-      if (ice_connection_state_ !=
+      if (pc_->ice_connection_state_ !=
           PeerConnectionInterface::kIceConnectionConnected) {
         // If jumping directly from "checking" to "connected",
         // signal "connected" first.
-        SetIceConnectionState(PeerConnectionInterface::kIceConnectionConnected);
+        pc_->SetIceConnectionState(
+            PeerConnectionInterface::kIceConnectionConnected);
       }
-      SetIceConnectionState(PeerConnectionInterface::kIceConnectionCompleted);
-      if (metrics_observer_) {
+      pc_->SetIceConnectionState(
+          PeerConnectionInterface::kIceConnectionCompleted);
+      if (pc_->metrics_observer()) {
         ReportTransportStats();
       }
       break;
@@ -1492,20 +1431,6 @@
   }
 }
 
-void WebRtcSession::OnTransportControllerReceiving(bool receiving) {
-  SetIceConnectionReceiving(receiving);
-}
-
-void WebRtcSession::SetIceConnectionReceiving(bool receiving) {
-  if (ice_connection_receiving_ == receiving) {
-    return;
-  }
-  ice_connection_receiving_ = receiving;
-  if (ice_observer_) {
-    ice_observer_->OnIceConnectionReceivingChange(receiving);
-  }
-}
-
 void WebRtcSession::OnTransportControllerCandidatesGathered(
     const std::string& transport_name,
     const cricket::Candidates& candidates) {
@@ -1525,9 +1450,7 @@
     if (local_description()) {
       mutable_local_description()->AddCandidate(candidate.get());
     }
-    if (ice_observer_) {
-      ice_observer_->OnIceCandidate(std::move(candidate));
-    }
+    pc_->OnIceCandidate(std::move(candidate));
   }
 }
 
@@ -1547,15 +1470,13 @@
   if (local_description()) {
     mutable_local_description()->RemoveCandidates(candidates);
   }
-  if (ice_observer_) {
-    ice_observer_->OnIceCandidatesRemoved(candidates);
-  }
+  pc_->OnIceCandidatesRemoved(candidates);
 }
 
 void WebRtcSession::OnTransportControllerDtlsHandshakeError(
     rtc::SSLHandshakeError error) {
-  if (metrics_observer_) {
-    metrics_observer_->IncrementEnumCounter(
+  if (pc_->metrics_observer()) {
+    pc_->metrics_observer()->IncrementEnumCounter(
         webrtc::kEnumCounterDtlsHandshakeError, static_cast<int>(error),
         static_cast<int>(rtc::SSLHandshakeError::MAX_VALUE));
   }
@@ -1644,8 +1565,9 @@
   if (transport_controller_->AddRemoteCandidates(content.name, candidates,
                                                  &error)) {
     // Candidates successfully submitted for checking.
-    if (ice_connection_state_ == PeerConnectionInterface::kIceConnectionNew ||
-        ice_connection_state_ ==
+    if (pc_->ice_connection_state_ ==
+            PeerConnectionInterface::kIceConnectionNew ||
+        pc_->ice_connection_state_ ==
             PeerConnectionInterface::kIceConnectionDisconnected) {
       // If state is New, then the session has just gotten its first remote ICE
       // candidates, so go to Checking.
@@ -1655,7 +1577,8 @@
       // TODO(bemasc): If state is Connected, and the new candidates are for a
       // newly added transport, then the state actually _should_ move to
       // checking.  Add a way to distinguish that case.
-      SetIceConnectionState(PeerConnectionInterface::kIceConnectionChecking);
+      pc_->SetIceConnectionState(
+          PeerConnectionInterface::kIceConnectionChecking);
     }
     // TODO(bemasc): If state is Completed, go back to Connected.
   } else {
@@ -1687,8 +1610,8 @@
       DestroyDataChannel();
     }
     if (sctp_transport_) {
-      SignalDataChannelDestroyed();
-      network_thread_->Invoke<void>(
+      pc_->OnDataChannelDestroyed();
+      network_thread()->Invoke<void>(
           RTC_FROM_HERE,
           rtc::Bind(&WebRtcSession::DestroySctpTransport_n, this));
     }
@@ -1719,7 +1642,8 @@
 bool WebRtcSession::CreateChannels(const SessionDescription* desc) {
   // TODO(steveanton): Add support for multiple audio/video channels.
   const cricket::ContentGroup* bundle_group = nullptr;
-  if (bundle_policy_ == PeerConnectionInterface::kBundlePolicyMaxBundle) {
+  if (pc_->configuration_.bundle_policy ==
+      PeerConnectionInterface::kBundlePolicyMaxBundle) {
     bundle_group = desc->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
     if (!bundle_group) {
       LOG(LS_WARNING) << "max-bundle specified without BUNDLE specified";
@@ -1763,9 +1687,6 @@
   // channels.
   RTC_DCHECK(voice_channels_.empty());
 
-  bool require_rtcp_mux =
-      rtcp_mux_policy_ == PeerConnectionInterface::kRtcpMuxPolicyRequire;
-
   std::string transport_name =
       bundle_transport ? *bundle_transport : content->name;
 
@@ -1773,15 +1694,18 @@
       transport_controller_->CreateDtlsTransport(
           transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
   cricket::DtlsTransportInternal* rtcp_dtls_transport = nullptr;
-  if (!require_rtcp_mux) {
+  if (pc_->configuration_.rtcp_mux_policy !=
+      PeerConnectionInterface::kRtcpMuxPolicyRequire) {
     rtcp_dtls_transport = transport_controller_->CreateDtlsTransport(
         transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
   }
 
-  cricket::VoiceChannel* voice_channel = channel_manager_->CreateVoiceChannel(
-      call_, media_config_, rtp_dtls_transport, rtcp_dtls_transport,
-      transport_controller_->signaling_thread(), content->name, SrtpRequired(),
-      audio_options_);
+  cricket::VoiceChannel* voice_channel =
+      pc_->channel_manager()->CreateVoiceChannel(
+          pc_->call_.get(), pc_->configuration_.media_config,
+          rtp_dtls_transport, rtcp_dtls_transport,
+          transport_controller_->signaling_thread(), content->name,
+          SrtpRequired(), audio_options_);
   if (!voice_channel) {
     transport_controller_->DestroyDtlsTransport(
         transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
@@ -1801,7 +1725,7 @@
 
   // TODO(steveanton): This should signal which voice channel was created since
   // we can have multiple.
-  SignalVoiceChannelCreated();
+  pc_->OnVoiceChannelCreated();
   voice_channel->SignalSentPacket.connect(this, &WebRtcSession::OnSentPacket_w);
   return true;
 }
@@ -1812,9 +1736,6 @@
   // channels.
   RTC_DCHECK(video_channels_.empty());
 
-  bool require_rtcp_mux =
-      rtcp_mux_policy_ == PeerConnectionInterface::kRtcpMuxPolicyRequire;
-
   std::string transport_name =
       bundle_transport ? *bundle_transport : content->name;
 
@@ -1822,15 +1743,18 @@
       transport_controller_->CreateDtlsTransport(
           transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
   cricket::DtlsTransportInternal* rtcp_dtls_transport = nullptr;
-  if (!require_rtcp_mux) {
+  if (pc_->configuration_.rtcp_mux_policy !=
+      PeerConnectionInterface::kRtcpMuxPolicyRequire) {
     rtcp_dtls_transport = transport_controller_->CreateDtlsTransport(
         transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
   }
 
-  cricket::VideoChannel* video_channel = channel_manager_->CreateVideoChannel(
-      call_, media_config_, rtp_dtls_transport, rtcp_dtls_transport,
-      transport_controller_->signaling_thread(), content->name, SrtpRequired(),
-      video_options_);
+  cricket::VideoChannel* video_channel =
+      pc_->channel_manager()->CreateVideoChannel(
+          pc_->call_.get(), pc_->configuration_.media_config,
+          rtp_dtls_transport, rtcp_dtls_transport,
+          transport_controller_->signaling_thread(), content->name,
+          SrtpRequired(), video_options_);
 
   if (!video_channel) {
     transport_controller_->DestroyDtlsTransport(
@@ -1851,7 +1775,7 @@
 
   // TODO(steveanton): This should signal which video channel was created since
   // we can have multiple.
-  SignalVideoChannelCreated();
+  pc_->OnVideoChannelCreated();
   video_channel->SignalSentPacket.connect(this, &WebRtcSession::OnSentPacket_w);
   return true;
 }
@@ -1868,30 +1792,28 @@
              "SCTP support (HAVE_SCTP)";
       return false;
     }
-    if (!network_thread_->Invoke<bool>(
+    if (!network_thread()->Invoke<bool>(
             RTC_FROM_HERE, rtc::Bind(&WebRtcSession::CreateSctpTransport_n,
                                      this, content->name, transport_name))) {
       return false;
     }
   } else {
-    bool require_rtcp_mux =
-        rtcp_mux_policy_ == PeerConnectionInterface::kRtcpMuxPolicyRequire;
-
     std::string transport_name =
         bundle_transport ? *bundle_transport : content->name;
     cricket::DtlsTransportInternal* rtp_dtls_transport =
         transport_controller_->CreateDtlsTransport(
             transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
     cricket::DtlsTransportInternal* rtcp_dtls_transport = nullptr;
-    if (!require_rtcp_mux) {
+    if (pc_->configuration_.rtcp_mux_policy !=
+        PeerConnectionInterface::kRtcpMuxPolicyRequire) {
       rtcp_dtls_transport = transport_controller_->CreateDtlsTransport(
           transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
     }
 
-    rtp_data_channel_.reset(channel_manager_->CreateRtpDataChannel(
-        media_config_, rtp_dtls_transport, rtcp_dtls_transport,
-        transport_controller_->signaling_thread(), content->name,
-        SrtpRequired()));
+    rtp_data_channel_ = pc_->channel_manager()->CreateRtpDataChannel(
+        pc_->configuration_.media_config, rtp_dtls_transport,
+        rtcp_dtls_transport, transport_controller_->signaling_thread(),
+        content->name, SrtpRequired());
 
     if (!rtp_data_channel_) {
       transport_controller_->DestroyDtlsTransport(
@@ -1911,7 +1833,7 @@
                                                 &WebRtcSession::OnSentPacket_w);
   }
 
-  SignalDataChannelCreated();
+  pc_->OnDataChannelCreated();
 
   return true;
 }
@@ -1921,12 +1843,14 @@
     return worker_thread()->Invoke<Call::Stats>(
         RTC_FROM_HERE, rtc::Bind(&WebRtcSession::GetCallStats, this));
   }
-  if (!call_)
+  if (pc_->call_) {
+    return pc_->call_->GetStats();
+  } else {
     return Call::Stats();
-  return call_->GetStats();
+  }
 }
 
-std::unique_ptr<SessionStats> WebRtcSession::GetStats_n(
+std::unique_ptr<SessionStats> WebRtcSession::GetSessionStats_n(
     const ChannelNamePairs& channel_name_pairs) {
   RTC_DCHECK(network_thread()->IsCurrent());
   std::unique_ptr<SessionStats> session_stats(new SessionStats());
@@ -1950,7 +1874,7 @@
 
 bool WebRtcSession::CreateSctpTransport_n(const std::string& content_name,
                                           const std::string& transport_name) {
-  RTC_DCHECK(network_thread_->IsCurrent());
+  RTC_DCHECK(network_thread()->IsCurrent());
   RTC_DCHECK(sctp_factory_);
   cricket::DtlsTransportInternal* tc =
       transport_controller_->CreateDtlsTransport_n(
@@ -1970,7 +1894,7 @@
 }
 
 void WebRtcSession::ChangeSctpTransport_n(const std::string& transport_name) {
-  RTC_DCHECK(network_thread_->IsCurrent());
+  RTC_DCHECK(network_thread()->IsCurrent());
   RTC_DCHECK(sctp_transport_);
   RTC_DCHECK(sctp_transport_name_);
   std::string old_sctp_transport_name = *sctp_transport_name_;
@@ -1984,7 +1908,7 @@
 }
 
 void WebRtcSession::DestroySctpTransport_n() {
-  RTC_DCHECK(network_thread_->IsCurrent());
+  RTC_DCHECK(network_thread()->IsCurrent());
   sctp_transport_.reset(nullptr);
   sctp_content_name_.reset();
   sctp_transport_name_.reset();
@@ -1994,14 +1918,14 @@
 
 void WebRtcSession::OnSctpTransportReadyToSendData_n() {
   RTC_DCHECK(data_channel_type_ == cricket::DCT_SCTP);
-  RTC_DCHECK(network_thread_->IsCurrent());
+  RTC_DCHECK(network_thread()->IsCurrent());
   sctp_invoker_->AsyncInvoke<void>(
-      RTC_FROM_HERE, signaling_thread_,
+      RTC_FROM_HERE, signaling_thread(),
       rtc::Bind(&WebRtcSession::OnSctpTransportReadyToSendData_s, this, true));
 }
 
 void WebRtcSession::OnSctpTransportReadyToSendData_s(bool ready) {
-  RTC_DCHECK(signaling_thread_->IsCurrent());
+  RTC_DCHECK(signaling_thread()->IsCurrent());
   sctp_ready_to_send_data_ = ready;
   SignalSctpReadyToSendData(ready);
 }
@@ -2010,9 +1934,9 @@
     const cricket::ReceiveDataParams& params,
     const rtc::CopyOnWriteBuffer& payload) {
   RTC_DCHECK(data_channel_type_ == cricket::DCT_SCTP);
-  RTC_DCHECK(network_thread_->IsCurrent());
+  RTC_DCHECK(network_thread()->IsCurrent());
   sctp_invoker_->AsyncInvoke<void>(
-      RTC_FROM_HERE, signaling_thread_,
+      RTC_FROM_HERE, signaling_thread(),
       rtc::Bind(&WebRtcSession::OnSctpTransportDataReceived_s, this, params,
                 payload));
 }
@@ -2020,7 +1944,7 @@
 void WebRtcSession::OnSctpTransportDataReceived_s(
     const cricket::ReceiveDataParams& params,
     const rtc::CopyOnWriteBuffer& payload) {
-  RTC_DCHECK(signaling_thread_->IsCurrent());
+  RTC_DCHECK(signaling_thread()->IsCurrent());
   if (params.type == cricket::DMT_CONTROL && IsOpenMessage(payload)) {
     // Received OPEN message; parse and signal that a new data channel should
     // be created.
@@ -2033,7 +1957,7 @@
       return;
     }
     config.open_handshake_role = InternalDataChannelInit::kAcker;
-    SignalDataChannelOpenMessage(label, config);
+    pc_->OnDataChannelOpenMessage(label, config);
   } else {
     // Otherwise just forward the signal.
     SignalSctpDataReceived(params, payload);
@@ -2042,9 +1966,9 @@
 
 void WebRtcSession::OnSctpStreamClosedRemotely_n(int sid) {
   RTC_DCHECK(data_channel_type_ == cricket::DCT_SCTP);
-  RTC_DCHECK(network_thread_->IsCurrent());
+  RTC_DCHECK(network_thread()->IsCurrent());
   sctp_invoker_->AsyncInvoke<void>(
-      RTC_FROM_HERE, signaling_thread_,
+      RTC_FROM_HERE, signaling_thread(),
       rtc::Bind(&sigslot::signal1<int>::operator(),
                 &SignalSctpStreamClosedRemotely, sid));
 }
@@ -2097,10 +2021,12 @@
   Action action = GetAction(sdesc->type());
   if (source == cricket::CS_LOCAL) {
     if (!ExpectSetLocalDescription(action))
-      return BadLocalSdp(type, BadStateErrMsg(state()), err_desc);
+      return BadLocalSdp(type, BadStateErrMsg(pc_->signaling_state()),
+                         err_desc);
   } else {
     if (!ExpectSetRemoteDescription(action))
-      return BadRemoteSdp(type, BadStateErrMsg(state()), err_desc);
+      return BadRemoteSdp(type, BadStateErrMsg(pc_->signaling_state()),
+                          err_desc);
   }
 
   // Verify crypto settings.
@@ -2151,29 +2077,25 @@
 }
 
 bool WebRtcSession::ExpectSetLocalDescription(Action action) {
-  return ((action == kOffer && state() == STATE_INIT) ||
-          // update local offer
-          (action == kOffer && state() == STATE_SENTOFFER) ||
-          // update the current ongoing session.
-          (action == kOffer && state() == STATE_INPROGRESS) ||
-          // accept remote offer
-          (action == kAnswer && state() == STATE_RECEIVEDOFFER) ||
-          (action == kAnswer && state() == STATE_SENTPRANSWER) ||
-          (action == kPrAnswer && state() == STATE_RECEIVEDOFFER) ||
-          (action == kPrAnswer && state() == STATE_SENTPRANSWER));
+  PeerConnectionInterface::SignalingState state = pc_->signaling_state();
+  if (action == kOffer) {
+    return (state == PeerConnectionInterface::kStable) ||
+           (state == PeerConnectionInterface::kHaveLocalOffer);
+  } else {  // Answer or PrAnswer
+    return (state == PeerConnectionInterface::kHaveRemoteOffer) ||
+           (state == PeerConnectionInterface::kHaveLocalPrAnswer);
+  }
 }
 
 bool WebRtcSession::ExpectSetRemoteDescription(Action action) {
-  return ((action == kOffer && state() == STATE_INIT) ||
-          // update remote offer
-          (action == kOffer && state() == STATE_RECEIVEDOFFER) ||
-          // update the current ongoing session
-          (action == kOffer && state() == STATE_INPROGRESS) ||
-          // accept local offer
-          (action == kAnswer && state() == STATE_SENTOFFER) ||
-          (action == kAnswer && state() == STATE_RECEIVEDPRANSWER) ||
-          (action == kPrAnswer && state() == STATE_SENTOFFER) ||
-          (action == kPrAnswer && state() == STATE_RECEIVEDPRANSWER));
+  PeerConnectionInterface::SignalingState state = pc_->signaling_state();
+  if (action == kOffer) {
+    return (state == PeerConnectionInterface::kStable) ||
+           (state == PeerConnectionInterface::kHaveRemoteOffer);
+  } else {  // Answer or PrAnswer.
+    return (state == PeerConnectionInterface::kHaveLocalOffer) ||
+           (state == PeerConnectionInterface::kHaveRemotePrAnswer);
+  }
 }
 
 std::string WebRtcSession::GetSessionErrorMsg() {
@@ -2232,15 +2154,9 @@
     cricket::IceGatheringState state) {
   RTC_DCHECK(signaling_thread()->IsCurrent());
   if (state == cricket::kIceGatheringGathering) {
-    if (ice_observer_) {
-      ice_observer_->OnIceGatheringChange(
-          PeerConnectionInterface::kIceGatheringGathering);
-    }
+    pc_->OnIceGatheringChange(PeerConnectionInterface::kIceGatheringGathering);
   } else if (state == cricket::kIceGatheringComplete) {
-    if (ice_observer_) {
-      ice_observer_->OnIceGatheringChange(
-          PeerConnectionInterface::kIceGatheringComplete);
-    }
+    pc_->OnIceGatheringChange(PeerConnectionInterface::kIceGatheringComplete);
   }
 }
 
@@ -2272,7 +2188,7 @@
 // for IPv4 and IPv6.
 void WebRtcSession::ReportBestConnectionState(
     const cricket::TransportStats& stats) {
-  RTC_DCHECK(metrics_observer_ != NULL);
+  RTC_DCHECK(pc_->metrics_observer());
   for (cricket::TransportChannelStatsList::const_iterator it =
          stats.channel_stats.begin();
        it != stats.channel_stats.end(); ++it) {
@@ -2297,18 +2213,18 @@
       } else {
         RTC_CHECK(0);
       }
-      metrics_observer_->IncrementEnumCounter(
+      pc_->metrics_observer()->IncrementEnumCounter(
           type, GetIceCandidatePairCounter(local, remote),
           kIceCandidatePairMax);
 
       // Increment the counter for IP type.
       if (local.address().family() == AF_INET) {
-        metrics_observer_->IncrementEnumCounter(
+        pc_->metrics_observer()->IncrementEnumCounter(
             kEnumCounterAddressFamily, kBestConnections_IPv4,
             kPeerConnectionAddressFamilyCounter_Max);
 
       } else if (local.address().family() == AF_INET6) {
-        metrics_observer_->IncrementEnumCounter(
+        pc_->metrics_observer()->IncrementEnumCounter(
             kEnumCounterAddressFamily, kBestConnections_IPv6,
             kPeerConnectionAddressFamilyCounter_Max);
       } else {
@@ -2322,7 +2238,7 @@
 
 void WebRtcSession::ReportNegotiatedCiphers(
     const cricket::TransportStats& stats) {
-  RTC_DCHECK(metrics_observer_ != NULL);
+  RTC_DCHECK(pc_->metrics_observer());
   if (!dtls_enabled_ || stats.channel_stats.empty()) {
     return;
   }
@@ -2351,19 +2267,19 @@
   }
 
   if (srtp_crypto_suite != rtc::SRTP_INVALID_CRYPTO_SUITE) {
-    metrics_observer_->IncrementSparseEnumCounter(srtp_counter_type,
-                                                  srtp_crypto_suite);
+    pc_->metrics_observer()->IncrementSparseEnumCounter(srtp_counter_type,
+                                                        srtp_crypto_suite);
   }
   if (ssl_cipher_suite != rtc::TLS_NULL_WITH_NULL_NULL) {
-    metrics_observer_->IncrementSparseEnumCounter(ssl_counter_type,
-                                                  ssl_cipher_suite);
+    pc_->metrics_observer()->IncrementSparseEnumCounter(ssl_counter_type,
+                                                        ssl_cipher_suite);
   }
 }
 
 void WebRtcSession::OnSentPacket_w(const rtc::SentPacket& sent_packet) {
   RTC_DCHECK(worker_thread()->IsCurrent());
-  RTC_DCHECK(call_);
-  call_->OnSentPacket(sent_packet);
+  RTC_DCHECK(pc_->call_);
+  pc_->call_->OnSentPacket(sent_packet);
 }
 
 const std::string WebRtcSession::GetTransportName(
@@ -2404,7 +2320,7 @@
 void WebRtcSession::DestroyVideoChannel(cricket::VideoChannel* video_channel) {
   // TODO(steveanton): This should take an identifier for the video channel
   // since we now support more than one.
-  SignalVideoChannelDestroyed();
+  pc_->OnVideoChannelDestroyed();
   RTC_DCHECK(video_channel->rtp_dtls_transport());
   const std::string transport_name =
       video_channel->rtp_dtls_transport()->transport_name();
@@ -2412,7 +2328,7 @@
       (video_channel->rtcp_dtls_transport() != nullptr);
   // The above need to be cached before destroying the video channel so that we
   // do not access uninitialized memory.
-  channel_manager_->DestroyVideoChannel(video_channel);
+  pc_->channel_manager()->DestroyVideoChannel(video_channel);
   transport_controller_->DestroyDtlsTransport(
       transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
   if (need_to_delete_rtcp) {
@@ -2436,7 +2352,7 @@
 void WebRtcSession::DestroyVoiceChannel(cricket::VoiceChannel* voice_channel) {
   // TODO(steveanton): This should take an identifier for the voice channel
   // since we now support more than one.
-  SignalVoiceChannelDestroyed();
+  pc_->OnVoiceChannelDestroyed();
   RTC_DCHECK(voice_channel->rtp_dtls_transport());
   const std::string transport_name =
       voice_channel->rtp_dtls_transport()->transport_name();
@@ -2444,7 +2360,7 @@
       (voice_channel->rtcp_dtls_transport() != nullptr);
   // The above need to be cached before destroying the video channel so that we
   // do not access uninitialized memory.
-  channel_manager_->DestroyVoiceChannel(voice_channel);
+  pc_->channel_manager()->DestroyVoiceChannel(voice_channel);
   transport_controller_->DestroyDtlsTransport(
       transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
   if (need_to_delete_rtcp) {
@@ -2454,13 +2370,14 @@
 }
 
 void WebRtcSession::DestroyDataChannel() {
-  SignalDataChannelDestroyed();
+  pc_->OnDataChannelDestroyed();
   RTC_DCHECK(rtp_data_channel_->rtp_dtls_transport());
   std::string transport_name;
   transport_name = rtp_data_channel_->rtp_dtls_transport()->transport_name();
   bool need_to_delete_rtcp =
       (rtp_data_channel_->rtcp_dtls_transport() != nullptr);
-  channel_manager_->DestroyRtpDataChannel(rtp_data_channel_.release());
+  pc_->channel_manager()->DestroyRtpDataChannel(rtp_data_channel_);
+  rtp_data_channel_ = nullptr;
   transport_controller_->DestroyDtlsTransport(
       transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
   if (need_to_delete_rtcp) {
diff --git a/pc/webrtcsession.h b/pc/webrtcsession.h
index 09e5a3e..00c4a5c 100644
--- a/pc/webrtcsession.h
+++ b/pc/webrtcsession.h
@@ -51,55 +51,6 @@
 class RtcEventLog;
 class WebRtcSessionDescriptionFactory;
 
-extern const char kBundleWithoutRtcpMux[];
-extern const char kCreateChannelFailed[];
-extern const char kInvalidCandidates[];
-extern const char kInvalidSdp[];
-extern const char kMlineMismatchInAnswer[];
-extern const char kMlineMismatchInSubsequentOffer[];
-extern const char kPushDownTDFailed[];
-extern const char kSdpWithoutDtlsFingerprint[];
-extern const char kSdpWithoutSdesCrypto[];
-extern const char kSdpWithoutIceUfragPwd[];
-extern const char kSdpWithoutSdesAndDtlsDisabled[];
-extern const char kSessionError[];
-extern const char kSessionErrorDesc[];
-extern const char kDtlsSrtpSetupFailureRtp[];
-extern const char kDtlsSrtpSetupFailureRtcp[];
-extern const char kEnableBundleFailed[];
-
-// Maximum number of received video streams that will be processed by webrtc
-// even if they are not signalled beforehand.
-extern const int kMaxUnsignalledRecvStreams;
-
-// ICE state callback interface.
-class IceObserver {
- public:
-  IceObserver() {}
-  // Called any time the IceConnectionState changes
-  virtual void OnIceConnectionStateChange(
-      PeerConnectionInterface::IceConnectionState new_state) {}
-  // Called any time the IceGatheringState changes
-  virtual void OnIceGatheringChange(
-      PeerConnectionInterface::IceGatheringState new_state) {}
-  // New Ice candidate have been found.
-  virtual void OnIceCandidate(
-      std::unique_ptr<IceCandidateInterface> candidate) = 0;
-
-  // Some local ICE candidates have been removed.
-  virtual void OnIceCandidatesRemoved(
-      const std::vector<cricket::Candidate>& candidates) = 0;
-
-  // Called whenever the state changes between receiving and not receiving.
-  virtual void OnIceConnectionReceivingChange(bool receiving) {}
-
- protected:
-  ~IceObserver() {}
-
- private:
-  RTC_DISALLOW_COPY_AND_ASSIGN(IceObserver);
-};
-
 // Statistics for all the transports of the session.
 // TODO(pthatcher): Think of a better name for this.  We already have
 // a TransportStats in transport.h.  Perhaps TransportsStats?
@@ -133,16 +84,6 @@
     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
@@ -151,25 +92,18 @@
 
   // |sctp_factory| may be null, in which case SCTP is treated as unsupported.
   WebRtcSession(
-      Call* call,
-      cricket::ChannelManager* channel_manager,
-      const cricket::MediaConfig& media_config,
-      RtcEventLog* event_log,
-      rtc::Thread* network_thread,
-      rtc::Thread* worker_thread,
-      rtc::Thread* signaling_thread,
-      cricket::PortAllocator* port_allocator,
+      PeerConnection* pc,  // TODO(steveanton): Temporary.
       std::unique_ptr<cricket::TransportController> transport_controller,
       std::unique_ptr<cricket::SctpTransportInternalFactory> sctp_factory);
   virtual ~WebRtcSession();
 
   // These are const to allow them to be called from const methods.
-  rtc::Thread* network_thread() const { return network_thread_; }
-  rtc::Thread* worker_thread() const { return worker_thread_; }
-  rtc::Thread* signaling_thread() const { return signaling_thread_; }
+  rtc::Thread* network_thread() const;
+  rtc::Thread* worker_thread() const;
+  rtc::Thread* signaling_thread() const;
 
   // The ID of this session.
-  const std::string& id() const { return sid_; }
+  const std::string& session_id() const { return session_id_; }
 
   void Initialize(
       const PeerConnectionFactoryInterface::Options& options,
@@ -181,21 +115,12 @@
   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;
+  bool initial_offerer() const { return initial_offerer_ && *initial_offerer_; }
 
   // 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;
-  }
-
   // Exposed for stats collecting.
   // TODO(steveanton): Switch callers to use the plural form and remove these.
   virtual cricket::VoiceChannel* voice_channel() {
@@ -222,7 +147,7 @@
 
   // Only valid when using deprecated RTP data channels.
   virtual cricket::RtpDataChannel* rtp_data_channel() {
-    return rtp_data_channel_.get();
+    return rtp_data_channel_;
   }
   virtual rtc::Optional<std::string> sctp_content_name() const {
     return sctp_content_name_;
@@ -309,8 +234,8 @@
   // called on the signaling thread - and invokes the other |GetStats|. The
   // other |GetStats| can be invoked on any thread; if not invoked on the
   // network thread a thread hop will happen.
-  std::unique_ptr<SessionStats> GetStats_s();
-  virtual std::unique_ptr<SessionStats> GetStats(
+  std::unique_ptr<SessionStats> GetSessionStats_s();
+  virtual std::unique_ptr<SessionStats> GetSessionStats(
       const ChannelNamePairs& channel_name_pairs);
 
   // virtual so it can be mocked in unit tests
@@ -343,31 +268,10 @@
       const rtc::scoped_refptr<rtc::RTCCertificate>& certificate);
   void OnDtlsSrtpSetupFailure(cricket::BaseChannel*, bool rtcp);
 
-  // For unit test.
-  bool waiting_for_certificate_for_testing() const;
-  const rtc::scoped_refptr<rtc::RTCCertificate>& certificate_for_testing();
-
-  void set_metrics_observer(
-      webrtc::MetricsObserverInterface* metrics_observer) {
-    metrics_observer_ = metrics_observer;
-    transport_controller_->SetMetricsObserver(metrics_observer);
+  cricket::TransportController* transport_controller() const {
+    return transport_controller_.get();
   }
 
-  // Called when voice_channel_, video_channel_ and
-  // rtp_data_channel_/sctp_transport_ are created and destroyed. As a result
-  // of, for example, setting a new description.
-  sigslot::signal0<> SignalVoiceChannelCreated;
-  sigslot::signal0<> SignalVoiceChannelDestroyed;
-  sigslot::signal0<> SignalVideoChannelCreated;
-  sigslot::signal0<> SignalVideoChannelDestroyed;
-  sigslot::signal0<> SignalDataChannelCreated;
-  sigslot::signal0<> SignalDataChannelDestroyed;
-
-  // Called when a valid data channel OPEN message is received.
-  // std::string represents the data channel label.
-  sigslot::signal2<const std::string&, const InternalDataChannelInit&>
-      SignalDataChannelOpenMessage;
-
  private:
   // Indicates the type of SessionDescription in a call to SetLocalDescription
   // and SetRemoteDescription.
@@ -377,6 +281,11 @@
     kAnswer,
   };
 
+  // TODO(steveanton): Remove this once WebRtcSession and PeerConnection are
+  // merged. This is so that we can eliminate signals from this class and
+  // directly call the method in PeerConnection they are connected to.
+  PeerConnection* pc_;
+
   // Return all managed, non-null channels.
   std::vector<cricket::BaseChannel*> Channels() const;
 
@@ -391,19 +300,12 @@
                                        : current_remote_description_.get();
   }
 
-  // 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);
+  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);
+  Action GetAction(const std::string& type);
   // Push the media parts of the local or remote session description
   // down to all of the channels.
   bool PushdownMediaDescription(cricket::ContentAction action,
@@ -471,7 +373,7 @@
   bool CreateDataChannel(const cricket::ContentInfo* content,
                          const std::string* bundle_transport);
 
-  std::unique_ptr<SessionStats> GetStats_n(
+  std::unique_ptr<SessionStats> GetSessionStats_n(
       const ChannelNamePairs& channel_name_pairs);
 
   bool CreateSctpTransport_n(const std::string& content_name,
@@ -493,10 +395,6 @@
                                      const rtc::CopyOnWriteBuffer& payload);
   void OnSctpStreamClosedRemotely_n(int sid);
 
-  std::string BadStateErrMsg(State state);
-  void SetIceConnectionState(PeerConnectionInterface::IceConnectionState state);
-  void SetIceConnectionReceiving(bool receiving);
-
   bool ValidateBundleSettings(const cricket::SessionDescription* desc);
   bool HasRtcpMuxEnabled(const cricket::ContentInfo* content);
   // Below methods are helper methods which verifies SDP.
@@ -526,7 +424,6 @@
 
   // TransportController signal handlers.
   void OnTransportControllerConnectionState(cricket::IceConnectionState state);
-  void OnTransportControllerReceiving(bool receiving);
   void OnTransportControllerGatheringState(cricket::IceGatheringState state);
   void OnTransportControllerCandidatesGathered(
       const std::string& transport_name,
@@ -557,22 +454,14 @@
   void DestroyVoiceChannel(cricket::VoiceChannel* voice_channel);
   void DestroyDataChannel();
 
-  rtc::Thread* const network_thread_;
-  rtc::Thread* const worker_thread_;
-  rtc::Thread* const signaling_thread_;
-
-  State state_ = STATE_INIT;
   Error error_ = ERROR_NONE;
   std::string error_desc_;
 
-  const std::string sid_;
-  bool initial_offerer_ = false;
+  const std::string session_id_;
+  rtc::Optional<bool> initial_offerer_;
 
   const std::unique_ptr<cricket::TransportController> transport_controller_;
   const std::unique_ptr<cricket::SctpTransportInternalFactory> sctp_factory_;
-  const cricket::MediaConfig media_config_;
-  RtcEventLog* event_log_;
-  Call* call_;
   // TODO(steveanton): voice_channels_ and video_channels_ used to be a single
   // VoiceChannel/VideoChannel respectively but are being changed to support
   // multiple m= lines in unified plan. But until more work is done, these can
@@ -582,10 +471,7 @@
   std::vector<cricket::VideoChannel*> video_channels_;
   // |rtp_data_channel_| is used if in RTP data channel mode, |sctp_transport_|
   // when using SCTP.
-  // TODO(steveanton): This should be changed to a bare pointer because
-  // WebRtcSession doesn't actually own the RtpDataChannel
-  // (ChannelManager does).
-  std::unique_ptr<cricket::RtpDataChannel> rtp_data_channel_;
+  cricket::RtpDataChannel* rtp_data_channel_ = nullptr;
 
   std::unique_ptr<cricket::SctpTransportInternal> sctp_transport_;
   // |sctp_transport_name_| keeps track of what DTLS transport the SCTP
@@ -612,16 +498,10 @@
       SignalSctpDataReceived;
   sigslot::signal1<int> SignalSctpStreamClosedRemotely;
 
-  cricket::ChannelManager* channel_manager_;
-  IceObserver* ice_observer_;
-  PeerConnectionInterface::IceConnectionState ice_connection_state_;
-  bool ice_connection_receiving_;
   std::unique_ptr<SessionDescriptionInterface> current_local_description_;
   std::unique_ptr<SessionDescriptionInterface> pending_local_description_;
   std::unique_ptr<SessionDescriptionInterface> current_remote_description_;
   std::unique_ptr<SessionDescriptionInterface> pending_remote_description_;
-  // If the remote peer is using a older version of implementation.
-  bool older_version_remote_peer_;
   bool dtls_enabled_;
   // Specifies which kind of data channel is allowed. This is controlled
   // by the chrome command-line flag and constraints:
@@ -639,16 +519,6 @@
   // Member variables for caching global options.
   cricket::AudioOptions audio_options_;
   cricket::VideoOptions video_options_;
-  MetricsObserverInterface* metrics_observer_;
-
-  // Declares the bundle policy for the WebRTCSession.
-  PeerConnectionInterface::BundlePolicy bundle_policy_;
-
-  // Declares the RTCP mux policy for the WebRTCSession.
-  PeerConnectionInterface::RtcpMuxPolicy rtcp_mux_policy_;
-
-  bool received_first_video_packet_ = false;
-  bool received_first_audio_packet_ = false;
 
   RTC_DISALLOW_COPY_AND_ASSIGN(WebRtcSession);
 };