Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(259)

Side by Side Diff: Source/modules/webaudio/AudioContext.cpp

Issue 24877002: Add more informative messages for DOM exceptions. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2010, Google Inc. All rights reserved. 2 * Copyright (C) 2010, Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 10 matching lines...) Expand all
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */ 23 */
24 24
25 #include "config.h" 25 #include "config.h"
26 26
27 #if ENABLE(WEB_AUDIO) 27 #if ENABLE(WEB_AUDIO)
28 28
29 #include "modules/webaudio/AudioContext.h" 29 #include "modules/webaudio/AudioContext.h"
30 30
31 #include "bindings/v8/ExceptionMessages.h"
31 #include "bindings/v8/ExceptionState.h" 32 #include "bindings/v8/ExceptionState.h"
32 #include "core/dom/Document.h" 33 #include "core/dom/Document.h"
33 #include "core/dom/ExceptionCode.h" 34 #include "core/dom/ExceptionCode.h"
34 #include "core/html/HTMLMediaElement.h" 35 #include "core/html/HTMLMediaElement.h"
35 #include "core/inspector/ScriptCallStack.h" 36 #include "core/inspector/ScriptCallStack.h"
36 #include "core/platform/audio/FFTFrame.h" 37 #include "core/platform/audio/FFTFrame.h"
37 #include "core/platform/audio/HRTFDatabaseLoader.h" 38 #include "core/platform/audio/HRTFDatabaseLoader.h"
38 #include "core/platform/audio/HRTFPanner.h" 39 #include "core/platform/audio/HRTFPanner.h"
39 #include "modules/mediastream/MediaStream.h" 40 #include "modules/mediastream/MediaStream.h"
40 #include "modules/webaudio/AnalyserNode.h" 41 #include "modules/webaudio/AnalyserNode.h"
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after
286 // of dealing with all of its ActiveDOMObjects at this point. uninitialize() can de-reference other 287 // of dealing with all of its ActiveDOMObjects at this point. uninitialize() can de-reference other
287 // ActiveDOMObjects so let's schedule uninitialize() to be called later. 288 // ActiveDOMObjects so let's schedule uninitialize() to be called later.
288 // FIXME: see if there's a more direct way to handle this issue. 289 // FIXME: see if there's a more direct way to handle this issue.
289 callOnMainThread(stopDispatch, this); 290 callOnMainThread(stopDispatch, this);
290 } 291 }
291 292
292 PassRefPtr<AudioBuffer> AudioContext::createBuffer(unsigned numberOfChannels, si ze_t numberOfFrames, float sampleRate, ExceptionState& es) 293 PassRefPtr<AudioBuffer> AudioContext::createBuffer(unsigned numberOfChannels, si ze_t numberOfFrames, float sampleRate, ExceptionState& es)
293 { 294 {
294 RefPtr<AudioBuffer> audioBuffer = AudioBuffer::create(numberOfChannels, numb erOfFrames, sampleRate); 295 RefPtr<AudioBuffer> audioBuffer = AudioBuffer::create(numberOfChannels, numb erOfFrames, sampleRate);
295 if (!audioBuffer.get()) { 296 if (!audioBuffer.get()) {
296 es.throwUninformativeAndGenericDOMException(SyntaxError); 297 es.throwDOMException(
298 SyntaxError,
299 ExceptionMessages::failedToConstruct(
300 "AudioBuffer",
301 "invalid number of channels, frames, or sample rate."));
Mike West 2013/09/27 06:44:39 For these kinds of errors, it would be nice to tel
Raymond Toy (Google) 2013/09/27 16:24:10 Agreed. I'll try to make this (and all others) mor
297 return 0; 302 return 0;
298 } 303 }
299 304
300 return audioBuffer; 305 return audioBuffer;
301 } 306 }
302 307
303 PassRefPtr<AudioBuffer> AudioContext::createBuffer(ArrayBuffer* arrayBuffer, boo l mixToMono, ExceptionState& es) 308 PassRefPtr<AudioBuffer> AudioContext::createBuffer(ArrayBuffer* arrayBuffer, boo l mixToMono, ExceptionState& es)
304 { 309 {
305 ASSERT(arrayBuffer); 310 ASSERT(arrayBuffer);
306 if (!arrayBuffer) { 311 if (!arrayBuffer) {
307 es.throwUninformativeAndGenericDOMException(SyntaxError); 312 es.throwDOMException(
313 SyntaxError,
314 ExceptionMessages::failedToConstruct(
315 "AudioBuffer",
316 "invalid ArrayBuffer."));
308 return 0; 317 return 0;
309 } 318 }
310 319
311 RefPtr<AudioBuffer> audioBuffer = AudioBuffer::createFromAudioFileData(array Buffer->data(), arrayBuffer->byteLength(), mixToMono, sampleRate()); 320 RefPtr<AudioBuffer> audioBuffer = AudioBuffer::createFromAudioFileData(array Buffer->data(), arrayBuffer->byteLength(), mixToMono, sampleRate());
312 if (!audioBuffer.get()) { 321 if (!audioBuffer.get()) {
313 es.throwUninformativeAndGenericDOMException(SyntaxError); 322 es.throwDOMException(
323 SyntaxError,
324 ExceptionMessages::failedToConstruct(
325 "AudioBuffer",
326 "invalid audio data in ArrayBuffer."));
314 return 0; 327 return 0;
315 } 328 }
316 329
317 return audioBuffer; 330 return audioBuffer;
318 } 331 }
319 332
320 void AudioContext::decodeAudioData(ArrayBuffer* audioData, PassRefPtr<AudioBuffe rCallback> successCallback, PassRefPtr<AudioBufferCallback> errorCallback, Excep tionState& es) 333 void AudioContext::decodeAudioData(ArrayBuffer* audioData, PassRefPtr<AudioBuffe rCallback> successCallback, PassRefPtr<AudioBufferCallback> errorCallback, Excep tionState& es)
321 { 334 {
322 if (!audioData) { 335 if (!audioData) {
323 es.throwUninformativeAndGenericDOMException(SyntaxError); 336 es.throwDOMException(
337 SyntaxError,
338 ExceptionMessages::failedToExecute(
339 "decodeAudioData",
340 "AudioContext",
341 "invalid ArrayBuffer for audioData."));
324 return; 342 return;
325 } 343 }
326 m_audioDecoder.decodeAsync(audioData, sampleRate(), successCallback, errorCa llback); 344 m_audioDecoder.decodeAsync(audioData, sampleRate(), successCallback, errorCa llback);
327 } 345 }
328 346
329 PassRefPtr<AudioBufferSourceNode> AudioContext::createBufferSource() 347 PassRefPtr<AudioBufferSourceNode> AudioContext::createBufferSource()
330 { 348 {
331 ASSERT(isMainThread()); 349 ASSERT(isMainThread());
332 lazyInitialize(); 350 lazyInitialize();
333 RefPtr<AudioBufferSourceNode> node = AudioBufferSourceNode::create(this, m_d estinationNode->sampleRate()); 351 RefPtr<AudioBufferSourceNode> node = AudioBufferSourceNode::create(this, m_d estinationNode->sampleRate());
334 352
335 // Because this is an AudioScheduledSourceNode, the context keeps a referenc e until it has finished playing. 353 // Because this is an AudioScheduledSourceNode, the context keeps a referenc e until it has finished playing.
336 // When this happens, AudioScheduledSourceNode::finish() calls AudioContext: :notifyNodeFinishedProcessing(). 354 // When this happens, AudioScheduledSourceNode::finish() calls AudioContext: :notifyNodeFinishedProcessing().
337 refNode(node.get()); 355 refNode(node.get());
338 356
339 return node; 357 return node;
340 } 358 }
341 359
342 PassRefPtr<MediaElementAudioSourceNode> AudioContext::createMediaElementSource(H TMLMediaElement* mediaElement, ExceptionState& es) 360 PassRefPtr<MediaElementAudioSourceNode> AudioContext::createMediaElementSource(H TMLMediaElement* mediaElement, ExceptionState& es)
343 { 361 {
344 ASSERT(mediaElement);
Mike West 2013/09/27 06:44:39 Why drop the ASSERT?
Raymond Toy (Google) 2013/09/27 16:24:10 When running the webaudio layout tests in debug mo
345 if (!mediaElement) { 362 if (!mediaElement) {
346 es.throwUninformativeAndGenericDOMException(InvalidStateError); 363 es.throwDOMException(
364 InvalidStateError,
365 ExceptionMessages::failedToConstruct(
366 "MediaElementAudioSourceNode",
367 "invalid HTMLMedialElement."));
347 return 0; 368 return 0;
348 } 369 }
349 370
350 ASSERT(isMainThread()); 371 ASSERT(isMainThread());
351 lazyInitialize(); 372 lazyInitialize();
352 373
353 // First check if this media element already has a source node. 374 // First check if this media element already has a source node.
354 if (mediaElement->audioSourceNode()) { 375 if (mediaElement->audioSourceNode()) {
355 es.throwUninformativeAndGenericDOMException(InvalidStateError); 376 es.throwDOMException(
377 InvalidStateError,
378 ExceptionMessages::failedToConstruct(
379 "MediaElementAudioSourceNode",
380 "invalid HTMLMediaElement."));
356 return 0; 381 return 0;
357 } 382 }
358 383
359 RefPtr<MediaElementAudioSourceNode> node = MediaElementAudioSourceNode::crea te(this, mediaElement); 384 RefPtr<MediaElementAudioSourceNode> node = MediaElementAudioSourceNode::crea te(this, mediaElement);
360 385
361 mediaElement->setAudioSourceNode(node.get()); 386 mediaElement->setAudioSourceNode(node.get());
362 387
363 refNode(node.get()); // context keeps reference until node is disconnected 388 refNode(node.get()); // context keeps reference until node is disconnected
364 return node; 389 return node;
365 } 390 }
366 391
367 PassRefPtr<MediaStreamAudioSourceNode> AudioContext::createMediaStreamSource(Med iaStream* mediaStream, ExceptionState& es) 392 PassRefPtr<MediaStreamAudioSourceNode> AudioContext::createMediaStreamSource(Med iaStream* mediaStream, ExceptionState& es)
368 { 393 {
369 ASSERT(mediaStream);
370 if (!mediaStream) { 394 if (!mediaStream) {
371 es.throwUninformativeAndGenericDOMException(InvalidStateError); 395 es.throwDOMException(
396 InvalidStateError,
397 ExceptionMessages::failedToConstruct("MediaStreamAudioSourceNode"));
Mike West 2013/09/27 06:44:39 "invalid MediaStream source"?
372 return 0; 398 return 0;
373 } 399 }
374 400
375 ASSERT(isMainThread()); 401 ASSERT(isMainThread());
376 lazyInitialize(); 402 lazyInitialize();
377 403
378 AudioSourceProvider* provider = 0; 404 AudioSourceProvider* provider = 0;
379 405
380 MediaStreamTrackVector audioTracks = mediaStream->getAudioTracks(); 406 MediaStreamTrackVector audioTracks = mediaStream->getAudioTracks();
381 407
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
416 return createScriptProcessor(bufferSize, numberOfInputChannels, 2, es); 442 return createScriptProcessor(bufferSize, numberOfInputChannels, 2, es);
417 } 443 }
418 444
419 PassRefPtr<ScriptProcessorNode> AudioContext::createScriptProcessor(size_t buffe rSize, size_t numberOfInputChannels, size_t numberOfOutputChannels, ExceptionSta te& es) 445 PassRefPtr<ScriptProcessorNode> AudioContext::createScriptProcessor(size_t buffe rSize, size_t numberOfInputChannels, size_t numberOfOutputChannels, ExceptionSta te& es)
420 { 446 {
421 ASSERT(isMainThread()); 447 ASSERT(isMainThread());
422 lazyInitialize(); 448 lazyInitialize();
423 RefPtr<ScriptProcessorNode> node = ScriptProcessorNode::create(this, m_desti nationNode->sampleRate(), bufferSize, numberOfInputChannels, numberOfOutputChann els); 449 RefPtr<ScriptProcessorNode> node = ScriptProcessorNode::create(this, m_desti nationNode->sampleRate(), bufferSize, numberOfInputChannels, numberOfOutputChann els);
424 450
425 if (!node.get()) { 451 if (!node.get()) {
426 es.throwUninformativeAndGenericDOMException(SyntaxError); 452 es.throwDOMException(
453 SyntaxError,
454 ExceptionMessages::failedToConstruct(
455 "ScriptProcessorNode",
456 "invalid buffer size, or number of input/outputs."));
427 return 0; 457 return 0;
428 } 458 }
429 459
430 refNode(node.get()); // context keeps reference until we stop making javascr ipt rendering callbacks 460 refNode(node.get()); // context keeps reference until we stop making javascr ipt rendering callbacks
431 return node; 461 return node;
432 } 462 }
433 463
434 PassRefPtr<BiquadFilterNode> AudioContext::createBiquadFilter() 464 PassRefPtr<BiquadFilterNode> AudioContext::createBiquadFilter()
435 { 465 {
436 ASSERT(isMainThread()); 466 ASSERT(isMainThread());
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 } 533 }
504 534
505 PassRefPtr<ChannelSplitterNode> AudioContext::createChannelSplitter(size_t numbe rOfOutputs, ExceptionState& es) 535 PassRefPtr<ChannelSplitterNode> AudioContext::createChannelSplitter(size_t numbe rOfOutputs, ExceptionState& es)
506 { 536 {
507 ASSERT(isMainThread()); 537 ASSERT(isMainThread());
508 lazyInitialize(); 538 lazyInitialize();
509 539
510 RefPtr<ChannelSplitterNode> node = ChannelSplitterNode::create(this, m_desti nationNode->sampleRate(), numberOfOutputs); 540 RefPtr<ChannelSplitterNode> node = ChannelSplitterNode::create(this, m_desti nationNode->sampleRate(), numberOfOutputs);
511 541
512 if (!node.get()) { 542 if (!node.get()) {
513 es.throwUninformativeAndGenericDOMException(SyntaxError); 543 es.throwDOMException(
544 SyntaxError,
545 ExceptionMessages::failedToConstruct(
546 "ChannelSplitterNode",
547 "invalid number of outputs."));
Mike West 2013/09/27 06:44:39 "The number of outputs (" + String::number(numberO
514 return 0; 548 return 0;
515 } 549 }
516 550
517 return node; 551 return node;
518 } 552 }
519 553
520 PassRefPtr<ChannelMergerNode> AudioContext::createChannelMerger(ExceptionState& es) 554 PassRefPtr<ChannelMergerNode> AudioContext::createChannelMerger(ExceptionState& es)
521 { 555 {
522 const unsigned ChannelMergerDefaultNumberOfInputs = 6; 556 const unsigned ChannelMergerDefaultNumberOfInputs = 6;
523 return createChannelMerger(ChannelMergerDefaultNumberOfInputs, es); 557 return createChannelMerger(ChannelMergerDefaultNumberOfInputs, es);
524 } 558 }
525 559
526 PassRefPtr<ChannelMergerNode> AudioContext::createChannelMerger(size_t numberOfI nputs, ExceptionState& es) 560 PassRefPtr<ChannelMergerNode> AudioContext::createChannelMerger(size_t numberOfI nputs, ExceptionState& es)
527 { 561 {
528 ASSERT(isMainThread()); 562 ASSERT(isMainThread());
529 lazyInitialize(); 563 lazyInitialize();
530 564
531 RefPtr<ChannelMergerNode> node = ChannelMergerNode::create(this, m_destinati onNode->sampleRate(), numberOfInputs); 565 RefPtr<ChannelMergerNode> node = ChannelMergerNode::create(this, m_destinati onNode->sampleRate(), numberOfInputs);
532 566
533 if (!node.get()) { 567 if (!node.get()) {
534 es.throwUninformativeAndGenericDOMException(SyntaxError); 568 es.throwDOMException(
569 SyntaxError,
570 ExceptionMessages::failedToConstruct(
571 "ChannelMergerNode",
572 "invalid number of inputs."));
Mike West 2013/09/27 06:44:39 Same as for outputs.
535 return 0; 573 return 0;
536 } 574 }
537 575
538 return node; 576 return node;
539 } 577 }
540 578
541 PassRefPtr<OscillatorNode> AudioContext::createOscillator() 579 PassRefPtr<OscillatorNode> AudioContext::createOscillator()
542 { 580 {
543 ASSERT(isMainThread()); 581 ASSERT(isMainThread());
544 lazyInitialize(); 582 lazyInitialize();
545 583
546 RefPtr<OscillatorNode> node = OscillatorNode::create(this, m_destinationNode ->sampleRate()); 584 RefPtr<OscillatorNode> node = OscillatorNode::create(this, m_destinationNode ->sampleRate());
547 585
548 // Because this is an AudioScheduledSourceNode, the context keeps a referenc e until it has finished playing. 586 // Because this is an AudioScheduledSourceNode, the context keeps a referenc e until it has finished playing.
549 // When this happens, AudioScheduledSourceNode::finish() calls AudioContext: :notifyNodeFinishedProcessing(). 587 // When this happens, AudioScheduledSourceNode::finish() calls AudioContext: :notifyNodeFinishedProcessing().
550 refNode(node.get()); 588 refNode(node.get());
551 589
552 return node; 590 return node;
553 } 591 }
554 592
555 PassRefPtr<PeriodicWave> AudioContext::createPeriodicWave(Float32Array* real, Fl oat32Array* imag, ExceptionState& es) 593 PassRefPtr<PeriodicWave> AudioContext::createPeriodicWave(Float32Array* real, Fl oat32Array* imag, ExceptionState& es)
556 { 594 {
557 ASSERT(isMainThread()); 595 ASSERT(isMainThread());
558 596
559 if (!real || !imag || (real->length() != imag->length())) { 597 if (!real || !imag || (real->length() != imag->length())) {
560 es.throwUninformativeAndGenericDOMException(SyntaxError); 598 es.throwDOMException(
599 SyntaxError,
600 ExceptionMessages::failedToConstruct(
601 "WaveTable",
602 "invalid real or imag arrays for wave table."));
Mike West 2013/09/27 06:44:39 One option would be to split this up into multiple
561 return 0; 603 return 0;
562 } 604 }
563 605
564 lazyInitialize(); 606 lazyInitialize();
565 return PeriodicWave::create(sampleRate(), real, imag); 607 return PeriodicWave::create(sampleRate(), real, imag);
566 } 608 }
567 609
568 void AudioContext::notifyNodeFinishedProcessing(AudioNode* node) 610 void AudioContext::notifyNodeFinishedProcessing(AudioNode* node)
569 { 611 {
570 ASSERT(isAudioThread()); 612 ASSERT(isAudioThread());
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after
951 } 993 }
952 994
953 void AudioContext::decrementActiveSourceCount() 995 void AudioContext::decrementActiveSourceCount()
954 { 996 {
955 atomicDecrement(&m_activeSourceCount); 997 atomicDecrement(&m_activeSourceCount);
956 } 998 }
957 999
958 } // namespace WebCore 1000 } // namespace WebCore
959 1001
960 #endif // ENABLE(WEB_AUDIO) 1002 #endif // ENABLE(WEB_AUDIO)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698