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

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

Issue 2404743002: Web Audio: record autoplay status when an AudioContext is destroyed. (Closed)
Patch Set: remove empty line 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 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 m_closedContextSampleRate(-1), 100 m_closedContextSampleRate(-1),
101 m_periodicWaveSine(nullptr), 101 m_periodicWaveSine(nullptr),
102 m_periodicWaveSquare(nullptr), 102 m_periodicWaveSquare(nullptr),
103 m_periodicWaveSawtooth(nullptr), 103 m_periodicWaveSawtooth(nullptr),
104 m_periodicWaveTriangle(nullptr) { 104 m_periodicWaveTriangle(nullptr) {
105 // If mediaPlaybackRequiresUserGesture is enabled, cross origin iframes will 105 // If mediaPlaybackRequiresUserGesture is enabled, cross origin iframes will
106 // require user gesture for the AudioContext to produce sound. 106 // require user gesture for the AudioContext to produce sound.
107 if (document->settings() && 107 if (document->settings() &&
108 document->settings()->mediaPlaybackRequiresUserGesture() && 108 document->settings()->mediaPlaybackRequiresUserGesture() &&
109 document->frame() && document->frame()->isCrossOriginSubframe()) { 109 document->frame() && document->frame()->isCrossOriginSubframe()) {
110 m_autoplayStatus = AutoplayStatus::AutoplayStatusFailed;
110 m_userGestureRequired = true; 111 m_userGestureRequired = true;
111 } 112 }
112 113
113 m_destinationNode = DefaultAudioDestinationNode::create(this); 114 m_destinationNode = DefaultAudioDestinationNode::create(this);
114 115
115 initialize(); 116 initialize();
116 } 117 }
117 118
118 // Constructor for offline (non-realtime) rendering. 119 // Constructor for offline (non-realtime) rendering.
119 BaseAudioContext::BaseAudioContext(Document* document, 120 BaseAudioContext::BaseAudioContext(Document* document,
(...skipping 17 matching lines...) Expand all
137 138
138 BaseAudioContext::~BaseAudioContext() { 139 BaseAudioContext::~BaseAudioContext() {
139 deferredTaskHandler().contextWillBeDestroyed(); 140 deferredTaskHandler().contextWillBeDestroyed();
140 // AudioNodes keep a reference to their context, so there should be no way to 141 // AudioNodes keep a reference to their context, so there should be no way to
141 // be in the destructor if there are still AudioNodes around. 142 // be in the destructor if there are still AudioNodes around.
142 DCHECK(!isDestinationInitialized()); 143 DCHECK(!isDestinationInitialized());
143 DCHECK(!m_activeSourceNodes.size()); 144 DCHECK(!m_activeSourceNodes.size());
144 DCHECK(!m_finishedSourceHandlers.size()); 145 DCHECK(!m_finishedSourceHandlers.size());
145 DCHECK(!m_isResolvingResumePromises); 146 DCHECK(!m_isResolvingResumePromises);
146 DCHECK(!m_resumeResolvers.size()); 147 DCHECK(!m_resumeResolvers.size());
148
149 recordAutoplayStatus();
Raymond Toy 2016/10/10 17:05:10 I think if the user closes a tab, everything goes
mlamouri (slow - plz ping) 2016/10/10 18:44:40 I guess if the object is marked as GCFinalized, it
147 } 150 }
148 151
149 void BaseAudioContext::initialize() { 152 void BaseAudioContext::initialize() {
150 if (isDestinationInitialized()) 153 if (isDestinationInitialized())
151 return; 154 return;
152 155
153 FFTFrame::initialize(); 156 FFTFrame::initialize();
154 157
155 if (m_destinationNode) { 158 if (m_destinationNode) {
156 m_destinationNode->handler().initialize(); 159 m_destinationNode->handler().initialize();
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 m_listener->waitForHRTFDatabaseLoaderThreadCompletion(); 192 m_listener->waitForHRTFDatabaseLoaderThreadCompletion();
190 193
191 clear(); 194 clear();
192 } 195 }
193 196
194 void BaseAudioContext::contextDestroyed() { 197 void BaseAudioContext::contextDestroyed() {
195 uninitialize(); 198 uninitialize();
196 } 199 }
197 200
198 bool BaseAudioContext::hasPendingActivity() const { 201 bool BaseAudioContext::hasPendingActivity() const {
202 LOG(INFO) << "hasPendingActivity() => " << !m_isCleared;
Raymond Toy 2016/10/10 17:05:10 Do you really want this log? Just asking.
mlamouri (slow - plz ping) 2016/10/10 18:44:40 No :)
199 // There's no pending activity if the audio context has been cleared. 203 // There's no pending activity if the audio context has been cleared.
200 return !m_isCleared; 204 return !m_isCleared;
201 } 205 }
202 206
203 AudioDestinationNode* BaseAudioContext::destination() const { 207 AudioDestinationNode* BaseAudioContext::destination() const {
204 // Cannot be called from the audio thread because this method touches objects 208 // Cannot be called from the audio thread because this method touches objects
205 // managed by Oilpan, and the audio thread is not managed by Oilpan. 209 // managed by Oilpan, and the audio thread is not managed by Oilpan.
206 DCHECK(!isAudioThread()); 210 DCHECK(!isAudioThread());
207 return m_destinationNode; 211 return m_destinationNode;
208 } 212 }
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after
546 // Initialize the table if necessary 550 // Initialize the table if necessary
547 if (!m_periodicWaveTriangle) 551 if (!m_periodicWaveTriangle)
548 m_periodicWaveTriangle = PeriodicWave::createTriangle(sampleRate()); 552 m_periodicWaveTriangle = PeriodicWave::createTriangle(sampleRate());
549 return m_periodicWaveTriangle; 553 return m_periodicWaveTriangle;
550 default: 554 default:
551 NOTREACHED(); 555 NOTREACHED();
552 return nullptr; 556 return nullptr;
553 } 557 }
554 } 558 }
555 559
560 void BaseAudioContext::maybeRecordStartAttempt() {
561 if (!m_userGestureRequired || !UserGestureIndicator::processingUserGesture())
562 return;
563
564 DCHECK(!m_autoplayStatus.has_value() ||
565 m_autoplayStatus != AutoplayStatus::AutoplayStatusSucceeded);
566 m_autoplayStatus = AutoplayStatus::AutoplayStatusFailedWithStart;
567 }
568
556 String BaseAudioContext::state() const { 569 String BaseAudioContext::state() const {
557 // These strings had better match the strings for AudioContextState in 570 // These strings had better match the strings for AudioContextState in
558 // AudioContext.idl. 571 // AudioContext.idl.
559 switch (m_contextState) { 572 switch (m_contextState) {
560 case Suspended: 573 case Suspended:
561 return "suspended"; 574 return "suspended";
562 case Running: 575 case Running:
563 return "running"; 576 return "running";
564 case Closed: 577 case Closed:
565 return "closed"; 578 return "closed";
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
768 for (auto& resolver : m_decodeAudioResolvers) 781 for (auto& resolver : m_decodeAudioResolvers)
769 resolver->reject( 782 resolver->reject(
770 DOMException::create(InvalidStateError, "Audio context is going away")); 783 DOMException::create(InvalidStateError, "Audio context is going away"));
771 m_decodeAudioResolvers.clear(); 784 m_decodeAudioResolvers.clear();
772 } 785 }
773 786
774 void BaseAudioContext::maybeUnlockUserGesture() { 787 void BaseAudioContext::maybeUnlockUserGesture() {
775 if (!m_userGestureRequired || !UserGestureIndicator::processingUserGesture()) 788 if (!m_userGestureRequired || !UserGestureIndicator::processingUserGesture())
776 return; 789 return;
777 790
791 DCHECK(!m_autoplayStatus.has_value() ||
792 m_autoplayStatus != AutoplayStatus::AutoplayStatusSucceeded);
793
778 UserGestureIndicator::utilizeUserGesture(); 794 UserGestureIndicator::utilizeUserGesture();
779 m_userGestureRequired = false; 795 m_userGestureRequired = false;
796 m_autoplayStatus = AutoplayStatus::AutoplayStatusSucceeded;
780 } 797 }
781 798
782 bool BaseAudioContext::isAllowedToStart() const { 799 bool BaseAudioContext::isAllowedToStart() const {
783 if (!m_userGestureRequired) 800 if (!m_userGestureRequired)
784 return true; 801 return true;
785 802
786 toDocument(getExecutionContext()) 803 toDocument(getExecutionContext())
787 ->addConsoleMessage(ConsoleMessage::create( 804 ->addConsoleMessage(ConsoleMessage::create(
788 JSMessageSource, WarningMessageLevel, 805 JSMessageSource, WarningMessageLevel,
789 "An AudioContext in a cross origin iframe must be created or resumed " 806 "An AudioContext in a cross origin iframe must be created or resumed "
(...skipping 10 matching lines...) Expand all
800 for (auto& resolver : m_resumeResolvers) { 817 for (auto& resolver : m_resumeResolvers) {
801 resolver->reject( 818 resolver->reject(
802 DOMException::create(InvalidStateError, "Audio context is going away")); 819 DOMException::create(InvalidStateError, "Audio context is going away"));
803 } 820 }
804 m_resumeResolvers.clear(); 821 m_resumeResolvers.clear();
805 m_isResolvingResumePromises = false; 822 m_isResolvingResumePromises = false;
806 823
807 rejectPendingDecodeAudioDataResolvers(); 824 rejectPendingDecodeAudioDataResolvers();
808 } 825 }
809 826
827 void BaseAudioContext::recordAutoplayStatus() {
828 if (!m_autoplayStatus.has_value())
829 return;
830
831 DEFINE_STATIC_LOCAL(
832 EnumerationHistogram, autoplayHistogram,
833 ("WebAudio.Autoplay.CrossOrigin", AutoplayStatus::AutoplayStatusCount));
834 autoplayHistogram.count(m_autoplayStatus.value());
835
836 m_autoplayStatus.reset();
837 }
838
810 const AtomicString& BaseAudioContext::interfaceName() const { 839 const AtomicString& BaseAudioContext::interfaceName() const {
811 return EventTargetNames::AudioContext; 840 return EventTargetNames::AudioContext;
812 } 841 }
813 842
814 ExecutionContext* BaseAudioContext::getExecutionContext() const { 843 ExecutionContext* BaseAudioContext::getExecutionContext() const {
815 return ActiveDOMObject::getExecutionContext(); 844 return ActiveDOMObject::getExecutionContext();
816 } 845 }
817 846
818 void BaseAudioContext::startRendering() { 847 void BaseAudioContext::startRendering() {
819 // This is called for both online and offline contexts. 848 // This is called for both online and offline contexts.
(...skipping 23 matching lines...) Expand all
843 } 872 }
844 873
845 SecurityOrigin* BaseAudioContext::getSecurityOrigin() const { 874 SecurityOrigin* BaseAudioContext::getSecurityOrigin() const {
846 if (getExecutionContext()) 875 if (getExecutionContext())
847 return getExecutionContext()->getSecurityOrigin(); 876 return getExecutionContext()->getSecurityOrigin();
848 877
849 return nullptr; 878 return nullptr;
850 } 879 }
851 880
852 } // namespace blink 881 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698