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

Side by Side Diff: third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp

Issue 2314903002: Web Audio: when media playback requires a user gesture, apply rule to cross origin iframes. (Closed)
Patch Set: move click simulation to top frame Created 4 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
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 15 matching lines...) Expand all
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
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
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
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 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
775 } 734 }
776 735
777 void BaseAudioContext::rejectPendingDecodeAudioDataResolvers() 736 void BaseAudioContext::rejectPendingDecodeAudioDataResolvers()
778 { 737 {
779 // Now reject any pending decodeAudioData resolvers 738 // Now reject any pending decodeAudioData resolvers
780 for (auto& resolver : m_decodeAudioResolvers) 739 for (auto& resolver : m_decodeAudioResolvers)
781 resolver->reject(DOMException::create(InvalidStateError, "Audio context is going away")); 740 resolver->reject(DOMException::create(InvalidStateError, "Audio context is going away"));
782 m_decodeAudioResolvers.clear(); 741 m_decodeAudioResolvers.clear();
783 } 742 }
784 743
744 void BaseAudioContext::maybeUnlockUserGesture()
745 {
746 if (!m_userGestureRequired || !UserGestureIndicator::processingUserGesture() )
747 return;
748
749 UserGestureIndicator::utilizeUserGesture();
750 m_userGestureRequired = false;
751 }
752
753 bool BaseAudioContext::isAllowedToStart() const
754 {
755 if (!m_userGestureRequired)
756 return true;
757
758 toDocument(getExecutionContext())->addConsoleMessage(ConsoleMessage::create( JSMessageSource, WarningMessageLevel, "An AudioContext in a cross origin iframe must be created or resumed from a user gesture to enable audio output."));
759 return false;
760 }
761
785 void BaseAudioContext::rejectPendingResolvers() 762 void BaseAudioContext::rejectPendingResolvers()
786 { 763 {
787 DCHECK(isMainThread()); 764 DCHECK(isMainThread());
788 765
789 // Audio context is closing down so reject any resume promises that are stil l pending. 766 // Audio context is closing down so reject any resume promises that are stil l pending.
790 767
791 for (auto& resolver : m_resumeResolvers) { 768 for (auto& resolver : m_resumeResolvers) {
792 resolver->reject(DOMException::create(InvalidStateError, "Audio context is going away")); 769 resolver->reject(DOMException::create(InvalidStateError, "Audio context is going away"));
793 } 770 }
794 m_resumeResolvers.clear(); 771 m_resumeResolvers.clear();
(...skipping 10 matching lines...) Expand all
805 ExecutionContext* BaseAudioContext::getExecutionContext() const 782 ExecutionContext* BaseAudioContext::getExecutionContext() const
806 { 783 {
807 return ActiveDOMObject::getExecutionContext(); 784 return ActiveDOMObject::getExecutionContext();
808 } 785 }
809 786
810 void BaseAudioContext::startRendering() 787 void BaseAudioContext::startRendering()
811 { 788 {
812 // This is called for both online and offline contexts. 789 // This is called for both online and offline contexts.
813 DCHECK(isMainThread()); 790 DCHECK(isMainThread());
814 DCHECK(m_destinationNode); 791 DCHECK(m_destinationNode);
815 792 DCHECK(isAllowedToStart());
816 recordUserGestureState();
817 793
818 if (m_contextState == Suspended) { 794 if (m_contextState == Suspended) {
819 destination()->audioDestinationHandler().startRendering(); 795 destination()->audioDestinationHandler().startRendering();
820 setContextState(Running); 796 setContextState(Running);
821 } 797 }
822 } 798 }
823 799
824 DEFINE_TRACE(BaseAudioContext) 800 DEFINE_TRACE(BaseAudioContext)
825 { 801 {
826 visitor->trace(m_destinationNode); 802 visitor->trace(m_destinationNode);
(...skipping 12 matching lines...) Expand all
839 815
840 SecurityOrigin* BaseAudioContext::getSecurityOrigin() const 816 SecurityOrigin* BaseAudioContext::getSecurityOrigin() const
841 { 817 {
842 if (getExecutionContext()) 818 if (getExecutionContext())
843 return getExecutionContext()->getSecurityOrigin(); 819 return getExecutionContext()->getSecurityOrigin();
844 820
845 return nullptr; 821 return nullptr;
846 } 822 }
847 823
848 } // namespace blink 824 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/modules/webaudio/BaseAudioContext.h ('k') | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698