Bug 1361259. P4 - enforce copy in NonExclusive mode for each listener must get a copy. draft
authorJW Wang <jwwang@mozilla.com>
Fri, 28 Apr 2017 17:56:57 +0800
changeset 571202 567c4a15434c48f2161725a6491125ded5b061e1
parent 571201 12b6a213d49b1d8405a058030aad520c4cbde726
child 571203 f217a14fa24b8eff7b48da08b8bbed0dd00efdf6
push id56725
push userjwwang@mozilla.com
push dateTue, 02 May 2017 08:46:33 +0000
bugs1361259
milestone55.0a1
Bug 1361259. P4 - enforce copy in NonExclusive mode for each listener must get a copy. MozReview-Commit-ID: Mqt0N2erP6
dom/media/MediaEventSource.h
dom/media/gtest/TestMediaEventSource.cpp
--- a/dom/media/MediaEventSource.h
+++ b/dom/media/MediaEventSource.h
@@ -400,17 +400,18 @@ using MediaEventSourceExc =
  * and event publisher. Mostly used as a member variable to publish events
  * to the listeners.
  */
 template <typename... Es>
 class MediaEventProducer : public MediaEventSource<Es...> {
 public:
   template <typename... Ts>
   void Notify(Ts&&... aEvents) {
-    this->NotifyInternal(Forward<Ts>(aEvents)...);
+    // Pass lvalues to prevent move in NonExclusive mode.
+    this->NotifyInternal(aEvents...);
   }
 };
 
 /**
  * Specialization for void type. A dummy bool is passed to NotifyInternal
  * since there is no way to pass a void value.
  */
 template <>
--- a/dom/media/gtest/TestMediaEventSource.cpp
+++ b/dom/media/gtest/TestMediaEventSource.cpp
@@ -330,8 +330,47 @@ TEST(MediaEventSource, MoveOnly)
   // It is an error to pass an lvalue which is move-only.
   // UniquePtr<int> event(new int(30));
   // source.Notify(event);
 
   queue->BeginShutdown();
   queue->AwaitShutdownAndIdle();
   listener.Disconnect();
 }
+
+struct RefCounter
+{
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RefCounter)
+  explicit RefCounter(int aVal) : mVal(aVal) { }
+  int mVal;
+private:
+  ~RefCounter() { }
+};
+
+/*
+ * Test we should copy instead of move in NonExclusive mode
+ * for each listener must get a copy.
+ */
+TEST(MediaEventSource, NoMove)
+{
+  RefPtr<TaskQueue> queue = new TaskQueue(
+    GetMediaThreadPool(MediaThreadType::PLAYBACK));
+
+  MediaEventProducer<RefPtr<RefCounter>> source;
+
+  auto func1 = [] (RefPtr<RefCounter>&& aEvent) {
+    EXPECT_EQ(aEvent->mVal, 20);
+  };
+  auto func2 = [] (RefPtr<RefCounter>&& aEvent) {
+    EXPECT_EQ(aEvent->mVal, 20);
+  };
+  MediaEventListener listener1 = source.Connect(queue, func1);
+  MediaEventListener listener2 = source.Connect(queue, func2);
+
+  // We should copy this rvalue instead of move it in NonExclusive mode.
+  RefPtr<RefCounter> val = new RefCounter(20);
+  source.Notify(Move(val));
+
+  queue->BeginShutdown();
+  queue->AwaitShutdownAndIdle();
+  listener1.Disconnect();
+  listener2.Disconnect();
+}