Change the PeerConnection proxy templates to use blocking method calls instead of using Thread::Send.
The problem with Thread::Send is that it processes incoming pending messages and for the proxies,
this can mean that multiple incoming calls can concurrently run on the same thread, resulting in unexpected behavior.

See e.g. crbug.com/429740 (and more)

R=perkj@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@7607 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/app/webrtc/proxy.h b/talk/app/webrtc/proxy.h
index 0c21ef9..134f580 100644
--- a/talk/app/webrtc/proxy.h
+++ b/talk/app/webrtc/proxy.h
@@ -55,6 +55,7 @@
 #ifndef TALK_APP_WEBRTC_PROXY_H_
 #define TALK_APP_WEBRTC_PROXY_H_
 
+#include "webrtc/base/event.h"
 #include "webrtc/base/thread.h"
 
 namespace webrtc {
@@ -92,6 +93,34 @@
   void value() {}
 };
 
+namespace internal {
+
+class SynchronousMethodCall
+    : public rtc::MessageData,
+      public rtc::MessageHandler {
+ public:
+  SynchronousMethodCall(rtc::MessageHandler* proxy)
+      : e_(), proxy_(proxy) {}
+  ~SynchronousMethodCall() {}
+
+  void Invoke(rtc::Thread* t) {
+    if (t->IsCurrent()) {
+      proxy_->OnMessage(NULL);
+    } else {
+      e_.reset(new rtc::Event(false, false));
+      t->Post(this, 0);
+      e_->Wait(rtc::kForever);
+    }
+  }
+
+ private:
+  void OnMessage(rtc::Message*) { proxy_->OnMessage(NULL); e_->Set(); }
+  rtc::scoped_ptr<rtc::Event> e_;
+  rtc::MessageHandler* proxy_;
+};
+
+}  // internal
+
 template <typename C, typename R>
 class MethodCall0 : public rtc::Message,
                     public rtc::MessageHandler {
@@ -100,12 +129,12 @@
   MethodCall0(C* c, Method m) : c_(c), m_(m) {}
 
   R Marshal(rtc::Thread* t) {
-    t->Send(this, 0);
+    internal::SynchronousMethodCall(this).Invoke(t);
     return r_.value();
   }
 
  private:
-  void OnMessage(rtc::Message*) {  r_.Invoke(c_, m_);}
+  void OnMessage(rtc::Message*) {  r_.Invoke(c_, m_); }
 
   C* c_;
   Method m_;
@@ -120,7 +149,7 @@
   ConstMethodCall0(C* c, Method m) : c_(c), m_(m) {}
 
   R Marshal(rtc::Thread* t) {
-    t->Send(this, 0);
+    internal::SynchronousMethodCall(this).Invoke(t);
     return r_.value();
   }
 
@@ -140,7 +169,7 @@
   MethodCall1(C* c, Method m, T1 a1) : c_(c), m_(m), a1_(a1) {}
 
   R Marshal(rtc::Thread* t) {
-    t->Send(this, 0);
+    internal::SynchronousMethodCall(this).Invoke(t);
     return r_.value();
   }
 
@@ -161,7 +190,7 @@
   ConstMethodCall1(C* c, Method m, T1 a1) : c_(c), m_(m), a1_(a1) {}
 
   R Marshal(rtc::Thread* t) {
-    t->Send(this, 0);
+    internal::SynchronousMethodCall(this).Invoke(t);
     return r_.value();
   }
 
@@ -182,7 +211,7 @@
   MethodCall2(C* c, Method m, T1 a1, T2 a2) : c_(c), m_(m), a1_(a1), a2_(a2) {}
 
   R Marshal(rtc::Thread* t) {
-    t->Send(this, 0);
+    internal::SynchronousMethodCall(this).Invoke(t);
     return r_.value();
   }
 
@@ -205,7 +234,7 @@
       : c_(c), m_(m), a1_(a1), a2_(a2), a3_(a3) {}
 
   R Marshal(rtc::Thread* t) {
-    t->Send(this, 0);
+    internal::SynchronousMethodCall(this).Invoke(t);
     return r_.value();
   }