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

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: apply changes from TPAC discussion 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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698