Cap the number of SourceBuffers that may be added to a MediaSource.
authorannacc@chromium.org <annacc@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 13 Aug 2012 16:45:50 +0000 (16:45 +0000)
committerannacc@chromium.org <annacc@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 13 Aug 2012 16:45:50 +0000 (16:45 +0000)
https://bugs.webkit.org/show_bug.cgi?id=93406

Reviewed by Eric Carlson.

Make sure that no more SourceBuffer objects are added to a MediaSource
than can fit into the sourceBuffers SourceBufferList (internally stored
as a Vector). Also, make sure that new SourceBuffers are added with a
unique id even if the variable we are using to generate id wraps around.

No new tests.  It would not be realistic to add so many SourceBuffers to
test the id variable wrapping.  Existing tests should not be affected.

* Modules/mediasource/MediaSource.cpp:
(WebCore::MediaSource::MediaSource):
(WebCore::MediaSource::addSourceBuffer): Obtain a unique id before creating
    a new SourceBuffer.
* Modules/mediasource/MediaSource.h:
* Modules/mediasource/SourceBufferList.cpp:
(WebCore::SourceBufferList::SourceBufferList):
(WebCore::SourceBufferList::generateUniqueId): Search for and generate a
    unique id.
(WebCore):
(WebCore::SourceBufferList::contains): Check if a SourceBuffer with a
    given id already exists in this SourceBufferList.
* Modules/mediasource/SourceBufferList.h:
(SourceBufferList):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@125424 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/Modules/mediasource/MediaSource.cpp
Source/WebCore/Modules/mediasource/MediaSource.h
Source/WebCore/Modules/mediasource/SourceBufferList.cpp
Source/WebCore/Modules/mediasource/SourceBufferList.h

index 646dfee..089fffe 100644 (file)
@@ -1,3 +1,33 @@
+2012-08-13  Anna Cavender  <annacc@chromium.org>
+
+        Cap the number of SourceBuffers that may be added to a MediaSource.
+        https://bugs.webkit.org/show_bug.cgi?id=93406
+
+        Reviewed by Eric Carlson.
+
+        Make sure that no more SourceBuffer objects are added to a MediaSource
+        than can fit into the sourceBuffers SourceBufferList (internally stored
+        as a Vector). Also, make sure that new SourceBuffers are added with a
+        unique id even if the variable we are using to generate id wraps around.
+
+        No new tests.  It would not be realistic to add so many SourceBuffers to
+        test the id variable wrapping.  Existing tests should not be affected.
+
+        * Modules/mediasource/MediaSource.cpp:
+        (WebCore::MediaSource::MediaSource):
+        (WebCore::MediaSource::addSourceBuffer): Obtain a unique id before creating
+            a new SourceBuffer.
+        * Modules/mediasource/MediaSource.h:
+        * Modules/mediasource/SourceBufferList.cpp:
+        (WebCore::SourceBufferList::SourceBufferList):
+        (WebCore::SourceBufferList::generateUniqueId): Search for and generate a
+            unique id.
+        (WebCore):
+        (WebCore::SourceBufferList::contains): Check if a SourceBuffer with a
+            given id already exists in this SourceBufferList.
+        * Modules/mediasource/SourceBufferList.h:
+        (SourceBufferList):
+
 2012-08-13  Andrey Kosyakov  <caseq@chromium.org>
 
         Web Inspector: when status bar is too narrow, cut panel status bar, not main status bar items
index 6f84d94..e1317f5 100644 (file)
@@ -49,7 +49,6 @@ MediaSource::MediaSource(ScriptExecutionContext* context)
     : ContextDestructionObserver(context)
     , m_readyState(closedKeyword())
     , m_player(0)
-    , m_nextSourceBufferId(0)
 {
     m_sourceBuffers = SourceBufferList::create(scriptExecutionContext());
     m_activeSourceBuffers = SourceBufferList::create(scriptExecutionContext());
@@ -94,7 +93,13 @@ SourceBuffer* MediaSource::addSourceBuffer(const String& type, ExceptionCode& ec
     }
 
     // 5. Create a new SourceBuffer object and associated resources.
-    RefPtr<SourceBuffer> buffer = SourceBuffer::create(String::number(++m_nextSourceBufferId), this);
+    String id = m_sourceBuffers->generateUniqueId();
+    if (id == emptyString()) {
+        ec = QUOTA_EXCEEDED_ERR;
+        return 0;
+    }
+
+    RefPtr<SourceBuffer> buffer = SourceBuffer::create(id, this);
 
     switch (m_player->sourceAddId(buffer->id(), contentType.type(), codecs)) {
     case MediaPlayer::Ok:
index 646ac3a..2c85fd0 100644 (file)
@@ -104,7 +104,6 @@ private:
 
     RefPtr<SourceBufferList> m_sourceBuffers;
     RefPtr<SourceBufferList> m_activeSourceBuffers;
-    int m_nextSourceBufferId;
 };
 
 } // namespace WebCore
index 662b46f..ce213d5 100644 (file)
@@ -40,6 +40,7 @@ namespace WebCore {
 
 SourceBufferList::SourceBufferList(ScriptExecutionContext* context)
     : m_scriptExecutionContext(context)
+    , m_lastSourceBufferId(0)
 {
 }
 
@@ -79,6 +80,34 @@ void SourceBufferList::clear()
         remove(m_list[i].get());
 }
 
+String SourceBufferList::generateUniqueId()
+{
+    // Ensure a unique id. Until m_lastSourceBufferId wraps around (very unlikely),
+    // this loop will exit after one check. If m_lastSourceBufferId does wrap,
+    // this loop may run as many times as the size of m_list, but in most
+    // cases that should be less than 10. We may want to investigate a more
+    // efficient approach if many more SourceBuffers are allowed in the future.
+    size_t nextSourceBufferId = m_lastSourceBufferId + 1;
+
+    while (contains(nextSourceBufferId)) {
+        if (nextSourceBufferId == m_lastSourceBufferId)
+            return emptyString();
+        nextSourceBufferId++;
+    }
+    m_lastSourceBufferId = nextSourceBufferId;
+
+    return String::number(nextSourceBufferId);
+}
+
+bool SourceBufferList::contains(size_t id) const
+{
+    for (size_t i = 0; i < m_list.size(); ++i) {
+        if (m_list[i]->id() == String::number(id))
+            return true;
+    }
+    return false;
+}
+
 void SourceBufferList::createAndFireEvent(const AtomicString& eventName)
 {
     RefPtr<Event> event = Event::create(eventName, false, false);
index 6f7f9a7..c87cf34 100644 (file)
@@ -56,6 +56,10 @@ public:
     bool remove(SourceBuffer*);
     void clear();
 
+    // Generates an id for adding a new SourceBuffer. Returns an empty string
+    // if this SourceBufferList is full.
+    String generateUniqueId();
+
     // EventTarget interface
     virtual const AtomicString& interfaceName() const OVERRIDE;
     virtual ScriptExecutionContext* scriptExecutionContext() const OVERRIDE;
@@ -70,6 +74,7 @@ protected:
 private:
     explicit SourceBufferList(ScriptExecutionContext*);
 
+    bool contains(size_t id) const;
     void createAndFireEvent(const AtomicString&);
 
     virtual void refEventTarget() OVERRIDE { ref(); }
@@ -79,6 +84,7 @@ private:
     ScriptExecutionContext* m_scriptExecutionContext;
 
     Vector<RefPtr<SourceBuffer> > m_list;
+    size_t m_lastSourceBufferId;
 };
 
 } // namespace WebCore