Bug 1361259. P4 - enforce copy in NonExclusive mode for each listener must get a copy.
MozReview-Commit-ID: Mqt0N2erP6
--- 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();
+}