Fix two bugs in DataChannel state transition.
1. OnStateChange should not be fired if state is not changed.
2. RemotePeerRequestClose should be a no-op if it's already closed.

TBR=pthatcher@webrtc.org
BUG=

Review URL: https://webrtc-codereview.appspot.com/21559004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@6290 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/app/webrtc/datachannel.cc b/talk/app/webrtc/datachannel.cc
index ef20269..14caa41 100644
--- a/talk/app/webrtc/datachannel.cc
+++ b/talk/app/webrtc/datachannel.cc
@@ -370,6 +370,9 @@
 }
 
 void DataChannel::DoClose() {
+  if (state_ == kClosed)
+    return;
+
   receive_ssrc_set_ = false;
   send_ssrc_set_ = false;
   SetState(kClosing);
@@ -412,6 +415,9 @@
 }
 
 void DataChannel::SetState(DataState state) {
+  if (state_ == state)
+    return;
+
   state_ = state;
   if (observer_) {
     observer_->OnStateChange();
diff --git a/talk/app/webrtc/datachannel_unittest.cc b/talk/app/webrtc/datachannel_unittest.cc
index e132fb1..991ae0c 100644
--- a/talk/app/webrtc/datachannel_unittest.cc
+++ b/talk/app/webrtc/datachannel_unittest.cc
@@ -34,9 +34,13 @@
 
 class FakeDataChannelObserver : public webrtc::DataChannelObserver {
  public:
-  FakeDataChannelObserver() : messages_received_(0) {}
+  FakeDataChannelObserver()
+      : messages_received_(0), on_state_change_count_(0) {}
 
-  void OnStateChange() {}
+  void OnStateChange() {
+    ++on_state_change_count_;
+  }
+
   void OnMessage(const webrtc::DataBuffer& buffer) {
     ++messages_received_;
   }
@@ -45,8 +49,17 @@
     return messages_received_;
   }
 
+  void ResetOnStateChangeCount() {
+    on_state_change_count_ = 0;
+  }
+
+  size_t on_state_change_count() const {
+    return on_state_change_count_;
+  }
+
  private:
   size_t messages_received_;
+  size_t on_state_change_count_;
 };
 
 class SctpDataChannelTest : public testing::Test {
@@ -339,3 +352,27 @@
   EXPECT_EQ(webrtc::DataChannelInterface::kClosed,
             webrtc_data_channel_->state());
 }
+
+// Tests that a already closed DataChannel does not fire onStateChange again.
+TEST_F(SctpDataChannelTest, ClosedDataChannelDoesNotFireOnStateChange) {
+  AddObserver();
+  webrtc_data_channel_->Close();
+  // OnStateChange called for kClosing and kClosed.
+  EXPECT_EQ(2U, observer_->on_state_change_count());
+
+  observer_->ResetOnStateChangeCount();
+  webrtc_data_channel_->RemotePeerRequestClose();
+  EXPECT_EQ(0U, observer_->on_state_change_count());
+}
+
+// Tests that RemotePeerRequestClose closes the local DataChannel.
+TEST_F(SctpDataChannelTest, RemotePeerRequestClose) {
+  AddObserver();
+  webrtc_data_channel_->RemotePeerRequestClose();
+
+  // OnStateChange called for kClosing and kClosed.
+  EXPECT_EQ(2U, observer_->on_state_change_count());
+  EXPECT_EQ(webrtc::DataChannelInterface::kClosed,
+            webrtc_data_channel_->state());
+}
+