Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 15 matching lines...) Expand all Loading... | |
| 26 | 26 |
| 27 #include "bindings/core/v8/Dictionary.h" | 27 #include "bindings/core/v8/Dictionary.h" |
| 28 #include "bindings/core/v8/ExceptionMessages.h" | 28 #include "bindings/core/v8/ExceptionMessages.h" |
| 29 #include "bindings/core/v8/ExceptionState.h" | 29 #include "bindings/core/v8/ExceptionState.h" |
| 30 #include "bindings/core/v8/ScriptPromiseResolver.h" | 30 #include "bindings/core/v8/ScriptPromiseResolver.h" |
| 31 #include "bindings/core/v8/ScriptState.h" | 31 #include "bindings/core/v8/ScriptState.h" |
| 32 #include "core/dom/DOMException.h" | 32 #include "core/dom/DOMException.h" |
| 33 #include "core/dom/Document.h" | 33 #include "core/dom/Document.h" |
| 34 #include "core/dom/ExceptionCode.h" | 34 #include "core/dom/ExceptionCode.h" |
| 35 #include "core/dom/ExecutionContextTask.h" | 35 #include "core/dom/ExecutionContextTask.h" |
| 36 #include "core/frame/Deprecation.h" | |
| 37 #include "core/frame/Settings.h" | 36 #include "core/frame/Settings.h" |
| 38 #include "core/html/HTMLMediaElement.h" | 37 #include "core/html/HTMLMediaElement.h" |
| 38 #include "core/inspector/ConsoleMessage.h" | |
| 39 #include "core/inspector/ConsoleTypes.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" |
| 41 #include "modules/webaudio/AudioBuffer.h" | 42 #include "modules/webaudio/AudioBuffer.h" |
| 42 #include "modules/webaudio/AudioBufferCallback.h" | 43 #include "modules/webaudio/AudioBufferCallback.h" |
| 43 #include "modules/webaudio/AudioBufferSourceNode.h" | 44 #include "modules/webaudio/AudioBufferSourceNode.h" |
| 44 #include "modules/webaudio/AudioContext.h" | 45 #include "modules/webaudio/AudioContext.h" |
| 45 #include "modules/webaudio/AudioListener.h" | 46 #include "modules/webaudio/AudioListener.h" |
| 46 #include "modules/webaudio/AudioNodeInput.h" | 47 #include "modules/webaudio/AudioNodeInput.h" |
| 47 #include "modules/webaudio/AudioNodeOutput.h" | 48 #include "modules/webaudio/AudioNodeOutput.h" |
| 48 #include "modules/webaudio/BiquadFilterNode.h" | 49 #include "modules/webaudio/BiquadFilterNode.h" |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 69 #include "modules/webaudio/WaveShaperNode.h" | 70 #include "modules/webaudio/WaveShaperNode.h" |
| 70 #include "platform/CrossThreadFunctional.h" | 71 #include "platform/CrossThreadFunctional.h" |
| 71 #include "platform/Histogram.h" | 72 #include "platform/Histogram.h" |
| 72 #include "platform/UserGestureIndicator.h" | 73 #include "platform/UserGestureIndicator.h" |
| 73 #include "platform/audio/IIRFilter.h" | 74 #include "platform/audio/IIRFilter.h" |
| 74 #include "public/platform/Platform.h" | 75 #include "public/platform/Platform.h" |
| 75 #include "wtf/text/WTFString.h" | 76 #include "wtf/text/WTFString.h" |
| 76 | 77 |
| 77 namespace blink { | 78 namespace blink { |
| 78 | 79 |
| 79 namespace { | |
| 80 | |
| 81 enum UserGestureRecord { | |
| 82 UserGestureRequiredAndAvailable = 0, | |
| 83 UserGestureRequiredAndNotAvailable, | |
| 84 UserGestureNotRequiredAndAvailable, | |
| 85 UserGestureNotRequiredAndNotAvailable, | |
| 86 UserGestureRecordMax | |
| 87 }; | |
| 88 | |
| 89 } // anonymous namespace | |
| 90 | |
| 91 BaseAudioContext* BaseAudioContext::create(Document& document, ExceptionState& e xceptionState) | 80 BaseAudioContext* BaseAudioContext::create(Document& document, ExceptionState& e xceptionState) |
| 92 { | 81 { |
| 93 return AudioContext::create(document, exceptionState); | 82 return AudioContext::create(document, exceptionState); |
| 94 } | 83 } |
| 95 | 84 |
| 96 // FIXME(dominicc): Devolve these constructors to AudioContext | 85 // FIXME(dominicc): Devolve these constructors to AudioContext |
| 97 // and OfflineAudioContext respectively. | 86 // and OfflineAudioContext respectively. |
| 98 | 87 |
| 99 // Constructor for rendering to the audio hardware. | 88 // Constructor for rendering to the audio hardware. |
| 100 BaseAudioContext::BaseAudioContext(Document* document) | 89 BaseAudioContext::BaseAudioContext(Document* document) |
| 101 : ActiveScriptWrappable(this) | 90 : ActiveScriptWrappable(this) |
| 102 , ActiveDOMObject(document) | 91 , ActiveDOMObject(document) |
| 103 , m_destinationNode(nullptr) | 92 , m_destinationNode(nullptr) |
| 104 , m_isCleared(false) | 93 , m_isCleared(false) |
| 105 , m_isResolvingResumePromises(false) | 94 , m_isResolvingResumePromises(false) |
| 106 , m_userGestureRequired(false) | 95 , m_userGestureRequired(false) |
| 107 , m_connectionCount(0) | 96 , m_connectionCount(0) |
| 108 , m_deferredTaskHandler(DeferredTaskHandler::create()) | 97 , m_deferredTaskHandler(DeferredTaskHandler::create()) |
| 109 , m_contextState(Suspended) | 98 , m_contextState(Suspended) |
| 110 , m_closedContextSampleRate(-1) | 99 , m_closedContextSampleRate(-1) |
| 111 , m_periodicWaveSine(nullptr) | 100 , m_periodicWaveSine(nullptr) |
| 112 , m_periodicWaveSquare(nullptr) | 101 , m_periodicWaveSquare(nullptr) |
| 113 , m_periodicWaveSawtooth(nullptr) | 102 , m_periodicWaveSawtooth(nullptr) |
| 114 , m_periodicWaveTriangle(nullptr) | 103 , m_periodicWaveTriangle(nullptr) |
| 115 { | 104 { |
| 116 // TODO(mlamouri): we might want to use other ways of checking for this but | 105 // If mediaPlaybackRequiresUserGesture is enabled, cross origin iframes will |
|
Raymond Toy
2016/09/26 16:09:54
Is mediaPlaybackRequiresUserGesture enabled for al
mlamouri (slow - plz ping)
2016/09/26 17:01:24
Only enabled on Android.
Raymond Toy
2016/09/26 17:24:39
Can you just a note that this is for Android? Wit
mlamouri (slow - plz ping)
2016/09/27 14:11:15
I don't think that this would be a good idea. It i
Raymond Toy
2016/09/28 16:13:47
Fair enough. But its only outdated if, in the fut
mlamouri (slow - plz ping)
2016/09/28 16:17:25
Indeed. But I don't want to close this door :)
| |
| 117 // in order to record metrics, re-using the HTMLMediaElement setting is | 106 // require user gesture for the AudioContext to produce sound. |
| 118 // probably the simplest solution. | 107 if (document->settings() && document->settings()->mediaPlaybackRequiresUserG esture() |
| 119 if (document->settings() && document->settings()->mediaPlaybackRequiresUserG esture()) | 108 && document->frame() && document->frame()->isCrossOriginSubframe()) { |
| 120 m_userGestureRequired = true; | 109 m_userGestureRequired = true; |
| 110 } | |
| 121 | 111 |
| 122 m_destinationNode = DefaultAudioDestinationNode::create(this); | 112 m_destinationNode = DefaultAudioDestinationNode::create(this); |
| 123 | 113 |
| 124 initialize(); | 114 initialize(); |
| 125 } | 115 } |
| 126 | 116 |
| 127 // Constructor for offline (non-realtime) rendering. | 117 // Constructor for offline (non-realtime) rendering. |
| 128 BaseAudioContext::BaseAudioContext(Document* document, unsigned numberOfChannels , size_t numberOfFrames, float sampleRate) | 118 BaseAudioContext::BaseAudioContext(Document* document, unsigned numberOfChannels , size_t numberOfFrames, float sampleRate) |
| 129 : ActiveScriptWrappable(this) | 119 : ActiveScriptWrappable(this) |
| 130 , ActiveDOMObject(document) | 120 , ActiveDOMObject(document) |
| 131 , m_destinationNode(nullptr) | 121 , m_destinationNode(nullptr) |
| 132 , m_isCleared(false) | 122 , m_isCleared(false) |
| 133 , m_isResolvingResumePromises(false) | 123 , m_isResolvingResumePromises(false) |
| 134 , m_userGestureRequired(false) | 124 , m_userGestureRequired(false) |
| 135 , m_connectionCount(0) | 125 , m_connectionCount(0) |
| 136 , m_deferredTaskHandler(DeferredTaskHandler::create()) | 126 , m_deferredTaskHandler(DeferredTaskHandler::create()) |
| 137 , m_contextState(Suspended) | 127 , m_contextState(Suspended) |
| 138 , m_closedContextSampleRate(-1) | 128 , m_closedContextSampleRate(-1) |
| 139 , m_periodicWaveSine(nullptr) | 129 , m_periodicWaveSine(nullptr) |
| 140 , m_periodicWaveSquare(nullptr) | 130 , m_periodicWaveSquare(nullptr) |
| 141 , m_periodicWaveSawtooth(nullptr) | 131 , m_periodicWaveSawtooth(nullptr) |
| 142 , m_periodicWaveTriangle(nullptr) | 132 , m_periodicWaveTriangle(nullptr) |
| 143 { | 133 { |
| 144 // TODO(mlamouri): we might want to use other ways of checking for this but | |
| 145 // in order to record metrics, re-using the HTMLMediaElement setting is | |
| 146 // probably the simplest solution. | |
| 147 if (document->settings() && document->settings()->mediaPlaybackRequiresUserG esture()) | |
| 148 m_userGestureRequired = true; | |
| 149 } | 134 } |
| 150 | 135 |
| 151 BaseAudioContext::~BaseAudioContext() | 136 BaseAudioContext::~BaseAudioContext() |
| 152 { | 137 { |
| 153 deferredTaskHandler().contextWillBeDestroyed(); | 138 deferredTaskHandler().contextWillBeDestroyed(); |
| 154 // AudioNodes keep a reference to their context, so there should be no way t o be in the destructor if there are still AudioNodes around. | 139 // AudioNodes keep a reference to their context, so there should be no way t o be in the destructor if there are still AudioNodes around. |
| 155 DCHECK(!isDestinationInitialized()); | 140 DCHECK(!isDestinationInitialized()); |
| 156 DCHECK(!m_activeSourceNodes.size()); | 141 DCHECK(!m_activeSourceNodes.size()); |
| 157 DCHECK(!m_finishedSourceHandlers.size()); | 142 DCHECK(!m_finishedSourceHandlers.size()); |
| 158 DCHECK(!m_isResolvingResumePromises); | 143 DCHECK(!m_isResolvingResumePromises); |
| (...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 536 // Initialize the table if necessary | 521 // Initialize the table if necessary |
| 537 if (!m_periodicWaveTriangle) | 522 if (!m_periodicWaveTriangle) |
| 538 m_periodicWaveTriangle = PeriodicWave::createTriangle(sampleRate()); | 523 m_periodicWaveTriangle = PeriodicWave::createTriangle(sampleRate()); |
| 539 return m_periodicWaveTriangle; | 524 return m_periodicWaveTriangle; |
| 540 default: | 525 default: |
| 541 NOTREACHED(); | 526 NOTREACHED(); |
| 542 return nullptr; | 527 return nullptr; |
| 543 } | 528 } |
| 544 } | 529 } |
| 545 | 530 |
| 546 void BaseAudioContext::recordUserGestureState() | |
| 547 { | |
| 548 DEFINE_STATIC_LOCAL(EnumerationHistogram, userGestureHistogram, ("WebAudio.U serGesture", UserGestureRecordMax)); | |
| 549 | |
| 550 if (!m_userGestureRequired) { | |
| 551 if (UserGestureIndicator::processingUserGesture()) | |
| 552 userGestureHistogram.count(UserGestureNotRequiredAndAvailable); | |
| 553 else | |
| 554 userGestureHistogram.count(UserGestureNotRequiredAndNotAvailable); | |
| 555 return; | |
| 556 } | |
| 557 | |
| 558 DCHECK(m_userGestureRequired); | |
| 559 if (!UserGestureIndicator::processingUserGesture()) { | |
| 560 userGestureHistogram.count(UserGestureRequiredAndNotAvailable); | |
| 561 | |
| 562 Document* document = toDocument(getExecutionContext()); | |
| 563 if (document) | |
| 564 Deprecation::countDeprecationCrossOriginIframe(*document, UseCounter ::WebAudioAutoplayCrossOriginIframe); | |
| 565 | |
| 566 return; | |
| 567 } | |
| 568 userGestureHistogram.count(UserGestureRequiredAndAvailable); | |
| 569 m_userGestureRequired = false; | |
| 570 } | |
| 571 | |
| 572 String BaseAudioContext::state() const | 531 String BaseAudioContext::state() const |
| 573 { | 532 { |
| 574 // These strings had better match the strings for AudioContextState in Audio Context.idl. | 533 // These strings had better match the strings for AudioContextState in Audio Context.idl. |
| 575 switch (m_contextState) { | 534 switch (m_contextState) { |
| 576 case Suspended: | 535 case Suspended: |
| 577 return "suspended"; | 536 return "suspended"; |
| 578 case Running: | 537 case Running: |
| 579 return "running"; | 538 return "running"; |
| 580 case Closed: | 539 case Closed: |
| 581 return "closed"; | 540 return "closed"; |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 806 { | 765 { |
| 807 return ActiveDOMObject::getExecutionContext(); | 766 return ActiveDOMObject::getExecutionContext(); |
| 808 } | 767 } |
| 809 | 768 |
| 810 void BaseAudioContext::startRendering() | 769 void BaseAudioContext::startRendering() |
| 811 { | 770 { |
| 812 // This is called for both online and offline contexts. | 771 // This is called for both online and offline contexts. |
| 813 DCHECK(isMainThread()); | 772 DCHECK(isMainThread()); |
| 814 DCHECK(m_destinationNode); | 773 DCHECK(m_destinationNode); |
| 815 | 774 |
| 816 recordUserGestureState(); | 775 if (m_userGestureRequired) { |
| 776 if (!UserGestureIndicator::processingUserGesture()) { | |
| 777 toDocument(getExecutionContext())->addConsoleMessage(ConsoleMessage: :create(JSMessageSource, WarningMessageLevel, "An AudioContext in a cross origin iframe must be created from a user gesture handler or have resume() called from one.")); | |
|
Raymond Toy
2016/09/26 16:09:54
The message says the context must be created from
mlamouri (slow - plz ping)
2016/09/26 17:01:24
Both are valid: you can create it from a user gest
Raymond Toy
2016/09/26 17:24:38
Yeah, concise messages are really hard. Oh, you a
mlamouri (slow - plz ping)
2016/09/27 14:11:15
Done.
| |
| 778 return; | |
| 779 } | |
| 780 m_userGestureRequired = false; | |
| 781 } | |
|
Raymond Toy
2016/09/26 16:09:54
I think this block of code should be in the caller
mlamouri (slow - plz ping)
2016/09/26 17:01:24
Sure. I will add a DCHECK though to make sure we d
Raymond Toy
2016/09/26 17:24:39
Yeah, that's fine with me.
| |
| 817 | 782 |
| 818 if (m_contextState == Suspended) { | 783 if (m_contextState == Suspended) { |
| 819 destination()->audioDestinationHandler().startRendering(); | 784 destination()->audioDestinationHandler().startRendering(); |
| 820 setContextState(Running); | 785 setContextState(Running); |
| 821 } | 786 } |
| 822 } | 787 } |
| 823 | 788 |
| 824 DEFINE_TRACE(BaseAudioContext) | 789 DEFINE_TRACE(BaseAudioContext) |
| 825 { | 790 { |
| 826 visitor->trace(m_destinationNode); | 791 visitor->trace(m_destinationNode); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 839 | 804 |
| 840 SecurityOrigin* BaseAudioContext::getSecurityOrigin() const | 805 SecurityOrigin* BaseAudioContext::getSecurityOrigin() const |
| 841 { | 806 { |
| 842 if (getExecutionContext()) | 807 if (getExecutionContext()) |
| 843 return getExecutionContext()->getSecurityOrigin(); | 808 return getExecutionContext()->getSecurityOrigin(); |
| 844 | 809 |
| 845 return nullptr; | 810 return nullptr; |
| 846 } | 811 } |
| 847 | 812 |
| 848 } // namespace blink | 813 } // namespace blink |
| OLD | NEW |