diff --git a/dom/media/tests/mochitest/test_peerConnection_webAudio.html b/dom/media/tests/mochitest/test_peerConnection_webAudio.html index 2ca1488274..bc1552346e 100644 --- a/dom/media/tests/mochitest/test_peerConnection_webAudio.html +++ b/dom/media/tests/mochitest/test_peerConnection_webAudio.html @@ -17,12 +17,24 @@ createHTML({ // output side. We then sanity check the audio by comparing the frequency domain // data from both analysers. +/* + * Use as callback to Array.reduce to get an object { value, index } + * that contains the largest element in the array. + */ +var maxWithIndex = function(a, b, i) { + if (b >= a.value) { + return { value: b, index: i }; + } else { + return a; + } +}; + runNetworkTest(function() { var test = new PeerConnectionTest(); var audioContext = new AudioContext(); - var inputAnalyser; - var outputAnalyser; + var inputAnalyser, outputAnalyser; + var inputData, outputData; test.setMediaConstraints([{audio: true}], []); test.chain.replace("PC_LOCAL_GUM", [ @@ -56,12 +68,35 @@ runNetworkTest(function() { return Promise.resolve(); }]); test.chain.append([ - function CHECK_AUDIO_FLOW(test) { - var inputData = new Uint8Array(inputAnalyser.frequencyBinCount); + function GET_INPUT_DATA(test) { + inputData = new Uint8Array(inputAnalyser.frequencyBinCount); inputAnalyser.getByteFrequencyData(inputData); - - var outputData = new Uint8Array(outputAnalyser.frequencyBinCount); - outputAnalyser.getByteFrequencyData(outputData); + return Promise.resolve(); + }, + function GET_OUTPUT_DATA(test) { + // We've seen completely silent output with e10s, suggesting that the + // machine is overloaded. Here we wait for actual audio data on the + // output side before we proceed. + return new Promise(resolve => { + is(test.pcRemote.mediaCheckers.length, 1, "One media element on remote side"); + var elem = test.pcRemote.mediaCheckers[0].element; + var data = new Uint8Array(outputAnalyser.frequencyBinCount); + elem.ontimeupdate = ev => { + outputAnalyser.getByteFrequencyData(data); + if (data.reduce(maxWithIndex, { value: -1, index: -1 }).value === 0) { + info("Waiting for output data... time: " + elem.currentTime); + return; + } + elem.ontimeupdate = null; + outputData = data; + resolve(); + }; + }); + }, + function CHECK_AUDIO_FLOW(test) { + // This is for sanity check only. We'll deem that the streams are working + // if the global maxima in the frequency domain for both the input and + // the output are within 10 (out of 1024) steps of each other. is(inputData.length, outputData.length, "Equally sized datasets"); var numChecks = 0; diff --git a/gfx/layers/LayersLogging.cpp b/gfx/layers/LayersLogging.cpp index d379207be5..446bc2774b 100644 --- a/gfx/layers/LayersLogging.cpp +++ b/gfx/layers/LayersLogging.cpp @@ -8,6 +8,7 @@ #include "LayersLogging.h" #include // for uint8_t #include "gfxColor.h" // for gfxRGBA +#include "ImageTypes.h" // for ImageFormat #include "mozilla/gfx/Matrix.h" // for Matrix4x4, Matrix #include "mozilla/gfx/Point.h" // for IntSize #include "nsDebug.h" // for NS_ERROR @@ -334,6 +335,83 @@ AppendToString(std::stringstream& aStream, mozilla::gfx::SurfaceFormat format, case SurfaceFormat::A8: aStream << "SurfaceFormat::A8"; break; case SurfaceFormat::YUV: aStream << "SurfaceFormat::YUV"; break; case SurfaceFormat::UNKNOWN: aStream << "SurfaceFormat::UNKNOWN"; break; + default: + NS_ERROR("unknown surface format"); + aStream << "???"; + } + + aStream << sfx; +} + +void +AppendToString(std::stringstream& aStream, gfx::SurfaceType aType, + const char* pfx, const char* sfx) +{ + aStream << pfx; + switch(aType) { + case SurfaceType::DATA: + aStream << "SurfaceType::DATA"; break; + case SurfaceType::D2D1_BITMAP: + aStream << "SurfaceType::D2D1_BITMAP"; break; + case SurfaceType::D2D1_DRAWTARGET: + aStream << "SurfaceType::D2D1_DRAWTARGET"; break; + case SurfaceType::CAIRO: + aStream << "SurfaceType::CAIRO"; break; + case SurfaceType::CAIRO_IMAGE: + aStream << "SurfaceType::CAIRO_IMAGE"; break; + case SurfaceType::COREGRAPHICS_IMAGE: + aStream << "SurfaceType::COREGRAPHICS_IMAGE"; break; + case SurfaceType::COREGRAPHICS_CGCONTEXT: + aStream << "SurfaceType::COREGRAPHICS_CGCONTEXT"; break; + case SurfaceType::SKIA: + aStream << "SurfaceType::SKIA"; break; + case SurfaceType::DUAL_DT: + aStream << "SurfaceType::DUAL_DT"; break; + case SurfaceType::D2D1_1_IMAGE: + aStream << "SurfaceType::D2D1_1_IMAGE"; break; + case SurfaceType::RECORDING: + aStream << "SurfaceType::RECORDING"; break; + case SurfaceType::TILED: + aStream << "SurfaceType::TILED"; break; + default: + NS_ERROR("unknown surface type"); + aStream << "???"; + } + aStream << sfx; +} + + +void +AppendToString(std::stringstream& aStream, ImageFormat format, + const char* pfx, const char* sfx) +{ + aStream << pfx; + switch (format) { + case ImageFormat::PLANAR_YCBCR: + aStream << "ImageFormat::PLANAR_YCBCR"; break; + case ImageFormat::GRALLOC_PLANAR_YCBCR: + aStream << "ImageFormat::GRALLOC_PLANAR_YCBCR"; break; + case ImageFormat::GONK_CAMERA_IMAGE: + aStream << "ImageFormat::GONK_CAMERA_IMAGE"; break; + case ImageFormat::SHARED_RGB: + aStream << "ImageFormat::SHARED_RGB"; break; + case ImageFormat::CAIRO_SURFACE: + aStream << "ImageFormat::CAIRO_SURFACE"; break; + case ImageFormat::MAC_IOSURFACE: + aStream << "ImageFormat::MAC_IOSURFACE"; break; + case ImageFormat::SURFACE_TEXTURE: + aStream << "ImageFormat::SURFACE_TEXTURE"; break; + case ImageFormat::EGLIMAGE: + aStream << "ImageFormat::EGLIMAGE"; break; + case ImageFormat::D3D9_RGB32_TEXTURE: + aStream << "ImageFormat::D3D9_RBG32_TEXTURE"; break; + case ImageFormat::OVERLAY_IMAGE: + aStream << "ImageFormat::OVERLAY_IMAGE"; break; + case ImageFormat::D3D11_SHARE_HANDLE_TEXTURE: + aStream << "ImageFormat::D3D11_SHARE_HANDLE_TEXTURE"; break; + default: + NS_ERROR("unknown image format"); + aStream << "???"; } aStream << sfx; diff --git a/gfx/layers/LayersLogging.h b/gfx/layers/LayersLogging.h index 33eb4dbbfe..1e621e4613 100644 --- a/gfx/layers/LayersLogging.h +++ b/gfx/layers/LayersLogging.h @@ -24,6 +24,8 @@ class Matrix4x4; template struct RectTyped; } // namespace gfx +enum class ImageFormat; + namespace layers { void @@ -210,6 +212,14 @@ void AppendToString(std::stringstream& aStream, mozilla::gfx::SurfaceFormat format, const char* pfx="", const char* sfx=""); +void +AppendToString(std::stringstream& aStream, gfx::SurfaceType format, + const char* pfx="", const char* sfx=""); + +void +AppendToString(std::stringstream& aStream, ImageFormat format, + const char* pfx="", const char* sfx=""); + // Sometimes, you just want a string from a single value. template std::string diff --git a/js/src/configure.in b/js/src/configure.in index 947f9cc569..5f8830f12b 100644 --- a/js/src/configure.in +++ b/js/src/configure.in @@ -2445,6 +2445,28 @@ AC_PROG_GCC_TRADITIONAL AC_FUNC_MEMCMP AC_CHECK_FUNCS([getc_unlocked _getc_nolock gmtime_r localtime_r]) +dnl check for clock_gettime(), the CLOCK_MONOTONIC clock +AC_CACHE_CHECK(for clock_gettime(CLOCK_MONOTONIC), + ac_cv_clock_monotonic, + [for libs in "" -lrt; do + _SAVE_LIBS="$LIBS" + LIBS="$LIBS $libs" + AC_TRY_LINK([#include ], + [ struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); ], + ac_cv_clock_monotonic=$libs + LIBS="$_SAVE_LIBS" + break, + ac_cv_clock_monotonic=no) + LIBS="$_SAVE_LIBS" + done]) +if test "$ac_cv_clock_monotonic" != "no"; then + HAVE_CLOCK_MONOTONIC=1 + REALTIME_LIBS=$ac_cv_clock_monotonic + AC_DEFINE(HAVE_CLOCK_MONOTONIC) + AC_SUBST(HAVE_CLOCK_MONOTONIC) + AC_SUBST_LIST(REALTIME_LIBS) +fi dnl Checks for math functions. dnl ======================================================== diff --git a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp index e2a33263e9..e9fe658764 100644 --- a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp +++ b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp @@ -19,6 +19,7 @@ #if !defined(MOZILLA_EXTERNAL_LINKAGE) #include "VideoSegment.h" #include "Layers.h" +#include "LayersLogging.h" #include "ImageTypes.h" #include "ImageContainer.h" #include "VideoUtils.h" @@ -43,11 +44,13 @@ #endif #include "mozilla/gfx/Point.h" #include "mozilla/gfx/Types.h" +#include "mozilla/UniquePtr.h" #include "logging.h" using namespace mozilla; using namespace mozilla::gfx; +using namespace mozilla::layers; // Logging context MOZ_MTLOG_MODULE("mediapipeline") @@ -688,6 +691,8 @@ nsresult MediaPipelineTransmit::ReplaceTrack(DOMMediaStream *domstream, } domstream_ = domstream; // Detach clears it stream_ = domstream->GetStream(); + // Unsets the track id after RemoveListener() takes effect. + listener_->UnsetTrackId(stream_->GraphImpl()); track_id_ = track_id; AttachToTrack(track_id); return NS_OK; @@ -853,6 +858,24 @@ nsresult MediaPipeline::PipelineTransport::SendRtcpPacket_s( out_len); } +void MediaPipelineTransmit::PipelineListener:: +UnsetTrackId(MediaStreamGraphImpl* graph) { +#ifndef USE_FAKE_MEDIA_STREAMS + class Message : public ControlMessage { + public: + Message(PipelineListener* listener) : + ControlMessage(nullptr), listener_(listener) {} + virtual void Run() override + { + listener_->UnsetTrackIdImpl(); + } + nsRefPtr listener_; + }; + graph->AppendMessage(new Message(this)); +#else + UnsetTrackIdImpl(); +#endif +} // Called if we're attached with AddDirectListener() void MediaPipelineTransmit::PipelineListener:: NotifyRealtimeData(MediaStreamGraph* graph, TrackID tid, @@ -1048,7 +1071,7 @@ void MediaPipelineTransmit::PipelineListener::ProcessAudioChunk( void MediaPipelineTransmit::PipelineListener::ProcessVideoChunk( VideoSessionConduit* conduit, VideoChunk& chunk) { - layers::Image *img = chunk.mFrame.GetImage(); + Image *img = chunk.mFrame.GetImage(); // We now need to send the video frame to the other side if (!img) { @@ -1057,7 +1080,7 @@ void MediaPipelineTransmit::PipelineListener::ProcessVideoChunk( } if (!enabled_ || chunk.mFrame.GetForceBlack()) { - gfx::IntSize size = img->GetSize(); + IntSize size = img->GetSize(); uint32_t yPlaneLen = YSIZE(size.width, size.height); uint32_t cbcrPlaneLen = 2 * CRSIZE(size.width, size.height); uint32_t length = yPlaneLen + cbcrPlaneLen; @@ -1087,7 +1110,7 @@ void MediaPipelineTransmit::PipelineListener::ProcessVideoChunk( ImageFormat format = img->GetFormat(); #ifdef WEBRTC_GONK - layers::GrallocImage* nativeImage = img->AsGrallocImage(); + GrallocImage* nativeImage = img->AsGrallocImage(); if (nativeImage) { android::sp graphicBuffer = nativeImage->GetGraphicBuffer(); int pixelFormat = graphicBuffer->getPixelFormat(); /* PixelFormat is an enum == int */ @@ -1097,10 +1120,10 @@ void MediaPipelineTransmit::PipelineListener::ProcessVideoChunk( // all android must support this destFormat = mozilla::kVideoYV12; break; - case layers::GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP: + case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP: destFormat = mozilla::kVideoNV21; break; - case layers::GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_P: + case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_P: destFormat = mozilla::kVideoI420; break; default: @@ -1121,95 +1144,125 @@ void MediaPipelineTransmit::PipelineListener::ProcessVideoChunk( height, destFormat, 0); graphicBuffer->unlock(); + return; } else #endif if (format == ImageFormat::PLANAR_YCBCR) { // Cast away constness b/c some of the accessors are non-const - layers::PlanarYCbCrImage* yuv = - const_cast( - static_cast(img)); - // Big-time assumption here that this is all contiguous data coming - // from getUserMedia or other sources. - const layers::PlanarYCbCrData *data = yuv->GetData(); + PlanarYCbCrImage* yuv = const_cast( + static_cast(img)); - uint8_t *y = data->mYChannel; - uint8_t *cb = data->mCbChannel; - uint8_t *cr = data->mCrChannel; - uint32_t width = yuv->GetSize().width; - uint32_t height = yuv->GetSize().height; - uint32_t length = yuv->GetDataSize(); - // NOTE: length may be rounded up or include 'other' data (see - // YCbCrImageDataDeserializerBase::ComputeMinBufferSize()) + const PlanarYCbCrData *data = yuv->GetData(); + if (data) { + uint8_t *y = data->mYChannel; + uint8_t *cb = data->mCbChannel; + uint8_t *cr = data->mCrChannel; + uint32_t width = yuv->GetSize().width; + uint32_t height = yuv->GetSize().height; + uint32_t length = yuv->GetDataSize(); + // NOTE: length may be rounded up or include 'other' data (see + // YCbCrImageDataDeserializerBase::ComputeMinBufferSize()) - // SendVideoFrame only supports contiguous YCrCb 4:2:0 buffers - // Verify it's contiguous and in the right order - if (cb != (y + YSIZE(width, height)) || - cr != (cb + CRSIZE(width, height))) { - MOZ_ASSERT(false, "Incorrect cb/cr pointers in ProcessVideoChunk()!"); - return; + // XXX Consider modifying these checks if we ever implement + // any subclasses of PlanarYCbCrImage that allow disjoint buffers such + // that y+3(width*height)/2 might go outside the allocation or there are + // pads between y, cr and cb. + // GrallocImage can have wider strides, and so in some cases + // would encode as garbage. If we need to encode it we'll either want to + // modify SendVideoFrame or copy/move the data in the buffer. + if (cb == (y + YSIZE(width, height)) && + cr == (cb + CRSIZE(width, height)) && + length >= I420SIZE(width, height)) { + MOZ_MTLOG(ML_DEBUG, "Sending an I420 video frame"); + conduit->SendVideoFrame(y, I420SIZE(width, height), width, height, mozilla::kVideoI420, 0); + return; + } else { + MOZ_MTLOG(ML_ERROR, "Unsupported PlanarYCbCrImage format: " + "width=" << width << ", height=" << height << ", y=" << y + << "\n Expected: cb=y+" << YSIZE(width, height) + << ", cr=y+" << YSIZE(width, height) + + CRSIZE(width, height) + << "\n Observed: cb=y+" << cb - y + << ", cr=y+" << cr - y + << "\n ystride=" << data->mYStride + << ", yskip=" << data->mYSkip + << "\n cbcrstride=" << data->mCbCrStride + << ", cbskip=" << data->mCbSkip + << ", crskip=" << data->mCrSkip + << "\n ywidth=" << data->mYSize.width + << ", yheight=" << data->mYSize.height + << "\n cbcrwidth=" << data->mCbCrSize.width + << ", cbcrheight=" << data->mCbCrSize.height); + NS_ASSERTION(false, "Unsupported PlanarYCbCrImage format"); + } } - if (length < I420SIZE(width, height)) { - MOZ_ASSERT(false, "Invalid length for ProcessVideoChunk()"); - return; - } - // XXX Consider modifying these checks if we ever implement - // any subclasses of PlanarYCbCrImage that allow disjoint buffers such - // that y+3(width*height)/2 might go outside the allocation or there are - // pads between y, cr and cb. - // GrallocImage can have wider strides, and so in some cases - // would encode as garbage. If we need to encode it we'll either want to - // modify SendVideoFrame or copy/move the data in the buffer. + } - // OK, pass it on to the conduit - MOZ_MTLOG(ML_DEBUG, "Sending a video frame"); - // Not much for us to do with an error - conduit->SendVideoFrame(y, I420SIZE(width, height), width, height, mozilla::kVideoI420, 0); - } else if(format == ImageFormat::CAIRO_SURFACE) { - layers::CairoImage* rgb = - const_cast( - static_cast(img)); - - gfx::IntSize size = rgb->GetSize(); - int half_width = (size.width + 1) >> 1; - int half_height = (size.height + 1) >> 1; - int c_size = half_width * half_height; - int buffer_size = YSIZE(size.width, size.height) + 2 * c_size; - uint8* yuv = (uint8*) malloc(buffer_size); // fallible - if (!yuv) - return; - - int cb_offset = YSIZE(size.width, size.height); - int cr_offset = cb_offset + c_size; - RefPtr tempSurf = rgb->GetAsSourceSurface(); - RefPtr surf = tempSurf->GetDataSurface(); - - switch (surf->GetFormat()) { - case gfx::SurfaceFormat::B8G8R8A8: - case gfx::SurfaceFormat::B8G8R8X8: - libyuv::ARGBToI420(static_cast(surf->GetData()), surf->Stride(), - yuv, size.width, - yuv + cb_offset, half_width, - yuv + cr_offset, half_width, - size.width, size.height); - break; - case gfx::SurfaceFormat::R5G6B5: - libyuv::RGB565ToI420(static_cast(surf->GetData()), surf->Stride(), - yuv, size.width, - yuv + cb_offset, half_width, - yuv + cr_offset, half_width, - size.width, size.height); - break; - default: - MOZ_MTLOG(ML_ERROR, "Unsupported RGB video format"); - MOZ_ASSERT(PR_FALSE); - } - conduit->SendVideoFrame(yuv, buffer_size, size.width, size.height, mozilla::kVideoI420, 0); - free(yuv); - } else { - MOZ_MTLOG(ML_ERROR, "Unsupported video format"); - MOZ_ASSERT(PR_FALSE); + RefPtr surf = img->GetAsSourceSurface(); + if (!surf) { + MOZ_MTLOG(ML_ERROR, "Getting surface from " << Stringify(format) << " image failed"); return; } + + RefPtr data = surf->GetDataSurface(); + if (!data) { + MOZ_MTLOG(ML_ERROR, "Getting data surface from " << Stringify(format) + << " image with " << Stringify(surf->GetType()) << "(" + << Stringify(surf->GetFormat()) << ") surface failed"); + return; + } + + IntSize size = img->GetSize(); + int half_width = (size.width + 1) >> 1; + int half_height = (size.height + 1) >> 1; + int c_size = half_width * half_height; + int buffer_size = YSIZE(size.width, size.height) + 2 * c_size; + UniquePtr yuv_scoped(new (fallible) uint8[buffer_size]); + if (!yuv_scoped) + return; + uint8* yuv = yuv_scoped.get(); + + DataSourceSurface::ScopedMap map(data, DataSourceSurface::READ); + if (!map.IsMapped()) { + MOZ_MTLOG(ML_ERROR, "Reading DataSourceSurface from " << Stringify(format) + << " image with " << Stringify(surf->GetType()) << "(" + << Stringify(surf->GetFormat()) << ") surface failed"); + return; + } + + int rv; + int cb_offset = YSIZE(size.width, size.height); + int cr_offset = cb_offset + c_size; + switch (surf->GetFormat()) { + case SurfaceFormat::B8G8R8A8: + case SurfaceFormat::B8G8R8X8: + rv = libyuv::ARGBToI420(static_cast(map.GetData()), + map.GetStride(), + yuv, size.width, + yuv + cb_offset, half_width, + yuv + cr_offset, half_width, + size.width, size.height); + break; + case SurfaceFormat::R5G6B5: + rv = libyuv::RGB565ToI420(static_cast(map.GetData()), + map.GetStride(), + yuv, size.width, + yuv + cb_offset, half_width, + yuv + cr_offset, half_width, + size.width, size.height); + break; + default: + MOZ_MTLOG(ML_ERROR, "Unsupported RGB video format" << Stringify(surf->GetFormat())); + MOZ_ASSERT(PR_FALSE); + return; + } + if (rv != 0) { + MOZ_MTLOG(ML_ERROR, Stringify(surf->GetFormat()) << " to I420 conversion failed"); + return; + } + MOZ_MTLOG(ML_DEBUG, "Sending an I420 video frame converted from " << + Stringify(surf->GetFormat())); + conduit->SendVideoFrame(yuv, buffer_size, size.width, size.height, mozilla::kVideoI420, 0); } #endif @@ -1413,14 +1466,14 @@ MediaPipelineReceiveVideo::PipelineListener::PipelineListener( width_(640), height_(480), #if defined(MOZILLA_XPCOMRT_API) - image_(new mozilla::SimpleImageBuffer), + image_(new SimpleImageBuffer), #elif defined(MOZILLA_INTERNAL_API) image_container_(), image_(), #endif monitor_("Video PipelineListener") { #if !defined(MOZILLA_EXTERNAL_LINKAGE) - image_container_ = layers::LayerManager::CreateImageContainer(); + image_container_ = LayerManager::CreateImageContainer(); #endif } @@ -1429,7 +1482,7 @@ void MediaPipelineReceiveVideo::PipelineListener::RenderVideoFrame( unsigned int buffer_size, uint32_t time_stamp, int64_t render_time, - const RefPtr& video_image) { + const RefPtr& video_image) { #ifdef MOZILLA_INTERNAL_API ReentrantMonitorAutoEnter enter(monitor_); @@ -1447,11 +1500,11 @@ void MediaPipelineReceiveVideo::PipelineListener::RenderVideoFrame( #else ImageFormat format = ImageFormat::PLANAR_YCBCR; #endif - nsRefPtr image = image_container_->CreateImage(format); - layers::PlanarYCbCrImage* yuvImage = static_cast(image.get()); + nsRefPtr image = image_container_->CreateImage(format); + PlanarYCbCrImage* yuvImage = static_cast(image.get()); uint8_t* frame = const_cast(static_cast (buffer)); - layers::PlanarYCbCrData yuvData; + PlanarYCbCrData yuvData; yuvData.mYChannel = frame; yuvData.mYSize = IntSize(width_, height_); yuvData.mYStride = width_; @@ -1485,7 +1538,7 @@ NotifyPull(MediaStreamGraph* graph, StreamTime desired_time) { #if defined(MOZILLA_XPCOMRT_API) nsRefPtr image = image_; #elif defined(MOZILLA_INTERNAL_API) - nsRefPtr image = image_; + nsRefPtr image = image_; // our constructor sets track_rate_ to the graph rate MOZ_ASSERT(track_rate_ == source_->GraphRate()); #endif diff --git a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.h b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.h index ea7698fafb..91f7210567 100644 --- a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.h +++ b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.h @@ -466,6 +466,12 @@ public: } } + // Dispatches setting the internal TrackID to TRACK_INVALID to the media + // graph thread to keep it in sync with other MediaStreamGraph operations + // like RemoveListener() and AddListener(). The TrackID will be updated on + // the next NewData() callback. + void UnsetTrackId(MediaStreamGraphImpl* graph); + void SetActive(bool active) { active_ = active; } void SetEnabled(bool enabled) { enabled_ = enabled; } TrackID trackid() { @@ -487,6 +493,11 @@ public: const MediaSegment& media) override; private: + void UnsetTrackIdImpl() { + MutexAutoLock lock(mMutex); + track_id_ = track_id_external_ = TRACK_INVALID; + } + void NewData(MediaStreamGraph* graph, TrackID tid, StreamTime offset, uint32_t events, diff --git a/media/webrtc/signaling/test/FakeMediaStreams.h b/media/webrtc/signaling/test/FakeMediaStreams.h index 32f2518d15..1c565288f0 100644 --- a/media/webrtc/signaling/test/FakeMediaStreams.h +++ b/media/webrtc/signaling/test/FakeMediaStreams.h @@ -30,6 +30,7 @@ class nsIDOMWindow; namespace mozilla { class MediaStreamGraph; + class MediaStreamGraphImpl; class MediaSegment; }; @@ -103,6 +104,7 @@ class Fake_MediaStream { virtual Fake_SourceMediaStream *AsSourceStream() { return nullptr; } + virtual mozilla::MediaStreamGraphImpl *GraphImpl() { return nullptr; } virtual nsresult Start() { return NS_OK; } virtual nsresult Stop() { return NS_OK; } virtual void StopStream() {} diff --git a/xpcom/ds/TimeStamp.cpp b/mozglue/misc/TimeStamp.cpp similarity index 95% rename from xpcom/ds/TimeStamp.cpp rename to mozglue/misc/TimeStamp.cpp index 1d6a6c58d4..932b75c995 100644 --- a/xpcom/ds/TimeStamp.cpp +++ b/mozglue/misc/TimeStamp.cpp @@ -9,7 +9,8 @@ */ #include "mozilla/TimeStamp.h" -#include "prenv.h" +#include +#include namespace mozilla { @@ -45,13 +46,13 @@ struct TimeStampInitialization static TimeStampInitialization sInitOnce; -TimeStamp +MFBT_API TimeStamp TimeStamp::ProcessCreation(bool& aIsInconsistent) { aIsInconsistent = false; if (sInitOnce.mProcessCreation.IsNull()) { - char* mozAppRestart = PR_GetEnv("MOZ_APP_RESTART"); + char* mozAppRestart = getenv("MOZ_APP_RESTART"); TimeStamp ts; /* When calling PR_SetEnv() with an empty value the existing variable may diff --git a/xpcom/ds/TimeStamp.h b/mozglue/misc/TimeStamp.h similarity index 96% rename from xpcom/ds/TimeStamp.h rename to mozglue/misc/TimeStamp.h index 826886312c..6eb348d9df 100644 --- a/xpcom/ds/TimeStamp.h +++ b/mozglue/misc/TimeStamp.h @@ -12,8 +12,7 @@ #include "mozilla/Attributes.h" #include "mozilla/FloatingPoint.h" #include "mozilla/TypeTraits.h" -#include "nscore.h" -#include "nsDebug.h" +#include "mozilla/Types.h" namespace IPC { template struct ParamTraits; @@ -39,10 +38,10 @@ class TimeStamp; class BaseTimeDurationPlatformUtils { public: - static double ToSeconds(int64_t aTicks); - static double ToSecondsSigDigits(int64_t aTicks); - static int64_t TicksFromMilliseconds(double aMilliseconds); - static int64_t ResolutionInTicks(); + static MFBT_API double ToSeconds(int64_t aTicks); + static MFBT_API double ToSecondsSigDigits(int64_t aTicks); + static MFBT_API int64_t TicksFromMilliseconds(double aMilliseconds); + static MFBT_API int64_t ResolutionInTicks(); }; /** @@ -206,7 +205,6 @@ public: BaseTimeDuration operator*(const uint64_t aMultiplier) const { if (aMultiplier > INT64_MAX) { - NS_WARNING("Out-of-range multiplier when multiplying BaseTimeDuration"); return Forever(); } return FromTicks(ValueCalculator::Multiply(mValue, aMultiplier)); @@ -428,8 +426,8 @@ public: * lower precision, usually 15.6 ms, but with very good performance benefit. * Use it for measurements of longer times, like >200ms timeouts. */ - static TimeStamp Now() { return Now(true); } - static TimeStamp NowLoRes() { return Now(false); } + static MFBT_API TimeStamp Now() { return Now(true); } + static MFBT_API TimeStamp NowLoRes() { return Now(false); } /** * Return a timestamp representing the time when the current process was @@ -443,14 +441,14 @@ public: * @returns A timestamp representing the time when the process was created, * this timestamp is always valid even when errors are reported */ - static TimeStamp ProcessCreation(bool& aIsInconsistent); + static MFBT_API TimeStamp ProcessCreation(bool& aIsInconsistent); /** * Records a process restart. After this call ProcessCreation() will return * the time when the browser was restarted instead of the actual time when * the process was created. */ - static void RecordProcessRestart(); + static MFBT_API void RecordProcessRestart(); /** * Compute the difference between two timestamps. Both must be non-null. @@ -536,8 +534,8 @@ public: // two TimeStamps, or scaling TimeStamps, is nonsense and must never // be allowed. - static nsresult Startup(); - static void Shutdown(); + static MFBT_API void Startup(); + static MFBT_API void Shutdown(); private: friend struct IPC::ParamTraits; @@ -545,7 +543,7 @@ private: MOZ_IMPLICIT TimeStamp(TimeStampValue aValue) : mValue(aValue) {} - static TimeStamp Now(bool aHighResolution); + static MFBT_API TimeStamp Now(bool aHighResolution); /** * Computes the uptime of the current process in microseconds. The result @@ -555,7 +553,7 @@ private: * @returns The number of microseconds since the calling process was started * or 0 if an error was encountered while computing the uptime */ - static uint64_t ComputeProcessUptime(); + static MFBT_API uint64_t ComputeProcessUptime(); /** * When built with PRIntervalTime, a value of 0 means this instance diff --git a/xpcom/ds/TimeStamp_darwin.cpp b/mozglue/misc/TimeStamp_darwin.cpp similarity index 97% rename from xpcom/ds/TimeStamp_darwin.cpp rename to mozglue/misc/TimeStamp_darwin.cpp index f9c3852dc5..f30bc98460 100644 --- a/xpcom/ds/TimeStamp_darwin.cpp +++ b/mozglue/misc/TimeStamp_darwin.cpp @@ -23,7 +23,6 @@ #include #include "mozilla/TimeStamp.h" -#include "nsDebug.h" // Estimate of the smallest duration of time we can measure. static uint64_t sResolution; @@ -120,11 +119,11 @@ BaseTimeDurationPlatformUtils::ResolutionInTicks() return static_cast(sResolution); } -nsresult +void TimeStamp::Startup() { if (gInitialized) { - return NS_OK; + return; } mach_timebase_info_data_t timebaseInfo; @@ -133,7 +132,7 @@ TimeStamp::Startup() // to cache the result. kern_return_t kr = mach_timebase_info(&timebaseInfo); if (kr != KERN_SUCCESS) { - NS_RUNTIMEABORT("mach_timebase_info failed"); + MOZ_RELEASE_ASSERT(false, "mach_timebase_info failed"); } sNsPerTick = double(timebaseInfo.numer) / timebaseInfo.denom; @@ -149,7 +148,7 @@ TimeStamp::Startup() gInitialized = true; - return NS_OK; + return; } void diff --git a/xpcom/ds/TimeStamp_posix.cpp b/mozglue/misc/TimeStamp_posix.cpp similarity index 93% rename from xpcom/ds/TimeStamp_posix.cpp rename to mozglue/misc/TimeStamp_posix.cpp index 5a09c9c7a8..e9c4620d6b 100644 --- a/xpcom/ds/TimeStamp_posix.cpp +++ b/mozglue/misc/TimeStamp_posix.cpp @@ -48,10 +48,7 @@ #include "mozilla/Snprintf.h" #include "mozilla/TimeStamp.h" -#include "nsCRT.h" -#include "prprf.h" -#include "prthread.h" -#include "nsDebug.h" +#include // Estimate of the smallest duration of time we can measure. static uint64_t sResolution; @@ -171,16 +168,16 @@ BaseTimeDurationPlatformUtils::ResolutionInTicks() static bool gInitialized = false; -nsresult +void TimeStamp::Startup() { if (gInitialized) { - return NS_OK; + return; } struct timespec dummy; if (clock_gettime(CLOCK_MONOTONIC, &dummy) != 0) { - NS_RUNTIMEABORT("CLOCK_MONOTONIC is absent!"); + MOZ_CRASH("CLOCK_MONOTONIC is absent!"); } sResolution = ClockResolutionNs(); @@ -194,7 +191,7 @@ TimeStamp::Startup() gInitialized = true; - return NS_OK; + return; } void @@ -259,7 +256,7 @@ JiffiesSinceBoot(const char* aFile) // process uptime. This value will be stored at the address pointed by aTime; // if an error occurred 0 will be stored instead. -static void +static void* ComputeProcessUptimeThread(void* aTime) { uint64_t* uptime = static_cast(aTime); @@ -268,7 +265,7 @@ ComputeProcessUptimeThread(void* aTime) *uptime = 0; if (!hz) { - return; + return nullptr; } char threadStat[40]; @@ -278,10 +275,11 @@ ComputeProcessUptimeThread(void* aTime) uint64_t selfJiffies = JiffiesSinceBoot("/proc/self/stat"); if (!threadJiffies || !selfJiffies) { - return; + return nullptr; } *uptime = ((threadJiffies - selfJiffies) * kNsPerSec) / hz; + return nullptr; } // Computes and returns the process uptime in us on Linux & its derivatives. @@ -291,15 +289,14 @@ uint64_t TimeStamp::ComputeProcessUptime() { uint64_t uptime = 0; - PRThread* thread = PR_CreateThread(PR_USER_THREAD, - ComputeProcessUptimeThread, - &uptime, - PR_PRIORITY_NORMAL, - PR_GLOBAL_THREAD, - PR_JOINABLE_THREAD, - 0); + pthread_t uptime_pthread; - PR_JoinThread(thread); + if (pthread_create(&uptime_pthread, nullptr, ComputeProcessUptimeThread, &uptime)) { + MOZ_CRASH("Failed to create process uptime thread."); + return 0; + } + + pthread_join(uptime_pthread, NULL); return uptime / kNsPerUs; } diff --git a/xpcom/ds/TimeStamp_windows.cpp b/mozglue/misc/TimeStamp_windows.cpp similarity index 95% rename from xpcom/ds/TimeStamp_windows.cpp rename to mozglue/misc/TimeStamp_windows.cpp index 15e3c2b00f..b79a677bfa 100644 --- a/xpcom/ds/TimeStamp_windows.cpp +++ b/mozglue/misc/TimeStamp_windows.cpp @@ -8,37 +8,31 @@ // values of GetTickCount(). #include "mozilla/MathAlgorithms.h" -#include "mozilla/Mutex.h" #include "mozilla/TimeStamp.h" -#include "nsWindowsHelpers.h" -#include -#include "nsCRT.h" -#include "mozilla/Logging.h" -#include "prprf.h" #include #include +#include -// Log module for mozilla::TimeStamp for Windows logging... -// -// To enable logging (see prlog.h for full details): -// -// set NSPR_LOG_MODULES=TimeStampWindows:5 -// set NSPR_LOG_FILE=nspr.log -// -// this enables LogLevel::Debug level information and places all output in -// the file nspr.log -static PRLogModuleInfo* -GetTimeStampLog() +// To enable logging define to your favorite logging API +#define LOG(x) + +class AutoCriticalSection { - static PRLogModuleInfo* sLog; - if (!sLog) { - sLog = PR_NewLogModule("TimeStampWindows"); +public: + AutoCriticalSection(LPCRITICAL_SECTION aSection) + : mSection(aSection) + { + ::EnterCriticalSection(mSection); } - return sLog; -} -#define LOG(x) MOZ_LOG(GetTimeStampLog(), mozilla::LogLevel::Debug, x) + ~AutoCriticalSection() + { + ::LeaveCriticalSection(mSection); + } +private: + LPCRITICAL_SECTION mSection; +}; // Estimate of the smallest duration of time we can measure. static volatile ULONGLONG sResolution; @@ -293,7 +287,7 @@ InitResolution() // ---------------------------------------------------------------------------- // TimeStampValue implementation // ---------------------------------------------------------------------------- - +MFBT_API TimeStampValue::TimeStampValue(ULONGLONG aGTC, ULONGLONG aQPC, bool aHasQPC) : mGTC(aGTC) , mQPC(aQPC) @@ -302,7 +296,7 @@ TimeStampValue::TimeStampValue(ULONGLONG aGTC, ULONGLONG aQPC, bool aHasQPC) { } -TimeStampValue& +MFBT_API TimeStampValue& TimeStampValue::operator+=(const int64_t aOther) { mGTC += aOther; @@ -310,7 +304,7 @@ TimeStampValue::operator+=(const int64_t aOther) return *this; } -TimeStampValue& +MFBT_API TimeStampValue& TimeStampValue::operator-=(const int64_t aOther) { mGTC -= aOther; @@ -320,7 +314,7 @@ TimeStampValue::operator-=(const int64_t aOther) // If the duration is less then two seconds, perform check of QPC stability // by comparing both GTC and QPC calculated durations of this and aOther. -uint64_t +MFBT_API uint64_t TimeStampValue::CheckQPC(const TimeStampValue& aOther) const { uint64_t deltaGTC = mGTC - aOther.mGTC; @@ -394,7 +388,7 @@ TimeStampValue::CheckQPC(const TimeStampValue& aOther) const return deltaGTC; } -uint64_t +MFBT_API uint64_t TimeStampValue::operator-(const TimeStampValue& aOther) const { if (mIsNull && aOther.mIsNull) { @@ -408,14 +402,14 @@ TimeStampValue::operator-(const TimeStampValue& aOther) const // TimeDuration and TimeStamp implementation // ---------------------------------------------------------------------------- -double +MFBT_API double BaseTimeDurationPlatformUtils::ToSeconds(int64_t aTicks) { // Converting before arithmetic avoids blocked store forward return double(aTicks) / (double(sFrequencyPerSec) * 1000.0); } -double +MFBT_API double BaseTimeDurationPlatformUtils::ToSecondsSigDigits(int64_t aTicks) { // don't report a value < mResolution ... @@ -427,7 +421,7 @@ BaseTimeDurationPlatformUtils::ToSecondsSigDigits(int64_t aTicks) return double(valueSigDigs) / kNsPerSecd; } -int64_t +MFBT_API int64_t BaseTimeDurationPlatformUtils::TicksFromMilliseconds(double aMilliseconds) { double result = ms2mt(aMilliseconds); @@ -440,7 +434,7 @@ BaseTimeDurationPlatformUtils::TicksFromMilliseconds(double aMilliseconds) return result; } -int64_t +MFBT_API int64_t BaseTimeDurationPlatformUtils::ResolutionInTicks() { return static_cast(sResolution); @@ -482,7 +476,7 @@ HasStableTSC() return regs[3] & (1 << 8); } -nsresult +MFBT_API void TimeStamp::Startup() { // Decide which implementation to use for the high-performance timer. @@ -508,7 +502,7 @@ TimeStamp::Startup() InitResolution(); LOG(("TimeStamp: using GetTickCount")); - return NS_OK; + return; } sFrequencyPerSec = freq.QuadPart; @@ -517,16 +511,16 @@ TimeStamp::Startup() InitThresholds(); InitResolution(); - return NS_OK; + return; } -void +MFBT_API void TimeStamp::Shutdown() { DeleteCriticalSection(&sTimeStampLock); } -TimeStamp +MFBT_API TimeStamp TimeStamp::Now(bool aHighResolution) { // sUseQPC is volatile @@ -541,7 +535,7 @@ TimeStamp::Now(bool aHighResolution) // Computes and returns the process uptime in microseconds. // Returns 0 if an error was encountered. -uint64_t +MFBT_API uint64_t TimeStamp::ComputeProcessUptime() { SYSTEMTIME nowSys; diff --git a/xpcom/ds/TimeStamp_windows.h b/mozglue/misc/TimeStamp_windows.h similarity index 83% rename from xpcom/ds/TimeStamp_windows.h rename to mozglue/misc/TimeStamp_windows.h index c746db6ac9..28ab59f934 100644 --- a/xpcom/ds/TimeStamp_windows.h +++ b/mozglue/misc/TimeStamp_windows.h @@ -7,6 +7,8 @@ #ifndef mozilla_TimeStamp_windows_h #define mozilla_TimeStamp_windows_h +#include "mozilla/Types.h" + namespace mozilla { class TimeStamp; @@ -23,9 +25,9 @@ class TimeStampValue bool mHasQPC; bool mIsNull; - TimeStampValue(uint64_t aGTC, uint64_t aQPC, bool aHasQPC); + MFBT_API TimeStampValue(uint64_t aGTC, uint64_t aQPC, bool aHasQPC); - uint64_t CheckQPC(const TimeStampValue& aOther) const; + MFBT_API uint64_t CheckQPC(const TimeStampValue& aOther) const; struct _SomethingVeryRandomHere; MOZ_CONSTEXPR TimeStampValue(_SomethingVeryRandomHere* aNullValue) @@ -37,7 +39,7 @@ class TimeStampValue } public: - uint64_t operator-(const TimeStampValue& aOther) const; + MFBT_API uint64_t operator-(const TimeStampValue& aOther) const; TimeStampValue operator+(const int64_t aOther) const { @@ -47,8 +49,8 @@ public: { return TimeStampValue(mGTC - aOther, mQPC - aOther, mHasQPC); } - TimeStampValue& operator+=(const int64_t aOther); - TimeStampValue& operator-=(const int64_t aOther); + MFBT_API TimeStampValue& operator+=(const int64_t aOther); + MFBT_API TimeStampValue& operator-=(const int64_t aOther); bool operator<(const TimeStampValue& aOther) const { diff --git a/mozglue/misc/moz.build b/mozglue/misc/moz.build new file mode 100644 index 0000000000..0836fb0c5f --- /dev/null +++ b/mozglue/misc/moz.build @@ -0,0 +1,40 @@ +FINAL_LIBRARY = 'mozglue' + +EXPORTS.mozilla += [ + 'TimeStamp.h', +] + +if CONFIG['OS_ARCH'] == 'WINNT': + EXPORTS.mozilla += [ + 'TimeStamp_windows.h', + ] + +SOURCES += [ + 'TimeStamp.cpp', +] + +OS_LIBS += CONFIG['REALTIME_LIBS'] + +# Don't use STL wrappers here (i.e. wrapped ); they require mozalloc +DISABLE_STL_WRAPPING = True + +DEFINES['MOZ_NO_MOZALLOC'] = True + +DEFINES['IMPL_MFBT'] = True + +if CONFIG['OS_ARCH'] == 'WINNT': + SOURCES += [ + 'TimeStamp_windows.cpp', + ] +elif CONFIG['HAVE_CLOCK_MONOTONIC']: + SOURCES += [ + 'TimeStamp_posix.cpp', + ] +elif CONFIG['OS_ARCH'] == 'Darwin': + SOURCES += [ + 'TimeStamp_darwin.cpp', + ] +elif CONFIG['COMPILE_ENVIRONMENT']: + error('No TimeStamp implementation on this platform. Build will not succeed') + +FAIL_ON_WARNINGS = True diff --git a/mozglue/moz.build b/mozglue/moz.build index 89f6867b71..70f27f38e6 100644 --- a/mozglue/moz.build +++ b/mozglue/moz.build @@ -7,7 +7,10 @@ if CONFIG['MOZ_LINKER']: DIRS += ['linker'] -DIRS += ['build'] +DIRS += [ + 'build', + 'misc', +] if CONFIG['MOZ_CRT']: DIRS += ['crt'] diff --git a/toolkit/devtools/app-manager/test/browser_manifest_editor.js b/toolkit/devtools/app-manager/test/browser_manifest_editor.js index 1dfc09a36c..51d271bac1 100644 --- a/toolkit/devtools/app-manager/test/browser_manifest_editor.js +++ b/toolkit/devtools/app-manager/test/browser_manifest_editor.js @@ -48,7 +48,7 @@ function waitForUpdate() { } function changeManifestValue(key, value) { - return Task.spawn(function() { + return Task.spawn(function*() { let propElem = gManifestWindow.document .querySelector("[id ^= '" + key + "']"); is(propElem.querySelector(".name").value, key, @@ -74,7 +74,7 @@ function changeManifestValue(key, value) { } function changeManifestValueBad(key, value) { - return Task.spawn(function() { + return Task.spawn(function*() { let propElem = gManifestWindow.document .querySelector("[id ^= '" + key + "']"); is(propElem.querySelector(".name").value, key, @@ -102,7 +102,7 @@ function changeManifestValueBad(key, value) { function addNewManifestProperty(parent, key, value) { info("Adding new property - parent: " + parent + "; key: " + key + "; value: " + value + "\n\n"); - return Task.spawn(function() { + return Task.spawn(function*() { let parentElem = gManifestWindow.document .querySelector("[id ^= '" + parent + "']"); ok(parentElem, "Found parent element: " + parentElem.id); @@ -143,7 +143,7 @@ function addNewManifestProperty(parent, key, value) { } function addNewManifestPropertyBad(parent, key, value) { - return Task.spawn(function() { + return Task.spawn(function*() { let parentElem = gManifestWindow.document .querySelector("[id ^= '" + parent + "']"); ok(parentElem, @@ -176,7 +176,7 @@ function addNewManifestPropertyBad(parent, key, value) { function removeManifestProperty(parent, key) { info("*** Remove property test ***"); - return Task.spawn(function() { + return Task.spawn(function*() { let parentElem = gManifestWindow.document .querySelector("[id ^= '" + parent + "']"); ok(parentElem, "Found parent element"); diff --git a/toolkit/devtools/app-manager/test/head.js b/toolkit/devtools/app-manager/test/head.js index a8cb422141..1d557c9b0a 100644 --- a/toolkit/devtools/app-manager/test/head.js +++ b/toolkit/devtools/app-manager/test/head.js @@ -127,7 +127,7 @@ function waitForProjectsPanel(deferred = promise.defer()) { } function selectProjectsPanel() { - return Task.spawn(function() { + return Task.spawn(function*() { let projectsButton = content.document.querySelector(".projects-button"); EventUtils.sendMouseEvent({ type: "click" }, projectsButton, content); @@ -144,7 +144,7 @@ function waitForProjectSelection() { } function selectFirstProject() { - return Task.spawn(function() { + return Task.spawn(function*() { let projectsFrame = content.document.querySelector(".projects-panel"); let projectsWindow = projectsFrame.contentWindow; let projectsDoc = projectsWindow.document; @@ -156,7 +156,7 @@ function selectFirstProject() { } function showSampleProjectDetails() { - return Task.spawn(function() { + return Task.spawn(function*() { yield selectProjectsPanel(); yield selectFirstProject(); }); diff --git a/toolkit/devtools/commandline/test/browser_cmd_screenshot.js b/toolkit/devtools/commandline/test/browser_cmd_screenshot.js index bf0726c946..a1be7883e6 100644 --- a/toolkit/devtools/commandline/test/browser_cmd_screenshot.js +++ b/toolkit/devtools/commandline/test/browser_cmd_screenshot.js @@ -25,7 +25,7 @@ function* spawnTest() { pbWin.close(); } -function addTabWithToolbarRunTests(win) { +function* addTabWithToolbarRunTests(win) { let options = yield helpers.openTab(TEST_URI, { chromeWindow: win }); yield helpers.openToolbar(options); diff --git a/toolkit/devtools/netmonitor/netmonitor-controller.js b/toolkit/devtools/netmonitor/netmonitor-controller.js index 6a9371b4b2..ba2a5d55bf 100644 --- a/toolkit/devtools/netmonitor/netmonitor-controller.js +++ b/toolkit/devtools/netmonitor/netmonitor-controller.js @@ -368,7 +368,9 @@ function TargetEventsHandler() { } TargetEventsHandler.prototype = { - get target() NetMonitorController._target, + get target() { + return NetMonitorController._target; + }, /** * Listen for events emitted by the current tab target. @@ -448,8 +450,13 @@ function NetworkEventsHandler() { } NetworkEventsHandler.prototype = { - get client() NetMonitorController._target.client, - get webConsoleClient() NetMonitorController.webConsoleClient, + get client() { + return NetMonitorController._target.client; + }, + + get webConsoleClient() { + return NetMonitorController.webConsoleClient; + }, /** * Connect to the current target client. @@ -763,7 +770,9 @@ NetMonitorController.NetworkEventsHandler = new NetworkEventsHandler(); */ Object.defineProperties(window, { "gNetwork": { - get: function() NetMonitorController.NetworkEventsHandler, + get: function() { + return NetMonitorController.NetworkEventsHandler; + }, configurable: true } }); diff --git a/toolkit/devtools/netmonitor/netmonitor-view.js b/toolkit/devtools/netmonitor/netmonitor-view.js index 852da24605..d0d69c848f 100644 --- a/toolkit/devtools/netmonitor/netmonitor-view.js +++ b/toolkit/devtools/netmonitor/netmonitor-view.js @@ -954,19 +954,21 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, { /** * Returns an object with all the filter predicates as [key: function] pairs. */ - get _allFilterPredicates() ({ - all: () => true, - html: this.isHtml, - css: this.isCss, - js: this.isJs, - xhr: this.isXHR, - fonts: this.isFont, - images: this.isImage, - media: this.isMedia, - flash: this.isFlash, - other: this.isOther, - freetext: this.isFreetextMatch - }), + get _allFilterPredicates() { + return { + all: () => true, + html: this.isHtml, + css: this.isCss, + js: this.isJs, + xhr: this.isXHR, + fonts: this.isFont, + images: this.isImage, + media: this.isMedia, + flash: this.isFlash, + other: this.isOther, + freetext: this.isFreetextMatch + }; + }, /** * Sorts all network requests in this container by a specified detail. @@ -1080,52 +1082,72 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, { * @return boolean * True if the item should be visible, false otherwise. */ - isHtml: function({ attachment: { mimeType } }) - mimeType && mimeType.includes("/html"), + isHtml: function({ attachment: { mimeType } }) { + return mimeType && mimeType.includes("/html"); + }, - isCss: function({ attachment: { mimeType } }) - mimeType && mimeType.includes("/css"), + isCss: function({ attachment: { mimeType } }) { + return mimeType && mimeType.includes("/css"); + }, - isJs: function({ attachment: { mimeType } }) - mimeType && ( + isJs: function({ attachment: { mimeType } }) { + return mimeType && ( mimeType.includes("/ecmascript") || mimeType.includes("/javascript") || - mimeType.includes("/x-javascript")), + mimeType.includes("/x-javascript")); + }, - isXHR: function({ attachment: { isXHR } }) - isXHR, + isXHR: function({ attachment: { isXHR } }) { + return isXHR; + }, - isFont: function({ attachment: { url, mimeType } }) // Fonts are a mess. - (mimeType && ( - mimeType.includes("font/") || - mimeType.includes("/font"))) || - url.includes(".eot") || - url.includes(".ttf") || - url.includes(".otf") || - url.includes(".woff"), + isFont: function({ attachment: { url, mimeType } }) { + // Fonts are a mess. + return (mimeType && ( + mimeType.includes("font/") || + mimeType.includes("/font"))) || + url.includes(".eot") || + url.includes(".ttf") || + url.includes(".otf") || + url.includes(".woff"); + }, - isImage: function({ attachment: { mimeType } }) - mimeType && mimeType.includes("image/"), + isImage: function({ attachment: { mimeType } }) { + return mimeType && mimeType.includes("image/"); + }, - isMedia: function({ attachment: { mimeType } }) // Not including images. - mimeType && ( + isMedia: function({ attachment: { mimeType } }) { + // Not including images. + return mimeType && ( mimeType.includes("audio/") || mimeType.includes("video/") || - mimeType.includes("model/")), + mimeType.includes("model/")); + }, - isFlash: function({ attachment: { url, mimeType } }) // Flash is a mess. - (mimeType && ( - mimeType.includes("/x-flv") || - mimeType.includes("/x-shockwave-flash"))) || - url.includes(".swf") || - url.includes(".flv"), + isFlash: function({ attachment: { url, mimeType } }) { + // Flash is a mess. + return (mimeType && ( + mimeType.includes("/x-flv") || + mimeType.includes("/x-shockwave-flash"))) || + url.includes(".swf") || + url.includes(".flv"); + }, - isOther: function(e) - !this.isHtml(e) && !this.isCss(e) && !this.isJs(e) && !this.isXHR(e) && - !this.isFont(e) && !this.isImage(e) && !this.isMedia(e) && !this.isFlash(e), + isOther: function(e) { + return !this.isHtml(e) && + !this.isCss(e) && + !this.isJs(e) && + !this.isXHR(e) && + !this.isFont(e) && + !this.isImage(e) && + !this.isMedia(e) && + !this.isFlash(e); + }, - isFreetextMatch: function({ attachment: { url } }, text) //no text is a positive match - !text || url.includes(text), + isFreetextMatch: function({ attachment: { url } }, text) { + //no text is a positive match + return !text || url.includes(text); + }, /** * Predicates used when sorting items. @@ -1139,18 +1161,21 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, { * 0 to leave aFirst and aSecond unchanged with respect to each other * 1 to sort aSecond to a lower index than aFirst */ - _byTiming: function({ attachment: first }, { attachment: second }) - first.startedMillis > second.startedMillis, + _byTiming: function({ attachment: first }, { attachment: second }) { + return first.startedMillis > second.startedMillis; + }, - _byStatus: function({ attachment: first }, { attachment: second }) - first.status == second.status - ? first.startedMillis > second.startedMillis - : first.status > second.status, + _byStatus: function({ attachment: first }, { attachment: second }) { + return first.status == second.status + ? first.startedMillis > second.startedMillis + : first.status > second.status; + }, - _byMethod: function({ attachment: first }, { attachment: second }) - first.method == second.method - ? first.startedMillis > second.startedMillis - : first.method > second.method, + _byMethod: function({ attachment: first }, { attachment: second }) { + return first.method == second.method + ? first.startedMillis > second.startedMillis + : first.method > second.method; + }, _byFile: function({ attachment: first }, { attachment: second }) { let firstUrl = this._getUriNameWithQuery(first.url).toLowerCase(); @@ -3300,8 +3325,8 @@ PerformanceStatisticsView.prototype = { /** * DOM query helper. */ -function $(aSelector, aTarget = document) aTarget.querySelector(aSelector); -function $all(aSelector, aTarget = document) aTarget.querySelectorAll(aSelector); +let $ = (aSelector, aTarget = document) => aTarget.querySelector(aSelector); +let $all = (aSelector, aTarget = document) => aTarget.querySelectorAll(aSelector); /** * Helper for getting an nsIURL instance out of a string. @@ -3396,7 +3421,7 @@ function parseRequestText(aText, aName, aDivider) { * List of headers in text format */ function writeHeaderText(aHeaders) { - return [(name + ": " + value) for ({name, value} of aHeaders)].join("\n"); + return aHeaders.map(({name, value}) => name + ": " + value).join("\n"); } /** @@ -3408,7 +3433,7 @@ function writeHeaderText(aHeaders) { * List of query params in text format */ function writeQueryText(aParams) { - return [(name + "=" + value) for ({name, value} of aParams)].join("\n"); + return aParams.map(({name, value}) => name + "=" + value).join("\n"); } /** @@ -3420,7 +3445,7 @@ function writeQueryText(aParams) { * Query string that can be appended to a url. */ function writeQueryString(aParams) { - return [(name + "=" + value) for ({name, value} of aParams)].join("&"); + return aParams.map(({name, value}) => name + "=" + value).join("&"); } /** diff --git a/toolkit/devtools/netmonitor/panel.js b/toolkit/devtools/netmonitor/panel.js index ff513e9d05..d6775598b4 100644 --- a/toolkit/devtools/netmonitor/panel.js +++ b/toolkit/devtools/netmonitor/panel.js @@ -56,7 +56,9 @@ NetMonitorPanel.prototype = { // DevToolPanel API - get target() this._toolbox.target, + get target() { + return this._toolbox.target; + }, destroy: function() { // Make sure this panel is not already destroyed. diff --git a/toolkit/devtools/netmonitor/test/browser_net_complex-params.js b/toolkit/devtools/netmonitor/test/browser_net_complex-params.js index d155a039f2..f728878e8d 100644 --- a/toolkit/devtools/netmonitor/test/browser_net_complex-params.js +++ b/toolkit/devtools/netmonitor/test/browser_net_complex-params.js @@ -17,7 +17,7 @@ function test() { NetworkDetails._params.lazyEmpty = false; Task.spawn(function*() { - yield waitForNetworkEvents(aMonitor, 0, 6); + yield waitForNetworkEvents(aMonitor, 1, 6); EventUtils.sendMouseEvent({ type: "mousedown" }, document.getElementById("details-pane-toggle")); @@ -47,6 +47,10 @@ function test() { yield waitFor(aMonitor.panelWin, EVENTS.REQUEST_POST_PARAMS_DISPLAYED); yield testParamsTab2('a', '"b"', '?foo=bar', "text"); + RequestsMenu.selectedIndex = 6; + yield waitFor(aMonitor.panelWin, EVENTS.SIDEBAR_POPULATED); + yield testParamsTab3('a', '"b"'); + yield teardown(aMonitor); finish(); }); @@ -141,6 +145,25 @@ function test() { }); } + function testParamsTab3(aQueryStringParamName, aQueryStringParamValue) { + let tab = document.querySelectorAll("#details-pane tab")[2]; + let tabpanel = document.querySelectorAll("#details-pane tabpanel")[2]; + + is(tabpanel.querySelectorAll(".variables-view-scope").length, 0, + "The number of param scopes displayed in this tabpanel is incorrect."); + is(tabpanel.querySelectorAll(".variable-or-property").length, 0, + "The number of param values displayed in this tabpanel is incorrect."); + is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 1, + "The empty notice should be displayed in this tabpanel."); + + is(tabpanel.querySelector("#request-params-box") + .hasAttribute("hidden"), false, + "The request params box should not be hidden."); + is(tabpanel.querySelector("#request-post-data-textarea-box") + .hasAttribute("hidden"), true, + "The request post data textarea box should be hidden."); + } + aDebuggee.performRequests(); }); } diff --git a/toolkit/devtools/netmonitor/test/browser_net_simple-request-details.js b/toolkit/devtools/netmonitor/test/browser_net_simple-request-details.js index 48fbb0b50e..fa1cddc83e 100644 --- a/toolkit/devtools/netmonitor/test/browser_net_simple-request-details.js +++ b/toolkit/devtools/netmonitor/test/browser_net_simple-request-details.js @@ -14,7 +14,7 @@ function test() { let TAB_UPDATED = aMonitor.panelWin.EVENTS.TAB_UPDATED; RequestsMenu.lazyUpdate = false; - Task.spawn(function () { + Task.spawn(function*() { yield waitForNetworkEvents(aMonitor, 1); is(RequestsMenu.selectedItem, null, "There shouldn't be any selected item in the requests menu."); @@ -174,7 +174,7 @@ function test() { EventUtils.sendMouseEvent({ type: "mousedown" }, document.querySelectorAll("#details-pane tab")[3]); - return Task.spawn(function () { + return Task.spawn(function*() { yield waitFor(aMonitor.panelWin, TAB_UPDATED); let tab = document.querySelectorAll("#details-pane tab")[3]; diff --git a/toolkit/devtools/netmonitor/test/head.js b/toolkit/devtools/netmonitor/test/head.js index 42db6baa5d..146eba3e9c 100644 --- a/toolkit/devtools/netmonitor/test/head.js +++ b/toolkit/devtools/netmonitor/test/head.js @@ -404,7 +404,7 @@ function testFilterButtons(aMonitor, aFilterType) { let buttons = doc.querySelectorAll(".requests-menu-footer-button"); // Only target should be checked. - let checkStatus = [(button == target) ? 1 : 0 for (button of buttons)] + let checkStatus = [...buttons].map(button => button == target ? 1 : 0); testFilterButtonsCustom(aMonitor, checkStatus); } diff --git a/toolkit/devtools/netmonitor/test/html_params-test-page.html b/toolkit/devtools/netmonitor/test/html_params-test-page.html index de1394b8c7..3f30e3d761 100644 --- a/toolkit/devtools/netmonitor/test/html_params-test-page.html +++ b/toolkit/devtools/netmonitor/test/html_params-test-page.html @@ -15,6 +15,12 @@

Request params type test