AudioBufferSourceNode must validate AudioBuffer in .buffer attribute setter
authorcrogers@google.com <crogers@google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 9 Sep 2011 22:15:37 +0000 (22:15 +0000)
committercrogers@google.com <crogers@google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 9 Sep 2011 22:15:37 +0000 (22:15 +0000)
https://bugs.webkit.org/show_bug.cgi?id=67749

Reviewed by Kenneth Russell.

Source/WebCore:

Test: webaudio/audiobuffersource-channels.html

* WebCore.gypi:
* bindings/js/JSAudioBufferSourceNodeCustom.cpp:
(WebCore::JSAudioBufferSourceNode::setBuffer):
* bindings/v8/custom/V8AudioBufferSourceNodeCustom.cpp: Copied from Source/WebCore/bindings/js/JSAudioBufferSourceNodeCustom.cpp.
(WebCore::V8AudioBufferSourceNode::bufferAccessorSetter):
* webaudio/AudioBufferSourceNode.cpp:
(WebCore::AudioBufferSourceNode::setBuffer):
* webaudio/AudioBufferSourceNode.h:
* webaudio/AudioBufferSourceNode.idl:

LayoutTests:

* webaudio/audiobuffersource-channels-expected.txt: Added.
* webaudio/audiobuffersource-channels.html: Added.

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

LayoutTests/ChangeLog
LayoutTests/webaudio/audiobuffersource-channels-expected.txt [new file with mode: 0644]
LayoutTests/webaudio/audiobuffersource-channels.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/WebCore.gypi
Source/WebCore/bindings/js/JSAudioBufferSourceNodeCustom.cpp
Source/WebCore/bindings/v8/custom/V8AudioBufferSourceNodeCustom.cpp [new file with mode: 0644]
Source/WebCore/webaudio/AudioBufferSourceNode.cpp
Source/WebCore/webaudio/AudioBufferSourceNode.h
Source/WebCore/webaudio/AudioBufferSourceNode.idl

index 7d3f6d8..630fc62 100644 (file)
@@ -1,3 +1,13 @@
+2011-09-09  Chris Rogers  <crogers@google.com>
+
+        AudioBufferSourceNode must validate AudioBuffer in .buffer attribute setter
+        https://bugs.webkit.org/show_bug.cgi?id=67749
+
+        Reviewed by Kenneth Russell.
+
+        * webaudio/audiobuffersource-channels-expected.txt: Added.
+        * webaudio/audiobuffersource-channels.html: Added.
+
 2011-09-09  Ryosuke Niwa  <rniwa@webkit.org>
 
         GTK rebaseline.
diff --git a/LayoutTests/webaudio/audiobuffersource-channels-expected.txt b/LayoutTests/webaudio/audiobuffersource-channels-expected.txt
new file mode 100644 (file)
index 0000000..d4e7ff6
--- /dev/null
@@ -0,0 +1,18 @@
+Tests that AudioBufferSourceNode validates AudioBuffer in .buffer attribute setter.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+PASS source.buffer = 57 threw exception TypeError: Value is not of type AudioBuffer.
+PASS Mono buffer can be set.
+PASS Stereo buffer can be set.
+PASS 3 channel buffer is not settable.
+PASS 4 channel buffer is not settable.
+PASS 5 channel buffer is not settable.
+PASS 6 channel buffer is not settable.
+PASS 7 channel buffer is not settable.
+PASS 8 channel buffer is not settable.
+PASS 9 channel buffer is not settable.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/webaudio/audiobuffersource-channels.html b/LayoutTests/webaudio/audiobuffersource-channels.html
new file mode 100644 (file)
index 0000000..f972e97
--- /dev/null
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+<link rel="stylesheet" href="../fast/js/resources/js-test-style.css"/>
+<script src="../fast/js/resources/js-test-pre.js"></script>
+<script type="text/javascript" src="resources/audio-testing.js"></script>
+</head>
+
+<body>
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+description("Tests that AudioBufferSourceNode validates AudioBuffer in .buffer attribute setter.");
+
+var context;
+var source;
+
+function runTest() {
+    if (window.layoutTestController) {
+        layoutTestController.dumpAsText();
+        layoutTestController.waitUntilDone();
+    }
+    
+    window.jsTestIsAsync = true;
+    
+    context = new webkitAudioContext();
+    source = context.createBufferSource();
+
+    // Make sure we can't set to something which isn't an AudioBuffer.
+    shouldThrow("source.buffer = 57");
+
+    // Check that mono buffer can be set.
+    try {
+        var monoBuffer = context.createBuffer(1, 1024, context.sampleRate);
+        source.buffer = monoBuffer;
+        testPassed("Mono buffer can be set.");
+    } catch(e) {
+        testFailed("Mono buffer can not be set.");
+    }
+
+    // Check that stereo buffer can be set.
+    try {
+        var stereoBuffer = context.createBuffer(2, 1024, context.sampleRate);
+        source.buffer = stereoBuffer;
+        testPassed("Stereo buffer can be set.");
+    } catch(e) {
+        testFailed("Stereo buffer can not be set.");
+    }
+    
+    // Check a few buffers with more than two channels and check for failure.
+    // (for now the implementation will only work with mono and stereo buffers)
+    for (var i = 3; i < 10; ++i) {
+        try {
+            var buffer = context.createBuffer(i, 1024, context.sampleRate);
+            source.buffer = buffer;
+            var message = i + " channel buffer should not be settable.";
+            testFailed(message);
+        } catch(e) {
+            var message = i + " channel buffer is not settable.";
+            testPassed(message);
+        }
+    }
+        
+    finishJSTest();
+}
+
+runTest();
+successfullyParsed = true;
+
+</script>
+
+<script src="../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
index af77178..912cdce 100644 (file)
@@ -1,3 +1,22 @@
+2011-09-09  Chris Rogers  <crogers@google.com>
+
+        AudioBufferSourceNode must validate AudioBuffer in .buffer attribute setter
+        https://bugs.webkit.org/show_bug.cgi?id=67749
+
+        Reviewed by Kenneth Russell.
+
+        Test: webaudio/audiobuffersource-channels.html
+
+        * WebCore.gypi:
+        * bindings/js/JSAudioBufferSourceNodeCustom.cpp:
+        (WebCore::JSAudioBufferSourceNode::setBuffer):
+        * bindings/v8/custom/V8AudioBufferSourceNodeCustom.cpp: Copied from Source/WebCore/bindings/js/JSAudioBufferSourceNodeCustom.cpp.
+        (WebCore::V8AudioBufferSourceNode::bufferAccessorSetter):
+        * webaudio/AudioBufferSourceNode.cpp:
+        (WebCore::AudioBufferSourceNode::setBuffer):
+        * webaudio/AudioBufferSourceNode.h:
+        * webaudio/AudioBufferSourceNode.idl:
+
 2011-09-09  Dan Bernstein  <mitz@apple.com>
 
         RenderBlock::addOverhangingFloats() takes superfluous parameters
index 2566b1c..701cda4 100644 (file)
             'bindings/v8/WrapperTypeInfo.h',
             'bindings/v8/custom/V8ArrayBufferCustom.cpp',
             'bindings/v8/custom/V8ArrayBufferViewCustom.h',
+            'bindings/v8/custom/V8AudioBufferSourceNodeCustom.cpp',
             'bindings/v8/custom/V8AudioContextCustom.cpp',
             'bindings/v8/custom/V8AudioNodeCustom.cpp',
             'bindings/v8/custom/V8BindingMacros.h',
index 8ca7f1f..2d917eb 100644 (file)
 
 #if ENABLE(WEB_AUDIO)
 
-#include "AudioBufferSourceNode.h"
+#include "JSAudioBufferSourceNode.h"
 
 #include "AudioBuffer.h"
+#include "AudioBufferSourceNode.h"
 #include "JSAudioBuffer.h"
-#include "JSAudioBufferSourceNode.h"
+#include <runtime/Error.h>
 
 using namespace JSC;
 
 namespace WebCore {
 
-void JSAudioBufferSourceNode::setBuffer(ExecState*, JSValue value)
+void JSAudioBufferSourceNode::setBuffer(ExecState* exec, JSValue value)
 {
     AudioBufferSourceNode* imp = static_cast<AudioBufferSourceNode*>(impl());
-    imp->setBuffer(toAudioBuffer(value));
+    AudioBuffer* buffer = toAudioBuffer(value);
+    if (!buffer) {
+        throwError(exec, createSyntaxError(exec, "Value is not of type AudioBuffer"));
+        return;
+    }
+    
+    if (!imp->setBuffer(buffer))
+        throwError(exec, createSyntaxError(exec, "AudioBuffer unsupported number of channels"));
 }
 
 } // namespace WebCore
diff --git a/Source/WebCore/bindings/v8/custom/V8AudioBufferSourceNodeCustom.cpp b/Source/WebCore/bindings/v8/custom/V8AudioBufferSourceNodeCustom.cpp
new file mode 100644 (file)
index 0000000..8d870be
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2011, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1.  Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(WEB_AUDIO)
+
+#include "V8AudioBufferSourceNode.h"
+
+#include "AudioBuffer.h"
+#include "AudioBufferSourceNode.h"
+#include "ExceptionCode.h"
+#include "V8AudioBuffer.h"
+#include "V8Binding.h"
+#include "V8Proxy.h"
+
+namespace WebCore {
+
+void V8AudioBufferSourceNode::bufferAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
+{
+    INC_STATS("DOM.AudioBufferSourceNode.buffer._set");
+    v8::Handle<v8::Object> holder = info.Holder();
+    AudioBufferSourceNode* imp = V8AudioBufferSourceNode::toNative(holder);
+
+    AudioBuffer* buffer = 0;
+    if (V8AudioBuffer::HasInstance(value)) {
+        buffer = V8AudioBuffer::toNative(value->ToObject());
+        if (buffer && !imp->setBuffer(buffer)) {
+            throwError("AudioBuffer unsupported number of channels");
+            return;
+        }
+    }
+    
+    if (!buffer) {
+        throwError("Value is not of type AudioBuffer");
+        return;
+    }
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_AUDIO)
index da79e64..b135060 100644 (file)
@@ -324,7 +324,7 @@ void AudioBufferSourceNode::finish()
     }
 }
 
-void AudioBufferSourceNode::setBuffer(AudioBuffer* buffer)
+bool AudioBufferSourceNode::setBuffer(AudioBuffer* buffer)
 {
     ASSERT(isMainThread());
     
@@ -337,11 +337,17 @@ void AudioBufferSourceNode::setBuffer(AudioBuffer* buffer)
     if (buffer) {
         // Do any necesssary re-configuration to the buffer's number of channels.
         unsigned numberOfChannels = buffer->numberOfChannels();
+        if (!numberOfChannels || numberOfChannels > 2) {
+            // FIXME: implement multi-channel greater than stereo.
+            return false;
+        }
         output(0)->setNumberOfChannels(numberOfChannels);
     }
 
     m_virtualReadIndex = 0;
     m_buffer = buffer;
+    
+    return true;
 }
 
 unsigned AudioBufferSourceNode::numberOfChannels()
index 5346f62..c769c97 100644 (file)
@@ -52,7 +52,8 @@ public:
     virtual void reset();
     
     // setBuffer() is called on the main thread.  This is the buffer we use for playback.
-    void setBuffer(AudioBuffer*);
+    // returns true on success.
+    bool setBuffer(AudioBuffer*);
     AudioBuffer* buffer() { return m_buffer.get(); }
                     
     // numberOfChannels() returns the number of output channels.  This value equals the number of channels from the buffer.
index 0eb15b2..c39ec75 100644 (file)
@@ -28,7 +28,8 @@ module audio {
         Conditional=WEB_AUDIO,
         GenerateToJS
     ] AudioBufferSourceNode : AudioSourceNode {
-        attribute [JSCCustomSetter] AudioBuffer buffer;
+        attribute [CustomSetter] AudioBuffer buffer
+            setter raises (DOMException);
 
         readonly attribute AudioGain gain;
         readonly attribute AudioParam playbackRate;