WebKit Bugzilla
Attachment 356625 Details for
Bug 192414
: REGRESSION(r238844): The layout tests added with this change are flaky. (Requested by ryanhaddad on #webkit).
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
ROLLOUT of r238844
bug-192414-20181205111634.patch (text/plain), 61.05 KB, created by
WebKit Commit Bot
on 2018-12-05 11:16:35 PST
(
hide
)
Description:
ROLLOUT of r238844
Filename:
MIME Type:
Creator:
WebKit Commit Bot
Created:
2018-12-05 11:16:35 PST
Size:
61.05 KB
patch
obsolete
>Subversion Revision: 238900 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index e9f6b72b9c7cccb2843e6748b64b155b9561a679..58efd87fd66e98ccff0e2db3ab11c143a48d5176 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,24 @@ >+2018-12-05 Commit Queue <commit-queue@webkit.org> >+ >+ Unreviewed, rolling out r238844, r238846, and r238874. >+ https://bugs.webkit.org/show_bug.cgi?id=192414 >+ >+ The layout tests added with this change are flaky. (Requested >+ by ryanhaddad on #webkit). >+ >+ Reverted changesets: >+ >+ "Implement non-timeslice mode encoding for MediaRecorder" >+ https://bugs.webkit.org/show_bug.cgi?id=192069 >+ https://trac.webkit.org/changeset/238844 >+ >+ "Fix the build" >+ https://trac.webkit.org/changeset/238846 >+ >+ "Fix MediaRecorder flaky tests" >+ https://bugs.webkit.org/show_bug.cgi?id=192371 >+ https://trac.webkit.org/changeset/238874 >+ > 2018-12-05 Frederic Wang <fwang@igalia.com> > > Minor refactoring of the scrolling code >diff --git a/Source/WebCore/Modules/mediarecorder/MediaRecorder.cpp b/Source/WebCore/Modules/mediarecorder/MediaRecorder.cpp >index a78d4be7ef990971f09d98e4dec536dbdd9b19b9..8f6bcf746b6a476b76fbc4abddc6559b009cb9c5 100644 >--- a/Source/WebCore/Modules/mediarecorder/MediaRecorder.cpp >+++ b/Source/WebCore/Modules/mediarecorder/MediaRecorder.cpp >@@ -33,48 +33,22 @@ > #include "Document.h" > #include "EventNames.h" > #include "MediaRecorderErrorEvent.h" >-#include "MediaRecorderPrivate.h" >-#include "SharedBuffer.h" >- >-#if PLATFORM(COCOA) >-#include "MediaRecorderPrivateAVFImpl.h" >-#endif >+#include "MediaRecorderPrivateMock.h" > > namespace WebCore { > >-creatorFunction MediaRecorder::m_customCreator = nullptr; >- >-ExceptionOr<Ref<MediaRecorder>> MediaRecorder::create(Document& document, Ref<MediaStream>&& stream, Options&& options) >+Ref<MediaRecorder> MediaRecorder::create(Document& document, Ref<MediaStream>&& stream, Options&& options) > { >- auto privateInstance = MediaRecorder::getPrivateImpl(stream->privateStream()); >- if (!privateInstance) >- return Exception { NotSupportedError, "The MediaRecorder is unsupported on this platform"_s }; >- auto recorder = adoptRef(*new MediaRecorder(document, WTFMove(stream), WTFMove(privateInstance), WTFMove(options))); >+ auto recorder = adoptRef(*new MediaRecorder(document, WTFMove(stream), WTFMove(options))); > recorder->suspendIfNeeded(); >- return WTFMove(recorder); >-} >- >-void MediaRecorder::setCustomPrivateRecorderCreator(creatorFunction creator) >-{ >- m_customCreator = creator; >+ return recorder; > } > >-std::unique_ptr<MediaRecorderPrivate> MediaRecorder::getPrivateImpl(const MediaStreamPrivate& stream) >-{ >- if (m_customCreator) >- return m_customCreator(); >- >-#if PLATFORM(COCOA) >- return MediaRecorderPrivateAVFImpl::create(stream); >-#endif >- return nullptr; >-} >- >-MediaRecorder::MediaRecorder(Document& document, Ref<MediaStream>&& stream, std::unique_ptr<MediaRecorderPrivate>&& privateImpl, Options&& option) >+MediaRecorder::MediaRecorder(Document& document, Ref<MediaStream>&& stream, Options&& option) > : ActiveDOMObject(&document) > , m_options(WTFMove(option)) > , m_stream(WTFMove(stream)) >- , m_private(WTFMove(privateImpl)) >+ , m_private(makeUniqueRef<MediaRecorderPrivateMock>()) // FIXME: we will need to decide which MediaRecorderPrivate instance to create based on the mock enabled feature flag > { > m_tracks = WTF::map(m_stream->getTracks(), [] (auto&& track) -> Ref<MediaStreamTrackPrivate> { > return track->privateTrack(); >@@ -121,14 +95,14 @@ ExceptionOr<void> MediaRecorder::stopRecording() > { > if (state() == RecordingState::Inactive) > return Exception { InvalidStateError, "The MediaRecorder's state cannot be inactive"_s }; >- >+ > scheduleDeferredTask([this] { > if (!m_isActive || state() == RecordingState::Inactive) > return; > > stopRecordingInternal(); > ASSERT(m_state == RecordingState::Inactive); >- dispatchEvent(BlobEvent::create(eventNames().dataavailableEvent, Event::CanBubble::No, Event::IsCancelable::No, createRecordingDataBlob())); >+ dispatchEvent(BlobEvent::create(eventNames().dataavailableEvent, Event::CanBubble::No, Event::IsCancelable::No, m_private->fetchData())); > if (!m_isActive) > return; > dispatchEvent(Event::create(eventNames().stopEvent, Event::CanBubble::No, Event::IsCancelable::No)); >@@ -145,15 +119,6 @@ void MediaRecorder::stopRecordingInternal() > track->removeObserver(*this); > > m_state = RecordingState::Inactive; >- m_private->stopRecording(); >-} >- >-Ref<Blob> MediaRecorder::createRecordingDataBlob() >-{ >- auto data = m_private->fetchData(); >- if (!data) >- return Blob::create(); >- return Blob::create(*data, m_private->mimeType()); > } > > void MediaRecorder::didAddOrRemoveTrack() >@@ -199,7 +164,6 @@ void MediaRecorder::scheduleDeferredTask(Function<void()>&& function) > auto* scriptExecutionContext = this->scriptExecutionContext(); > if (!scriptExecutionContext) > return; >- > scriptExecutionContext->postTask([protectedThis = makeRef(*this), function = WTFMove(function)] (auto&) { > function(); > }); >diff --git a/Source/WebCore/Modules/mediarecorder/MediaRecorder.h b/Source/WebCore/Modules/mediarecorder/MediaRecorder.h >index 8c5a6112c5386f46378c05e446ff27b6459e1b1f..7c8aea5772c671fdbc77bae2540393b634270fdf 100644 >--- a/Source/WebCore/Modules/mediarecorder/MediaRecorder.h >+++ b/Source/WebCore/Modules/mediarecorder/MediaRecorder.h >@@ -34,12 +34,9 @@ > > namespace WebCore { > >-class Blob; > class Document; > class MediaRecorderPrivate; > >-typedef std::unique_ptr<MediaRecorderPrivate>(*creatorFunction)(); >- > class MediaRecorder final > : public ActiveDOMObject > , public RefCounted<MediaRecorder> >@@ -59,9 +56,7 @@ public: > > ~MediaRecorder(); > >- static ExceptionOr<Ref<MediaRecorder>> create(Document&, Ref<MediaStream>&&, Options&& = { }); >- >- WEBCORE_EXPORT static void setCustomPrivateRecorderCreator(creatorFunction); >+ static Ref<MediaRecorder> create(Document&, Ref<MediaStream>&&, Options&& = { }); > > RecordingState state() const { return m_state; } > >@@ -72,12 +67,8 @@ public: > ExceptionOr<void> stopRecording(); > > private: >- MediaRecorder(Document&, Ref<MediaStream>&&, std::unique_ptr<MediaRecorderPrivate>&&, Options&& = { }); >+ MediaRecorder(Document&, Ref<MediaStream>&&, Options&& = { }); > >- static std::unique_ptr<MediaRecorderPrivate> getPrivateImpl(const MediaStreamPrivate&); >- >- Ref<Blob> createRecordingDataBlob(); >- > // EventTarget > void refEventTarget() final { ref(); } > void derefEventTarget() final { deref(); } >@@ -105,17 +96,15 @@ private: > void scheduleDeferredTask(Function<void()>&&); > void setNewRecordingState(RecordingState, Ref<Event>&&); > >- static creatorFunction m_customCreator; >- > Options m_options; > Ref<MediaStream> m_stream; >- std::unique_ptr<MediaRecorderPrivate> m_private; >+ UniqueRef<MediaRecorderPrivate> m_private; > RecordingState m_state { RecordingState::Inactive }; > Vector<Ref<MediaStreamTrackPrivate>> m_tracks; > > bool m_isActive { true }; > }; >- >+ > } // namespace WebCore > > #endif // ENABLE(MEDIA_STREAM) >diff --git a/Source/WebCore/Modules/mediarecorder/MediaRecorder.idl b/Source/WebCore/Modules/mediarecorder/MediaRecorder.idl >index 8c249b1f3adce89518021c4ca38bb36171bb3ca9..469738033a0fe53b54d0cc1b5194119cc448a791 100644 >--- a/Source/WebCore/Modules/mediarecorder/MediaRecorder.idl >+++ b/Source/WebCore/Modules/mediarecorder/MediaRecorder.idl >@@ -29,7 +29,6 @@ enum RecordingState { "inactive", "recording", "paused" }; > Conditional=MEDIA_STREAM, > Constructor(MediaStream stream, optional MediaRecorderOptions options), > ConstructorCallWith=Document, >- ConstructorMayThrowException, > EnabledAtRuntime=MediaRecorder, > Exposed=Window > ] interface MediaRecorder : EventTarget { >diff --git a/Source/WebCore/SourcesCocoa.txt b/Source/WebCore/SourcesCocoa.txt >index 4fefca3cbd1cdccde3ab418a09d7fe5a14741279..52bb2fc2d7a8e87d41f9ce1601ed8157462029cf 100644 >--- a/Source/WebCore/SourcesCocoa.txt >+++ b/Source/WebCore/SourcesCocoa.txt >@@ -480,9 +480,6 @@ platform/mac/WebNSAttributedStringExtras.mm > platform/mac/WebPlaybackControlsManager.mm > platform/mac/WidgetMac.mm > >-platform/mediarecorder/MediaRecorderPrivateAVFImpl.cpp >-platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.mm >- > platform/mediasession/mac/MediaSessionInterruptionProviderMac.mm > > platform/mediastream/ios/AVAudioSessionCaptureDevice.mm >diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >index 7a26ffcd9eb754841d82e885db6127135e565da9..bea0e3e9df918d4ebab3f38ea6d3446ff3a47fd7 100644 >--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj >+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >@@ -1392,8 +1392,6 @@ > 4D3B00AB215D69A70076B983 /* MediaRecorder.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D3B00A9215D69A70076B983 /* MediaRecorder.h */; }; > 4D3B00AF215D6A690076B983 /* BlobEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D3B00AD215D6A690076B983 /* BlobEvent.h */; }; > 4D3B5016217E58B700665DB1 /* MediaRecorderPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D3B5014217E58B700665DB1 /* MediaRecorderPrivate.h */; }; >- 4D73F946218BC5FA003A3ED6 /* MediaRecorderPrivateAVFImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D73F944218BC5FA003A3ED6 /* MediaRecorderPrivateAVFImpl.h */; }; >- 4D73F94E218C4A87003A3ED6 /* MediaRecorderPrivateWriterCocoa.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D73F94C218C4A87003A3ED6 /* MediaRecorderPrivateWriterCocoa.h */; }; > 4DB7130D216ECB4D0096A4DD /* MediaRecorderErrorEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 4DB7130C216EC2BD0096A4DD /* MediaRecorderErrorEvent.h */; }; > 4E1959220A39DABA00220FE5 /* MediaFeatureNames.h in Headers */ = {isa = PBXBuildFile; fileRef = 4E1959200A39DABA00220FE5 /* MediaFeatureNames.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 4E19592A0A39DACC00220FE5 /* MediaQuery.h in Headers */ = {isa = PBXBuildFile; fileRef = 4E1959240A39DACC00220FE5 /* MediaQuery.h */; settings = {ATTRIBUTES = (Private, ); }; }; >@@ -7939,10 +7937,6 @@ > 4D3B00A9215D69A70076B983 /* MediaRecorder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaRecorder.h; sourceTree = "<group>"; }; > 4D3B00AD215D6A690076B983 /* BlobEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlobEvent.h; sourceTree = "<group>"; }; > 4D3B5014217E58B700665DB1 /* MediaRecorderPrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MediaRecorderPrivate.h; sourceTree = "<group>"; }; >- 4D73F944218BC5FA003A3ED6 /* MediaRecorderPrivateAVFImpl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MediaRecorderPrivateAVFImpl.h; sourceTree = "<group>"; }; >- 4D73F945218BC5FA003A3ED6 /* MediaRecorderPrivateAVFImpl.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MediaRecorderPrivateAVFImpl.cpp; sourceTree = "<group>"; }; >- 4D73F94C218C4A87003A3ED6 /* MediaRecorderPrivateWriterCocoa.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MediaRecorderPrivateWriterCocoa.h; sourceTree = "<group>"; }; >- 4D73F94D218C4A87003A3ED6 /* MediaRecorderPrivateWriterCocoa.mm */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; path = MediaRecorderPrivateWriterCocoa.mm; sourceTree = "<group>"; wrapsLines = 0; }; > 4D7EB3F4217C6AE600D64888 /* BlobEvent.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = BlobEvent.cpp; sourceTree = "<group>"; }; > 4D9F6B642182532B0092A9C5 /* MediaRecorderPrivateMock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MediaRecorderPrivateMock.h; sourceTree = "<group>"; }; > 4D9F6B652182532B0092A9C5 /* MediaRecorderPrivateMock.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MediaRecorderPrivateMock.cpp; sourceTree = "<group>"; }; >@@ -18165,25 +18159,13 @@ > 4D3B5012217E58A300665DB1 /* mediarecorder */ = { > isa = PBXGroup; > children = ( >- 4D3C05D421AF480900F2890A /* cocoa */, > 4D3B5014217E58B700665DB1 /* MediaRecorderPrivate.h */, >- 4D73F945218BC5FA003A3ED6 /* MediaRecorderPrivateAVFImpl.cpp */, >- 4D73F944218BC5FA003A3ED6 /* MediaRecorderPrivateAVFImpl.h */, > 4D9F6B652182532B0092A9C5 /* MediaRecorderPrivateMock.cpp */, > 4D9F6B642182532B0092A9C5 /* MediaRecorderPrivateMock.h */, > ); > path = mediarecorder; > sourceTree = "<group>"; > }; >- 4D3C05D421AF480900F2890A /* cocoa */ = { >- isa = PBXGroup; >- children = ( >- 4D73F94C218C4A87003A3ED6 /* MediaRecorderPrivateWriterCocoa.h */, >- 4D73F94D218C4A87003A3ED6 /* MediaRecorderPrivateWriterCocoa.mm */, >- ); >- path = cocoa; >- sourceTree = "<group>"; >- }; > 510310421BA8C64C003329C0 /* client */ = { > isa = PBXGroup; > children = ( >@@ -30151,8 +30133,6 @@ > 4D3B00AB215D69A70076B983 /* MediaRecorder.h in Headers */, > 4DB7130D216ECB4D0096A4DD /* MediaRecorderErrorEvent.h in Headers */, > 4D3B5016217E58B700665DB1 /* MediaRecorderPrivate.h in Headers */, >- 4D73F946218BC5FA003A3ED6 /* MediaRecorderPrivateAVFImpl.h in Headers */, >- 4D73F94E218C4A87003A3ED6 /* MediaRecorderPrivateWriterCocoa.h in Headers */, > C90843D01B18E47D00B68564 /* MediaRemoteControls.h in Headers */, > CD8ACA8F1D23971900ECC59E /* MediaRemoteSoftLink.h in Headers */, > CEEFCD7A19DB31F7003876D7 /* MediaResourceLoader.h in Headers */, >diff --git a/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.h b/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.h >index bbe8a7bf5daf990316de520c4b9d80cab8c415ef..75fb09e2a650eb58c90532dcd2e9091bb3876013 100644 >--- a/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.h >+++ b/Source/WebCore/platform/mediarecorder/MediaRecorderPrivate.h >@@ -35,20 +35,18 @@ class MediaTime; > namespace WebCore { > > class AudioStreamDescription; >+class Blob; >+class PlatformAudioData; > class MediaSample; > class MediaStreamTrackPrivate; >-class PlatformAudioData; >-class SharedBuffer; > > class MediaRecorderPrivate { > public: > virtual void sampleBufferUpdated(MediaStreamTrackPrivate&, MediaSample&) = 0; > virtual void audioSamplesAvailable(MediaStreamTrackPrivate&, const WTF::MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t) = 0; > >- virtual RefPtr<SharedBuffer> fetchData() = 0; >- virtual const String& mimeType() = 0; >+ virtual Ref<Blob> fetchData() = 0; > virtual ~MediaRecorderPrivate() = default; >- virtual void stopRecording() { } > }; > > } // namespace WebCore >diff --git a/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateAVFImpl.cpp b/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateAVFImpl.cpp >deleted file mode 100644 >index 3b9522887617a49a1d1c8958cc40db2b5d876433..0000000000000000000000000000000000000000 >--- a/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateAVFImpl.cpp >+++ /dev/null >@@ -1,123 +0,0 @@ >-/* >- * Copyright (C) 2018 Apple Inc. All rights reserved. >- * >- * Redistribution and use in source and binary forms, with or without >- * modification, are permitted provided that the following conditions >- * are met: >- * 1. Redistributions of source code must retain the above copyright >- * notice, this list of conditions and the following disclaimer. >- * 2. Redistributions in binary form must reproduce the above copyright >- * notice, this list of conditions and the following disclaimer in the >- * documentation and/or other materials provided with the distribution. >- * >- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY >- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED >- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE >- * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY >- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES >- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; >- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON >- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS >- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >- */ >- >- >-#include "config.h" >-#include "MediaRecorderPrivateAVFImpl.h" >- >-#if ENABLE(MEDIA_STREAM) >- >-#include "AudioStreamDescription.h" >-#include "MediaSample.h" >-#include "MediaStreamPrivate.h" >-#include "SharedBuffer.h" >-#include "WebAudioBufferList.h" >- >-namespace WebCore { >- >-std::unique_ptr<MediaRecorderPrivateAVFImpl> MediaRecorderPrivateAVFImpl::create(const MediaStreamPrivate& stream) >-{ >- auto instance = std::unique_ptr<MediaRecorderPrivateAVFImpl>(new MediaRecorderPrivateAVFImpl(stream)); >- if (!instance->m_isWriterReady) >- return nullptr; >- return instance; >-} >- >-MediaRecorderPrivateAVFImpl::MediaRecorderPrivateAVFImpl(const MediaStreamPrivate& stream) >-{ >- if (!m_writer.setupWriter()) >- return; >- auto tracks = stream.tracks(); >- bool videoSelected = false; >- bool audioSelected = false; >- for (auto& track : tracks) { >- if (!track->enabled() || track->ended()) >- continue; >- switch (track->type()) { >- case RealtimeMediaSource::Type::Video: { >- auto& settings = track->settings(); >- if (videoSelected || !settings.supportsWidth() || !settings.supportsHeight()) >- break; >- // FIXME: we will need to implement support for multiple video tracks, currently we only choose the first track as the recorded track. >- // FIXME: we would better to throw an exception to JavaScript if setVideoInput failed >- if (!m_writer.setVideoInput(settings.width(), settings.height())) >- return; >- m_recordedVideoTrackID = track->id(); >- videoSelected = true; >- break; >- } >- case RealtimeMediaSource::Type::Audio: { >- if (audioSelected) >- break; >- // FIXME: we will need to implement support for multiple audio tracks, currently we only choose the first track as the recorded track. >- // FIXME: we would better to throw an exception to JavaScript if setAudioInput failed >- if (!m_writer.setAudioInput()) >- return; >- m_recordedAudioTrackID = track->id(); >- audioSelected = true; >- break; >- } >- case RealtimeMediaSource::Type::None: >- break; >- } >- } >- m_isWriterReady = true; >-} >- >-void MediaRecorderPrivateAVFImpl::sampleBufferUpdated(MediaStreamTrackPrivate& track, MediaSample& sampleBuffer) >-{ >- if (track.id() != m_recordedVideoTrackID) >- return; >- m_writer.appendVideoSampleBuffer(sampleBuffer.platformSample().sample.cmSampleBuffer); >-} >- >-void MediaRecorderPrivateAVFImpl::audioSamplesAvailable(MediaStreamTrackPrivate& track, const WTF::MediaTime& mediaTime, const PlatformAudioData& data, const AudioStreamDescription& description, size_t sampleCount) >-{ >- if (track.id() != m_recordedAudioTrackID) >- return; >- ASSERT(is<WebAudioBufferList>(data)); >- ASSERT(description.platformDescription().type == PlatformDescription::CAAudioStreamBasicType); >- m_writer.appendAudioSampleBuffer(data, description, mediaTime, sampleCount); >-} >- >-void MediaRecorderPrivateAVFImpl::stopRecording() >-{ >- m_writer.stopRecording(); >-} >- >-RefPtr<SharedBuffer> MediaRecorderPrivateAVFImpl::fetchData() >-{ >- return m_writer.fetchData(); >-} >- >-const String& MediaRecorderPrivateAVFImpl::mimeType() >-{ >- static NeverDestroyed<const String> mp4MimeType(MAKE_STATIC_STRING_IMPL("video/mp4")); >- // FIXME: we will need to support more MIME types. >- return mp4MimeType; >-} >- >-} // namespace WebCore >- >-#endif // ENABLE(MEDIA_STREAM) >diff --git a/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateAVFImpl.h b/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateAVFImpl.h >deleted file mode 100644 >index 2f923c247d6c24fe604f772dea68e50498e2026e..0000000000000000000000000000000000000000 >--- a/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateAVFImpl.h >+++ /dev/null >@@ -1,59 +0,0 @@ >-/* >- * Copyright (C) 2018 Apple Inc. All rights reserved. >- * >- * Redistribution and use in source and binary forms, with or without >- * modification, are permitted provided that the following conditions >- * are met: >- * 1. Redistributions of source code must retain the above copyright >- * notice, this list of conditions and the following disclaimer. >- * 2. Redistributions in binary form must reproduce the above copyright >- * notice, this list of conditions and the following disclaimer in the >- * documentation and/or other materials provided with the distribution. >- * >- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY >- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED >- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE >- * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY >- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES >- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; >- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON >- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS >- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >- */ >- >-#pragma once >- >-#if ENABLE(MEDIA_STREAM) >- >-#include "MediaRecorderPrivate.h" >-#include "MediaRecorderPrivateWriterCocoa.h" >- >-namespace WebCore { >- >-class MediaStreamPrivate; >- >-class MediaRecorderPrivateAVFImpl final : public MediaRecorderPrivate { >-public: >- static std::unique_ptr<MediaRecorderPrivateAVFImpl> create(const MediaStreamPrivate&); >- >-private: >- explicit MediaRecorderPrivateAVFImpl(const MediaStreamPrivate&); >- >- void sampleBufferUpdated(MediaStreamTrackPrivate&, MediaSample&) final; >- void audioSamplesAvailable(MediaStreamTrackPrivate&, const WTF::MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t) final; >- RefPtr<SharedBuffer> fetchData() final; >- const String& mimeType() final; >- void stopRecording(); >- >- String m_recordedVideoTrackID; >- String m_recordedAudioTrackID; >- >- MediaRecorderPrivateWriter m_writer; >- >- bool m_isWriterReady { false }; >-}; >- >-} // namespace WebCore >- >-#endif // ENABLE(MEDIA_STREAM) >diff --git a/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateMock.cpp b/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateMock.cpp >index c34a7afcd9f4d79925cb9313810f0292009b2a99..a4a8bcbd860bd3692ce4be76f521c6690420765e 100644 >--- a/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateMock.cpp >+++ b/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateMock.cpp >@@ -28,8 +28,8 @@ > > #if ENABLE(MEDIA_STREAM) > >+#include "Blob.h" > #include "MediaStreamTrackPrivate.h" >-#include "SharedBuffer.h" > > namespace WebCore { > >@@ -56,19 +56,13 @@ void MediaRecorderPrivateMock::generateMockString(MediaStreamTrackPrivate& track > m_buffer.append("\r\n---------\r\n"); > } > >-RefPtr<SharedBuffer> MediaRecorderPrivateMock::fetchData() >+Ref<Blob> MediaRecorderPrivateMock::fetchData() > { > auto locker = holdLock(m_bufferLock); > Vector<uint8_t> value(m_buffer.length()); > memcpy(value.data(), m_buffer.characters8(), m_buffer.length()); > m_buffer.clear(); >- return SharedBuffer::create(WTFMove(value)); >-} >- >-const String& MediaRecorderPrivateMock::mimeType() >-{ >- static NeverDestroyed<const String> textPlainMimeType(MAKE_STATIC_STRING_IMPL("text/plain")); >- return textPlainMimeType; >+ return Blob::create(WTFMove(value), "text/plain"); > } > > } // namespace WebCore >diff --git a/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateMock.h b/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateMock.h >index 6ca817315f870b4e83aec761259f57b09bab97a6..4d9adb60392e7a9ebf191ea7180616c9a8f004b1 100644 >--- a/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateMock.h >+++ b/Source/WebCore/platform/mediarecorder/MediaRecorderPrivateMock.h >@@ -32,14 +32,14 @@ > > namespace WebCore { > >+class Blob; > class MediaStreamTrackPrivate; > >-class WEBCORE_EXPORT MediaRecorderPrivateMock final : public MediaRecorderPrivate { >+class MediaRecorderPrivateMock final : public MediaRecorderPrivate { > private: > void sampleBufferUpdated(MediaStreamTrackPrivate&, MediaSample&) final; > void audioSamplesAvailable(MediaStreamTrackPrivate&, const WTF::MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t) final; >- RefPtr<SharedBuffer> fetchData() final; >- const String& mimeType() final; >+ Ref<Blob> fetchData() final; > > void generateMockString(MediaStreamTrackPrivate&); > >diff --git a/Source/WebCore/platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.h b/Source/WebCore/platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.h >deleted file mode 100644 >index b874b7520fdf147ad2627577a8f522267209dc0e..0000000000000000000000000000000000000000 >--- a/Source/WebCore/platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.h >+++ /dev/null >@@ -1,84 +0,0 @@ >-/* >- * Copyright (C) 2018 Apple Inc. All rights reserved. >- * >- * Redistribution and use in source and binary forms, with or without >- * modification, are permitted provided that the following conditions >- * are met: >- * 1. Redistributions of source code must retain the above copyright >- * notice, this list of conditions and the following disclaimer. >- * 2. Redistributions in binary form must reproduce the above copyright >- * notice, this list of conditions and the following disclaimer in the >- * documentation and/or other materials provided with the distribution. >- * >- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY >- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED >- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE >- * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY >- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES >- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; >- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON >- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS >- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >- */ >- >-#pragma once >- >-#if ENABLE(MEDIA_STREAM) >- >-#include "SharedBuffer.h" >-#include <wtf/Deque.h> >-#include <wtf/Lock.h> >-#include <wtf/RetainPtr.h> >-#include <wtf/ThreadSafeRefCounted.h> >-#include <wtf/threads/BinarySemaphore.h> >- >-typedef struct opaqueCMSampleBuffer *CMSampleBufferRef; >- >-OBJC_CLASS AVAssetWriter; >-OBJC_CLASS AVAssetWriterInput; >- >-namespace WTF { >-class MediaTime; >-} >- >-namespace WebCore { >- >-class AudioStreamDescription; >-class PlatformAudioData; >- >-class MediaRecorderPrivateWriter : public ThreadSafeRefCounted<MediaRecorderPrivateWriter, WTF::DestructionThread::Main> { >-public: >- MediaRecorderPrivateWriter() = default; >- >- bool setupWriter(); >- bool setVideoInput(int width, int height); >- bool setAudioInput(); >- void appendVideoSampleBuffer(CMSampleBufferRef); >- void appendAudioSampleBuffer(const PlatformAudioData&, const AudioStreamDescription&, const WTF::MediaTime&, size_t); >- void stopRecording(); >- RefPtr<SharedBuffer> fetchData(); >- >-private: >- RetainPtr<AVAssetWriter> m_writer; >- RetainPtr<AVAssetWriterInput> m_videoInput; >- RetainPtr<AVAssetWriterInput> m_audioInput; >- >- String m_path; >- Lock m_videoLock; >- Lock m_audioLock; >- BinarySemaphore m_finishWritingSemaphore; >- BinarySemaphore m_finishWritingAudioSemaphore; >- BinarySemaphore m_finishWritingVideoSemaphore; >- bool m_hasStartedWriting { false }; >- bool m_isStopped { false }; >- bool m_isFirstAudioSample { true }; >- dispatch_queue_t m_audioPullQueue; >- dispatch_queue_t m_videoPullQueue; >- Deque<RetainPtr<CMSampleBufferRef>> m_videoBufferPool; >- Deque<RetainPtr<CMSampleBufferRef>> m_audioBufferPool; >-}; >- >-} // namespace WebCore >- >-#endif // ENABLE(MEDIA_STREAM) >diff --git a/Source/WebCore/platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.mm b/Source/WebCore/platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.mm >deleted file mode 100644 >index 90aeee4c2bb5f31dcc4f92db1eb0a16ac8848c83..0000000000000000000000000000000000000000 >--- a/Source/WebCore/platform/mediarecorder/cocoa/MediaRecorderPrivateWriterCocoa.mm >+++ /dev/null >@@ -1,285 +0,0 @@ >-/* >- * Copyright (C) 2018 Apple Inc. All rights reserved. >- * >- * Redistribution and use in source and binary forms, with or without >- * modification, are permitted provided that the following conditions >- * are met: >- * 1. Redistributions of source code must retain the above copyright >- * notice, this list of conditions and the following disclaimer. >- * 2. Redistributions in binary form must reproduce the above copyright >- * notice, this list of conditions and the following disclaimer in the >- * documentation and/or other materials provided with the distribution. >- * >- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >- * THE POSSIBILITY OF SUCH DAMAGE. >- */ >- >-#include "config.h" >-#include "MediaRecorderPrivateWriterCocoa.h" >- >-#if ENABLE(MEDIA_STREAM) && USE(AVFOUNDATION) >- >-#include "AudioStreamDescription.h" >-#include "FileSystem.h" >-#include "Logging.h" >-#include "WebAudioBufferList.h" >-#include <AVFoundation/AVAssetWriter.h> >-#include <AVFoundation/AVAssetWriterInput.h> >-#include <pal/cf/CoreMediaSoftLink.h> >- >-typedef AVAssetWriter AVAssetWriterType; >-typedef AVAssetWriterInput AVAssetWriterInputType; >- >-SOFT_LINK_FRAMEWORK_OPTIONAL(AVFoundation) >- >-SOFT_LINK_CLASS(AVFoundation, AVAssetWriter) >-SOFT_LINK_CLASS(AVFoundation, AVAssetWriterInput) >- >-SOFT_LINK_CONSTANT(AVFoundation, AVFileTypeMPEG4, NSString *) >-SOFT_LINK_CONSTANT(AVFoundation, AVVideoCodecKey, NSString *) >-SOFT_LINK_CONSTANT(AVFoundation, AVVideoCodecH264, NSString *) >-SOFT_LINK_CONSTANT(AVFoundation, AVVideoWidthKey, NSString *) >-SOFT_LINK_CONSTANT(AVFoundation, AVVideoHeightKey, NSString *) >-SOFT_LINK_CONSTANT(AVFoundation, AVMediaTypeVideo, NSString *) >-SOFT_LINK_CONSTANT(AVFoundation, AVMediaTypeAudio, NSString *) >-SOFT_LINK_CONSTANT(AVFoundation, AVEncoderBitRatePerChannelKey, NSString *) >-SOFT_LINK_CONSTANT(AVFoundation, AVFormatIDKey, NSString *) >-SOFT_LINK_CONSTANT(AVFoundation, AVNumberOfChannelsKey, NSString *) >-SOFT_LINK_CONSTANT(AVFoundation, AVSampleRateKey, NSString *) >- >-#define AVFileTypeMPEG4 getAVFileTypeMPEG4() >-#define AVMediaTypeAudio getAVMediaTypeAudio() >-#define AVMediaTypeVideo getAVMediaTypeVideo() >-#define AVVideoCodecKey getAVVideoCodecKey() >-#define AVVideoCodecH264 getAVVideoCodecH264() >-#define AVVideoWidthKey getAVVideoWidthKey() >-#define AVVideoHeightKey getAVVideoHeightKey() >-#define AVEncoderBitRatePerChannelKey getAVEncoderBitRatePerChannelKey() >-#define AVFormatIDKey getAVFormatIDKey() >-#define AVNumberOfChannelsKey getAVNumberOfChannelsKey() >-#define AVSampleRateKey getAVSampleRateKey() >- >-namespace WebCore { >- >-using namespace PAL; >- >-bool MediaRecorderPrivateWriter::setupWriter() >-{ >- ASSERT(!m_writer); >- >- NSString *directory = FileSystem::createTemporaryDirectory(@"videos"); >- NSString *filename = [NSString stringWithFormat:@"/%lld.mp4", CMClockGetTime(CMClockGetHostTimeClock()).value]; >- NSString *path = [directory stringByAppendingString:filename]; >- >- NSURL *outputURL = [NSURL fileURLWithPath:path]; >- m_path = [path UTF8String]; >- NSError *error = nil; >- m_writer = adoptNS([allocAVAssetWriterInstance() initWithURL:outputURL fileType:AVFileTypeMPEG4 error:&error]); >- if (error) { >- RELEASE_LOG_ERROR(MediaStream, "create AVAssetWriter instance failed with error code %ld", (long)error.code); >- m_writer = nullptr; >- return false; >- } >- return true; >-} >- >-bool MediaRecorderPrivateWriter::setVideoInput(int width, int height) >-{ >- ASSERT(!m_videoInput); >- >- NSDictionary *videoSettings = @{ AVVideoCodecKey: AVVideoCodecH264, AVVideoWidthKey: [NSNumber numberWithInt:width], AVVideoHeightKey: [NSNumber numberWithInt:height] }; >- m_videoInput = adoptNS([allocAVAssetWriterInputInstance() initWithMediaType:AVMediaTypeVideo outputSettings:videoSettings sourceFormatHint:nil]); >- [m_videoInput setExpectsMediaDataInRealTime:true]; >- >- if (![m_writer canAddInput:m_videoInput.get()]) { >- m_videoInput = nullptr; >- RELEASE_LOG_ERROR(MediaStream, "the video input is not allowed to add to the AVAssetWriter"); >- return false; >- } >- [m_writer addInput:m_videoInput.get()]; >- m_videoPullQueue = dispatch_queue_create("WebCoreVideoRecordingPullBufferQueue", DISPATCH_QUEUE_SERIAL); >- return true; >-} >- >-bool MediaRecorderPrivateWriter::setAudioInput() >-{ >- ASSERT(!m_audioInput); >- >- NSDictionary *audioSettings = @{ AVEncoderBitRatePerChannelKey : @(28000), AVFormatIDKey : @(kAudioFormatMPEG4AAC), AVNumberOfChannelsKey : @(1), AVSampleRateKey : @(22050) }; >- >- m_audioInput = adoptNS([allocAVAssetWriterInputInstance() initWithMediaType:AVMediaTypeAudio outputSettings:audioSettings sourceFormatHint:nil]); >- [m_audioInput setExpectsMediaDataInRealTime:true]; >- >- if (![m_writer canAddInput:m_audioInput.get()]) { >- m_audioInput = nullptr; >- RELEASE_LOG_ERROR(MediaStream, "the audio input is not allowed to add to the AVAssetWriter"); >- return false; >- } >- [m_writer addInput:m_audioInput.get()]; >- m_audioPullQueue = dispatch_queue_create("WebCoreAudioRecordingPullBufferQueue", DISPATCH_QUEUE_SERIAL); >- return true; >-} >- >-static inline CMSampleBufferRef copySampleBufferWithCurrentTimeStamp(CMSampleBufferRef originalBuffer) >-{ >- CMTime startTime = CMClockGetTime(CMClockGetHostTimeClock()); >- CMItemCount count = 0; >- CMSampleBufferGetSampleTimingInfoArray(originalBuffer, 0, nil, &count); >- >- Vector<CMSampleTimingInfo> timeInfo(count); >- CMSampleBufferGetSampleTimingInfoArray(originalBuffer, count, timeInfo.data(), &count); >- >- for (CMItemCount i = 0; i < count; i++) { >- timeInfo[i].decodeTimeStamp = kCMTimeInvalid; >- timeInfo[i].presentationTimeStamp = startTime; >- } >- >- CMSampleBufferRef newBuffer; >- CMSampleBufferCreateCopyWithNewTiming(kCFAllocatorDefault, originalBuffer, count, timeInfo.data(), &newBuffer); >- return newBuffer; >-} >- >-void MediaRecorderPrivateWriter::appendVideoSampleBuffer(CMSampleBufferRef sampleBuffer) >-{ >- ASSERT(m_videoInput); >- if (m_isStopped) >- return; >- >- if (!m_hasStartedWriting) { >- if (![m_writer startWriting]) { >- m_isStopped = true; >- RELEASE_LOG_ERROR(MediaStream, "create AVAssetWriter instance failed with error code %ld", (long)[m_writer error]); >- return; >- } >- [m_writer startSessionAtSourceTime:CMClockGetTime(CMClockGetHostTimeClock())]; >- m_hasStartedWriting = true; >- RefPtr<MediaRecorderPrivateWriter> protectedThis = this; >- [m_videoInput requestMediaDataWhenReadyOnQueue:m_videoPullQueue usingBlock:[this, protectedThis] { >- do { >- if (![m_videoInput isReadyForMoreMediaData]) >- break; >- auto locker = holdLock(m_videoLock); >- if (m_videoBufferPool.isEmpty()) >- break; >- auto buffer = m_videoBufferPool.takeFirst(); >- locker.unlockEarly(); >- if (![m_videoInput appendSampleBuffer:buffer.get()]) >- break; >- } while (true); >- if (m_isStopped && m_videoBufferPool.isEmpty()) { >- [m_videoInput markAsFinished]; >- m_finishWritingVideoSemaphore.signal(); >- } >- }]; >- return; >- } >- CMSampleBufferRef bufferWithCurrentTime = copySampleBufferWithCurrentTimeStamp(sampleBuffer); >- auto locker = holdLock(m_videoLock); >- m_videoBufferPool.append(retainPtr(bufferWithCurrentTime)); >-} >- >-void MediaRecorderPrivateWriter::appendAudioSampleBuffer(const PlatformAudioData& data, const AudioStreamDescription& description, const WTF::MediaTime&, size_t sampleCount) >-{ >- ASSERT(m_audioInput); >- if ((!m_hasStartedWriting && m_videoInput) || m_isStopped) >- return; >- CMSampleBufferRef sampleBuffer; >- CMFormatDescriptionRef format; >- OSStatus error; >- auto& basicDescription = *WTF::get<const AudioStreamBasicDescription*>(description.platformDescription().description); >- error = CMAudioFormatDescriptionCreate(kCFAllocatorDefault, &basicDescription, 0, NULL, 0, NULL, NULL, &format); >- if (m_isFirstAudioSample) { >- if (!m_videoInput) { >- // audio-only recording. >- if (![m_writer startWriting]) { >- m_isStopped = true; >- return; >- } >- [m_writer startSessionAtSourceTime:CMClockGetTime(CMClockGetHostTimeClock())]; >- m_hasStartedWriting = true; >- } >- m_isFirstAudioSample = false; >- RefPtr<MediaRecorderPrivateWriter> protectedThis = this; >- [m_audioInput requestMediaDataWhenReadyOnQueue:m_audioPullQueue usingBlock:[this, protectedThis] { >- do { >- if (![m_audioInput isReadyForMoreMediaData]) >- break; >- auto locker = holdLock(m_audioLock); >- if (m_audioBufferPool.isEmpty()) >- break; >- auto buffer = m_audioBufferPool.takeFirst(); >- locker.unlockEarly(); >- [m_audioInput appendSampleBuffer:buffer.get()]; >- } while (true); >- if (m_isStopped && m_audioBufferPool.isEmpty()) { >- [m_audioInput markAsFinished]; >- m_finishWritingAudioSemaphore.signal(); >- } >- }]; >- } >- CMTime startTime = CMClockGetTime(CMClockGetHostTimeClock()); >- >- error = CMAudioSampleBufferCreateWithPacketDescriptions(kCFAllocatorDefault, NULL, false, NULL, NULL, format, sampleCount, startTime, NULL, &sampleBuffer); >- if (error) >- return; >- error = CMSampleBufferSetDataBufferFromAudioBufferList(sampleBuffer, kCFAllocatorDefault, kCFAllocatorDefault, 0, downcast<WebAudioBufferList>(data).list()); >- if (error) >- return; >- >- auto locker = holdLock(m_audioLock); >- m_audioBufferPool.append(retainPtr(sampleBuffer)); >-} >- >-void MediaRecorderPrivateWriter::stopRecording() >-{ >- m_isStopped = true; >- if (!m_hasStartedWriting) >- return; >- ASSERT([m_writer status] == AVAssetWriterStatusWriting); >- if (m_videoInput) >- m_finishWritingVideoSemaphore.wait(); >- >- if (m_audioInput) >- m_finishWritingAudioSemaphore.wait(); >- >- [m_writer finishWritingWithCompletionHandler:^{ >- m_isStopped = false; >- m_hasStartedWriting = false; >- m_isFirstAudioSample = true; >- if (m_videoInput) { >- m_videoInput.clear(); >- m_videoInput = nullptr; >- dispatch_release(m_videoPullQueue); >- } >- if (m_audioInput) { >- m_audioInput.clear(); >- m_audioInput = nullptr; >- dispatch_release(m_audioPullQueue); >- } >- m_writer.clear(); >- m_writer = nullptr; >- m_finishWritingSemaphore.signal(); >- }]; >-} >- >-RefPtr<SharedBuffer> MediaRecorderPrivateWriter::fetchData() >-{ >- if ((m_path.isEmpty() && !m_isStopped) || !m_hasStartedWriting) >- return nullptr; >- >- m_finishWritingSemaphore.wait(); >- return SharedBuffer::createWithContentsOfFile(m_path); >-} >- >-} // namespace WebCore >- >-#endif // ENABLE(MEDIA_STREAM) && USE(AVFOUNDATION) >diff --git a/Source/WebCore/testing/Internals.cpp b/Source/WebCore/testing/Internals.cpp >index 7cf44ff693dae4021de5cd1147b938174248dcf3..77bfc9821a5dcf054408b28e710c1b3adf236492 100644 >--- a/Source/WebCore/testing/Internals.cpp >+++ b/Source/WebCore/testing/Internals.cpp >@@ -228,8 +228,6 @@ > #endif > > #if ENABLE(MEDIA_STREAM) >-#include "MediaRecorder.h" >-#include "MediaRecorderPrivateMock.h" > #include "MediaStream.h" > #include "MockRealtimeMediaSourceCenter.h" > #endif >@@ -519,10 +517,6 @@ void Internals::resetToConsistentState(Page& page) > page.setFullscreenControlsHidden(false); > > MediaEngineConfigurationFactory::disableMock(); >- >-#if ENABLE(MEDIA_STREAM) >- WebCore::MediaRecorder::setCustomPrivateRecorderCreator(nullptr); >-#endif > } > > Internals::Internals(Document& document) >@@ -1479,16 +1473,6 @@ void Internals::setMockMediaCaptureDevicesEnabled(bool enabled) > WebCore::DeprecatedGlobalSettings::setMockCaptureDevicesEnabled(enabled); > } > >-static std::unique_ptr<MediaRecorderPrivate> createRecorderMockSource() >-{ >- return std::unique_ptr<MediaRecorderPrivateMock>(new MediaRecorderPrivateMock); >-} >- >-void Internals::setCustomPrivateRecorderCreator() >-{ >- WebCore::MediaRecorder::setCustomPrivateRecorderCreator(createRecorderMockSource); >-} >- > #endif > > ExceptionOr<Ref<DOMRect>> Internals::absoluteCaretBounds() >diff --git a/Source/WebCore/testing/Internals.h b/Source/WebCore/testing/Internals.h >index c7c9eee9769c0a7a417d3afa68987531cd1dbd7a..8ae3443bb10adbd51fa01ca5262320bc0e5c8f38 100644 >--- a/Source/WebCore/testing/Internals.h >+++ b/Source/WebCore/testing/Internals.h >@@ -507,7 +507,6 @@ public: > > #if ENABLE(MEDIA_STREAM) > void setMockMediaCaptureDevicesEnabled(bool); >- void setCustomPrivateRecorderCreator(); > #endif > > #if ENABLE(WEB_RTC) >diff --git a/Source/WebCore/testing/Internals.idl b/Source/WebCore/testing/Internals.idl >index e9aad58cb8754942bc063e8430553baff5cf6a05..2719346114bd0cbb16e01452062f1fe4f62cf965 100644 >--- a/Source/WebCore/testing/Internals.idl >+++ b/Source/WebCore/testing/Internals.idl >@@ -575,7 +575,6 @@ enum CompositingPolicy { > [Conditional=WIRELESS_PLAYBACK_TARGET] void setMockMediaPlaybackTargetPickerEnabled(boolean enabled); > [Conditional=WIRELESS_PLAYBACK_TARGET, MayThrowException] void setMockMediaPlaybackTargetPickerState(DOMString deviceName, DOMString deviceState); > [Conditional=MEDIA_STREAM] void setMockMediaCaptureDevicesEnabled(boolean enabled); >- [Conditional=MEDIA_STREAM] void setCustomPrivateRecorderCreator(); > > [Conditional=WEB_RTC] void emulateRTCPeerConnectionPlatformEvent(RTCPeerConnection connection, DOMString action); > [Conditional=WEB_RTC] void useMockRTCPeerConnectionFactory(DOMString testCase); >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index cc443d9c56671529e053838d4dd5e3917f19222c..f26e561bc52f077f52c3092dae66902fccd26d2b 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,24 @@ >+2018-12-05 Commit Queue <commit-queue@webkit.org> >+ >+ Unreviewed, rolling out r238844, r238846, and r238874. >+ https://bugs.webkit.org/show_bug.cgi?id=192414 >+ >+ The layout tests added with this change are flaky. (Requested >+ by ryanhaddad on #webkit). >+ >+ Reverted changesets: >+ >+ "Implement non-timeslice mode encoding for MediaRecorder" >+ https://bugs.webkit.org/show_bug.cgi?id=192069 >+ https://trac.webkit.org/changeset/238844 >+ >+ "Fix the build" >+ https://trac.webkit.org/changeset/238846 >+ >+ "Fix MediaRecorder flaky tests" >+ https://bugs.webkit.org/show_bug.cgi?id=192371 >+ https://trac.webkit.org/changeset/238874 >+ > 2018-12-05 Per Arne Vollan <pvollan@apple.com> > > Layout Test http/tests/misc/resource-timing-resolution.html is a flaky failure >diff --git a/LayoutTests/http/wpt/mediarecorder/MediaRecorder-AV-audio-only-dataavailable-expected.txt b/LayoutTests/http/wpt/mediarecorder/MediaRecorder-AV-audio-only-dataavailable-expected.txt >deleted file mode 100644 >index 4ace29c6c002daa7f91a725c582dd9ff423c967a..0000000000000000000000000000000000000000 >--- a/LayoutTests/http/wpt/mediarecorder/MediaRecorder-AV-audio-only-dataavailable-expected.txt >+++ /dev/null >@@ -1,3 +0,0 @@ >- >-PASS MediaRecorder can successfully record the audio for a audio-only stream >- >diff --git a/LayoutTests/http/wpt/mediarecorder/MediaRecorder-AV-audio-only-dataavailable.html b/LayoutTests/http/wpt/mediarecorder/MediaRecorder-AV-audio-only-dataavailable.html >deleted file mode 100644 >index 5b175daf35feadede9c658824ef4cbd40461e9af..0000000000000000000000000000000000000000 >--- a/LayoutTests/http/wpt/mediarecorder/MediaRecorder-AV-audio-only-dataavailable.html >+++ /dev/null >@@ -1,45 +0,0 @@ >-<!doctype html> >-<html> >-<head> >- <title>MediaRecorder can successfully record the audio for a audio-only stream</title> >- <link rel="help" href="https://w3c.github.io/mediacapture-record/MediaRecorder.html#mediarecorder"> >- <script src="/resources/testharness.js"></script> >- <script src="/resources/testharnessreport.js"></script> >-</head> >-<body> >-<audio id="player"> >-</audio> >-<script> >- >- const ac = new webkitAudioContext(); >- const osc = ac.createOscillator(); >- const dest = ac.createMediaStreamDestination(); >- const audio = dest.stream; >- osc.connect(dest); >- const recorder = new MediaRecorder(audio); >- recorder.ondataavailable = (blobEvent) => { >- assert_true(blobEvent instanceof BlobEvent, 'the type of event should be BlobEvent'); >- assert_equals(blobEvent.type, 'dataavailable', 'the event type should be dataavailable'); >- assert_true(blobEvent.isTrusted, 'isTrusted should be true when the event is created by C++'); >- assert_true(blobEvent.data instanceof Blob, 'the type of data should be Blob'); >- assert_true(blobEvent.data.size > 0, 'the blob should contain some buffers'); >- const player = document.getElementById("player"); >- player.src = window.URL.createObjectURL(blobEvent.data); >- player.oncanplay = () => { >- assert_greater_than(player.duration, 0, 'the duration should be greater than 0'); >- done(); >- }; >- player.load(); >- }; >- >- recorder.start(); >- osc.start(); >- assert_equals(recorder.state, 'recording', 'MediaRecorder has been started successfully'); >- setTimeout(() => { >- recorder.stop(); >- osc.stop(); >- }, 500); >- >-</script> >-</body> >-</html> >diff --git a/LayoutTests/http/wpt/mediarecorder/MediaRecorder-AV-audio-video-dataavailable-expected.txt b/LayoutTests/http/wpt/mediarecorder/MediaRecorder-AV-audio-video-dataavailable-expected.txt >deleted file mode 100644 >index 708c1285298e5345bc7cf9eef6816cf0f6215b2b..0000000000000000000000000000000000000000 >--- a/LayoutTests/http/wpt/mediarecorder/MediaRecorder-AV-audio-video-dataavailable-expected.txt >+++ /dev/null >@@ -1,4 +0,0 @@ >- >- >-PASS MediaRecorder can successfully record the video for a audio-video stream >- >diff --git a/LayoutTests/http/wpt/mediarecorder/MediaRecorder-AV-audio-video-dataavailable.html b/LayoutTests/http/wpt/mediarecorder/MediaRecorder-AV-audio-video-dataavailable.html >deleted file mode 100644 >index 012f241206ca142c07a883d0e9b715343a62bcb0..0000000000000000000000000000000000000000 >--- a/LayoutTests/http/wpt/mediarecorder/MediaRecorder-AV-audio-video-dataavailable.html >+++ /dev/null >@@ -1,115 +0,0 @@ >-<!doctype html> >-<html> >-<head> >- <title>MediaRecorder can successfully record the video for a audio-video stream</title> >- <link rel="help" href="https://w3c.github.io/mediacapture-record/MediaRecorder.html#mediarecorder"> >- <script src="/resources/testharness.js"></script> >- <script src="/resources/testharnessreport.js"></script> >- <script src="../common/canvas-tests.js"></script> >- <link rel="stylesheet" href="../common/canvas-tests.css"> >-</head> >-<body> >-<div> >- <video id="player" controls="true"> >- </video> >-</div> >-<div> >- <canvas id="canvas" width="200" height="200"> >- </canvas> >- <canvas id="frame" width="200" height="200" style="visibility:visible; display:block"> >- </canvas> >-</div> >-<script> >- var context; >- var drawStartTime; >- >- function createVideoStream() { >- const canvas = document.getElementById("canvas"); >- context = canvas.getContext('2d'); >- return canvas.captureStream(); >- } >- >- function doRedImageDraw() { >- if (context) { >- context.fillStyle = "#ff0000"; >- context.fillRect(0, 0, 200, 200); >- if (Date.now() - drawStartTime < 2000) { >- window.requestAnimationFrame(doRedImageDraw); >- } else { >- drawStartTime = Date.now(); >- doGreenImageDraw(); >- } >- } >- } >- >- function doGreenImageDraw() { >- if (context) { >- context.fillStyle = "#00ff00"; >- context.fillRect(0, 0, 200, 200); >- if (Date.now() - drawStartTime < 10000) { >- window.requestAnimationFrame(doGreenImageDraw); >- } >- } >- } >- >- const ac = new webkitAudioContext(); >- const osc = ac.createOscillator(); >- const dest = ac.createMediaStreamDestination(); >- const audio = dest.stream; >- osc.connect(dest); >- >- const video = createVideoStream(); >- assert_equals(video.getAudioTracks().length, 0, "video mediastream starts with no audio track"); >- assert_equals(audio.getAudioTracks().length, 1, "audio mediastream starts with one audio track"); >- video.addTrack(audio.getAudioTracks()[0]); >- assert_equals(video.getAudioTracks().length, 1, "video mediastream starts with one audio track"); >- const recorder = new MediaRecorder(video); >- let mode = 0; >- >- recorder.ondataavailable = (blobEvent) => { >- assert_true(blobEvent instanceof BlobEvent, 'the type of event should be BlobEvent'); >- assert_equals(blobEvent.type, 'dataavailable', 'the event type should be dataavailable'); >- assert_true(blobEvent.isTrusted, 'isTrusted should be true when the event is created by C++'); >- assert_true(blobEvent.data instanceof Blob, 'the type of data should be Blob'); >- assert_true(blobEvent.data.size > 0, 'the blob should contain some buffers'); >- player.src = window.URL.createObjectURL(blobEvent.data); >- const resFrame = document.getElementById("frame"); >- const resContext = resFrame.getContext('2d'); >- player.oncanplay = () => { >- assert_greater_than(player.duration, 0.1, 'the duration should be greater than 100ms'); >- player.play(); >- }; >- player.onplay = () => { >- if (mode === 2) >- return; >- player.pause(); >- player.currentTime = 1; >- }; >- player.onseeked = () => { >- resContext.drawImage(player, 0, 0); >- if (!mode) { >- _assertPixelApprox(resFrame, 20, 20, 255, 0, 0, 255, "20, 20", "255, 0, 0, 255", 50); >- _assertPixelApprox(resFrame, 50, 50, 255, 0, 0, 255, "50, 50", "255, 0, 0, 255", 50); >- mode = 1; >- player.currentTime = 3; >- } else if (mode === 1) { >- _assertPixelApprox(resFrame, 21, 21, 0, 255, 0, 255, "21, 21", "0, 255, 0, 255", 50); >- _assertPixelApprox(resFrame, 51, 51, 0, 255, 0, 255, "51, 51", "0, 255, 0, 255", 50); >- mode =2; >- done(); >- } >- }; >- player.load(); >- }; >- recorder.start(); >- assert_equals(recorder.state, 'recording', 'MediaRecorder has been started successfully'); >- drawStartTime = Date.now(); >- doRedImageDraw(); >- osc.start(); >- setTimeout(() => { >- recorder.stop(); >- }, 4000); >- >-</script> >-</body> >-</html> >diff --git a/LayoutTests/http/wpt/mediarecorder/MediaRecorder-AV-video-only-dataavailable-expected.txt b/LayoutTests/http/wpt/mediarecorder/MediaRecorder-AV-video-only-dataavailable-expected.txt >deleted file mode 100644 >index d69a7be74e1b2e0fb15adf434e8368a7a21c0704..0000000000000000000000000000000000000000 >--- a/LayoutTests/http/wpt/mediarecorder/MediaRecorder-AV-video-only-dataavailable-expected.txt >+++ /dev/null >@@ -1,4 +0,0 @@ >- >- >-PASS MediaRecorder can successfully record the video for a video-only stream >- >diff --git a/LayoutTests/http/wpt/mediarecorder/MediaRecorder-AV-video-only-dataavailable.html b/LayoutTests/http/wpt/mediarecorder/MediaRecorder-AV-video-only-dataavailable.html >deleted file mode 100644 >index bb68c7ba23136d863765dede00d6b05db04cc66b..0000000000000000000000000000000000000000 >--- a/LayoutTests/http/wpt/mediarecorder/MediaRecorder-AV-video-only-dataavailable.html >+++ /dev/null >@@ -1,103 +0,0 @@ >-<!doctype html> >-<html> >-<head> >- <title>MediaRecorder can successfully record the video for a video-only stream</title> >- <link rel="help" href="https://w3c.github.io/mediacapture-record/MediaRecorder.html#mediarecorder"> >- <script src="/resources/testharness.js"></script> >- <script src="/resources/testharnessreport.js"></script> >- <script src="../common/canvas-tests.js"></script> >- <link rel="stylesheet" href="../common/canvas-tests.css"> >-</head> >-<body> >-<div> >- <video id="player" controls=true> >- </video> >-</div> >-<div> >- <canvas id="canvas" width="200" height="200"> >- </canvas> >- <canvas id="frame" width="200" height="200" style="visibility:visible; display:block"> >- </canvas> >-</div> >-<script> >- var context; >- var drawStartTime; >- >- function createVideoStream() { >- const canvas = document.getElementById("canvas"); >- context = canvas.getContext('2d'); >- return canvas.captureStream(); >- } >- >- function doRedImageDraw() { >- if (context) { >- context.fillStyle = "#ff0000"; >- context.fillRect(0, 0, 200, 200); >- if (Date.now() - drawStartTime < 2000) { >- window.requestAnimationFrame(doRedImageDraw); >- } else { >- drawStartTime = Date.now(); >- doGreenImageDraw(); >- } >- } >- } >- >- function doGreenImageDraw() { >- if (context) { >- context.fillStyle = "#00ff00"; >- context.fillRect(0, 0, 200, 200); >- if (Date.now() - drawStartTime < 10000) { >- window.requestAnimationFrame(doGreenImageDraw); >- } >- } >- } >- >- const video = createVideoStream(); >- const recorder = new MediaRecorder(video); >- let mode = 0; >- recorder.ondataavailable = (blobEvent) => { >- assert_true(blobEvent instanceof BlobEvent, 'the type of event should be BlobEvent'); >- assert_equals(blobEvent.type, 'dataavailable', 'the event type should be dataavailable'); >- assert_true(blobEvent.isTrusted, 'isTrusted should be true when the event is created by C++'); >- assert_true(blobEvent.data instanceof Blob, 'the type of data should be Blob'); >- assert_true(blobEvent.data.size > 0, 'the blob should contain some buffers'); >- player.src = window.URL.createObjectURL(blobEvent.data); >- const resFrame = document.getElementById("frame"); >- const resContext = resFrame.getContext('2d'); >- player.oncanplay = () => { >- assert_greater_than(player.duration, 0.1, 'the duration should be greater than 100ms'); >- player.play(); >- }; >- player.onplay = () => { >- if (mode === 2) >- return; >- player.pause(); >- player.currentTime = 1; >- }; >- player.onseeked = () => { >- resContext.drawImage(player, 0, 0); >- if (!mode) { >- _assertPixelApprox(resFrame, 20, 20, 255, 0, 0, 255, "20,2 0", "255, 0, 0, 255", 50); >- _assertPixelApprox(resFrame, 50, 50, 255, 0, 0, 255, "50, 50", "255, 0, 0, 255", 50); >- mode = 1; >- player.currentTime = 3; >- } else if (mode === 1){ >- _assertPixelApprox(resFrame, 21, 21, 0, 255, 0, 255, "21, 21", "0, 255, 0, 255", 50); >- _assertPixelApprox(resFrame, 51, 51, 0, 255, 0, 255, "51, 51", "0, 255, 0, 255", 50); >- mode = 2; >- done(); >- } >- }; >- player.load(); >- }; >- recorder.start(); >- assert_equals(recorder.state, 'recording', 'MediaRecorder has been started successfully'); >- drawStartTime = Date.now(); >- doRedImageDraw(); >- setTimeout(() => { >- recorder.stop(); >- }, 4000); >- >-</script> >-</body> >-</html> >diff --git a/LayoutTests/http/wpt/mediarecorder/MediaRecorder-dataavailable.html b/LayoutTests/http/wpt/mediarecorder/MediaRecorder-dataavailable.html >index 4ac3d6d50bf17b682f4932bb0ea3aaafeefc903f..bdca7f7a40a137c18fb705230acffbd24e935ab9 100644 >--- a/LayoutTests/http/wpt/mediarecorder/MediaRecorder-dataavailable.html >+++ b/LayoutTests/http/wpt/mediarecorder/MediaRecorder-dataavailable.html >@@ -12,9 +12,6 @@ > <script> > var context; > >- if (window.internals) >- internals.setCustomPrivateRecorderCreator(); >- > function createVideoStream() { > const canvas = document.getElementById("canvas"); > context = canvas.getContext('2d'); >@@ -47,7 +44,7 @@ > drawSomethingOnCanvas(); > setTimeout(() => { > recorder.stop(); >- }, 1000) >+ }, 2000) > }, 'MediaRecorder will fire a dataavailable event with a blob data for a video-only stream when stop() is called'); > > async_test(t => { >@@ -68,7 +65,7 @@ > setTimeout(() => { > recorder.stop(); > osc.stop(); >- }, 1000); >+ }, 2000); > }, 'MediaRecorder will fire a dataavailable event with a blob data for a audio-only stream when stop() is called'); > > async_test(t => { >@@ -96,7 +93,7 @@ > setTimeout(() => { > recorder.stop(); > osc.stop(); >- }, 1000); >+ }, 2000); > }, 'MediaRecorder will fire a dataavailable event with a blob data for a video-audio stream when stop() is called'); > > </script> >diff --git a/LayoutTests/http/wpt/mediarecorder/MediaRecorder-mock-dataavailable.html b/LayoutTests/http/wpt/mediarecorder/MediaRecorder-mock-dataavailable.html >index 43ee488752a4bb46e36464b4b048c4b64f3e9766..1286b8bde4094fd44037f89dc567f35a7605e056 100644 >--- a/LayoutTests/http/wpt/mediarecorder/MediaRecorder-mock-dataavailable.html >+++ b/LayoutTests/http/wpt/mediarecorder/MediaRecorder-mock-dataavailable.html >@@ -12,9 +12,6 @@ > <script> > var context; > >- if (window.internals) >- internals.setCustomPrivateRecorderCreator(); >- > function createVideoStream() { > const canvas = document.getElementById("canvas"); > context = canvas.getContext('2d'); >@@ -44,7 +41,7 @@ > drawSomethingOnCanvas(); > setTimeout(() => { > recorder.stop(); >- }, 1000); >+ }, 2000); > }, 'MediaRecorder will fire a dataavailable event which only contains video buffers for a video-only stream when stop() is called'); > > async_test(t => { >@@ -70,7 +67,7 @@ > setTimeout(() => { > recorder.stop(); > osc.stop(); >- }, 1000); >+ }, 2000); > }, 'MediaRecorder will fire a dataavailable event which only contains audio buffers for a audio-only stream when stop() is called'); > > async_test(t => { >@@ -103,7 +100,7 @@ > setTimeout(() => { > recorder.stop(); > osc.stop(); >- }, 1000); >+ }, 2000); > }, 'MediaRecorder will fire a dataavailable event which only contains both video and audio buffers when stop() is called'); > > </script> >diff --git a/LayoutTests/platform/gtk/TestExpectations b/LayoutTests/platform/gtk/TestExpectations >index 3688e3cd5a35b536ac6aafb10b6f5c1f1b6e3e3b..ac1c0d249d5d105d2c1e83d662ed55a5dc7217af 100644 >--- a/LayoutTests/platform/gtk/TestExpectations >+++ b/LayoutTests/platform/gtk/TestExpectations >@@ -599,9 +599,6 @@ webkit.org/b/186933 webrtc/getUserMedia-webaudio-autoplay.html > > imported/w3c/web-platform-tests/webrtc/ [ Skip ] > http/tests/webrtc [ Skip ] >- >-http/wpt/mediarecorder [ Skip ] >- > # The MediaStream implementation is also still not completed > webkit.org/b/79203 fast/mediastream/mock-media-source-webaudio.html [ Timeout ] > webkit.org/b/79203 fast/mediastream/getUserMedia-webaudio.html [ Failure ] >diff --git a/LayoutTests/platform/wpe/TestExpectations b/LayoutTests/platform/wpe/TestExpectations >index 5c70a82b7d65bf01afe55b5ad50af1dfeabf4cac..a2df5e2ce902dcc65449df8f17ce03cce25b956c 100644 >--- a/LayoutTests/platform/wpe/TestExpectations >+++ b/LayoutTests/platform/wpe/TestExpectations >@@ -494,8 +494,6 @@ http/tests/webrtc [ Skip ] > http/tests/websocket [ Skip ] > http/tests/xmlhttprequest [ Skip ] > >-http/wpt/mediarecorder [ Skip ] >- > # Service-workers tests that fail, time out or crash. > webkit.org/b/175419 http/tests/workers/service/controller-change.html [ Skip ] > webkit.org/b/175419 http/tests/workers/service/no-page-cache-when-controlled.html [ Skip ]
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 192414
: 356625