Add helper KeepRefUntilDone.
The callback keeps a reference to an object until the callback goes out of scope.

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

Cr-Commit-Position: refs/heads/master@{#10847}
diff --git a/webrtc/base/callback_unittest.cc b/webrtc/base/callback_unittest.cc
index 66c9391..db294cd 100644
--- a/webrtc/base/callback_unittest.cc
+++ b/webrtc/base/callback_unittest.cc
@@ -11,6 +11,8 @@
 #include "webrtc/base/bind.h"
 #include "webrtc/base/callback.h"
 #include "webrtc/base/gunit.h"
+#include "webrtc/base/keep_ref_until_done.h"
+#include "webrtc/base/refcount.h"
 
 namespace rtc {
 
@@ -26,6 +28,21 @@
   int b(int x) const { return x * x; }
 };
 
+class RefCountedBindTester : public RefCountInterface {
+ public:
+  RefCountedBindTester() : count_(0) {}
+  int AddRef() const override {
+    return ++count_;
+  }
+  int Release() const {
+    return --count_;
+  }
+  int RefCount() const { return count_; }
+
+ private:
+  mutable int count_;
+};
+
 }  // namespace
 
 TEST(CallbackTest, VoidReturn) {
@@ -78,4 +95,46 @@
   EXPECT_EQ(25, cb1());
 }
 
+TEST(KeepRefUntilDoneTest, simple) {
+  RefCountedBindTester t;
+  EXPECT_EQ(0, t.RefCount());
+  {
+    Callback0<void> cb = KeepRefUntilDone(&t);
+    EXPECT_EQ(1, t.RefCount());
+    cb();
+    EXPECT_EQ(1, t.RefCount());
+    cb();
+    EXPECT_EQ(1, t.RefCount());
+  }
+  EXPECT_EQ(0, t.RefCount());
+}
+
+TEST(KeepRefUntilDoneTest, copy) {
+  RefCountedBindTester t;
+  EXPECT_EQ(0, t.RefCount());
+  Callback0<void> cb2;
+  {
+    Callback0<void> cb = KeepRefUntilDone(&t);
+    EXPECT_EQ(1, t.RefCount());
+    cb2 = cb;
+  }
+  EXPECT_EQ(1, t.RefCount());
+  cb2 = Callback0<void>();
+  EXPECT_EQ(0, t.RefCount());
+}
+
+TEST(KeepRefUntilDoneTest, scopedref) {
+  RefCountedBindTester t;
+  EXPECT_EQ(0, t.RefCount());
+  {
+    scoped_refptr<RefCountedBindTester> t_scoped_ref(&t);
+    Callback0<void> cb = KeepRefUntilDone(t_scoped_ref);
+    t_scoped_ref = nullptr;
+    EXPECT_EQ(1, t.RefCount());
+    cb();
+    EXPECT_EQ(1, t.RefCount());
+  }
+  EXPECT_EQ(0, t.RefCount());
+}
+
 }  // namespace rtc