mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 05:37:11 +00:00
import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1150717 - Test request with no params in the Network Monitor. r=brings (a60e9e8d9) - Bug 1168077 - Remove remaining spidermonkey js specific syntax from browser/devtools; r=miker (c98f20c30) - Bug 1168125 - Fix existing tests, r=jsantell (b1dfa101e) - Bug 1169439 - Pull out marker definitions into its own file, and move formatter and collapse functions into marker-utils. r=vp (17eb24ab3) - Bug 1173654 - Part 1: Add logging methods for SurfaceType and ImageFormat. r=Bas (22f2fa019) - Bug 1169125 - Part 1: Allow sending any DataSourceSurface-backed image over WebRTC and fix failure cases. r=bwc (1fb0def92) - Bug 1169125 - Part 2: Use UniquePtr for scoped delete of yuv data in MediaPipeline. r=bwc (cdb79e201) - Bug 1173654 - Part 2: Use namespaces in MediaPipeline.cpp. r=bwc (311696260) - Bug 1173654 - Part 3: Attempt to GetDataSurface() and convert if sending pure I420 fails. r=bwc, r=jesup (58520b820) - Bug 1173654 - Part 4: Add detailed logging and asserts to MediaPipeline::ProcessVideoChunk. r=bwc (ba08ae5bc) - Bug 1155089 - Part 1: Reset |TrackID| for MediaPipelineTransmit::PipelineListener on replaceTrack(). r=bwc (304fb8703) - adapted Bug 1142688 - Wait for actual audio data on remote side before checking audio sanity. r=jesup,padenot (479f6356c) - Bug 858927 - Move the mozilla::TimeStamp into mozglue. r=glandium (751938e09) - Bug 1166559 - Add documentation for ProfileTimelineMarkers from a dev tools perspective. r=fitzgen (ed1563dfb) - Bug 1141614 - Part 4: Expose cycle collection markers in the devtools frontend; r=jsantell (2eb830de7)
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "LayersLogging.h"
|
||||
#include <stdint.h> // 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;
|
||||
|
||||
@@ -24,6 +24,8 @@ class Matrix4x4;
|
||||
template <class units> 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 <typename T>
|
||||
std::string
|
||||
|
||||
@@ -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 <time.h>],
|
||||
[ 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 ========================================================
|
||||
|
||||
@@ -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<PipelineListener> 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<android::GraphicBuffer> 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<layers::PlanarYCbCrImage *>(
|
||||
static_cast<const layers::PlanarYCbCrImage *>(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<PlanarYCbCrImage *>(
|
||||
static_cast<const PlanarYCbCrImage *>(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<layers::CairoImage *>(
|
||||
static_cast<const layers::CairoImage *>(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<gfx::SourceSurface> tempSurf = rgb->GetAsSourceSurface();
|
||||
RefPtr<gfx::DataSourceSurface> surf = tempSurf->GetDataSurface();
|
||||
|
||||
switch (surf->GetFormat()) {
|
||||
case gfx::SurfaceFormat::B8G8R8A8:
|
||||
case gfx::SurfaceFormat::B8G8R8X8:
|
||||
libyuv::ARGBToI420(static_cast<uint8*>(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<uint8*>(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<SourceSurface> surf = img->GetAsSourceSurface();
|
||||
if (!surf) {
|
||||
MOZ_MTLOG(ML_ERROR, "Getting surface from " << Stringify(format) << " image failed");
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<DataSourceSurface> 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<uint8[]> 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<uint8*>(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<uint8*>(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<layers::Image>& video_image) {
|
||||
const RefPtr<Image>& 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<layers::Image> image = image_container_->CreateImage(format);
|
||||
layers::PlanarYCbCrImage* yuvImage = static_cast<layers::PlanarYCbCrImage*>(image.get());
|
||||
nsRefPtr<Image> image = image_container_->CreateImage(format);
|
||||
PlanarYCbCrImage* yuvImage = static_cast<PlanarYCbCrImage*>(image.get());
|
||||
uint8_t* frame = const_cast<uint8_t*>(static_cast<const uint8_t*> (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<SimpleImageBuffer> image = image_;
|
||||
#elif defined(MOZILLA_INTERNAL_API)
|
||||
nsRefPtr<layers::Image> image = image_;
|
||||
nsRefPtr<Image> image = image_;
|
||||
// our constructor sets track_rate_ to the graph rate
|
||||
MOZ_ASSERT(track_rate_ == source_->GraphRate());
|
||||
#endif
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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() {}
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
*/
|
||||
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "prenv.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
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
|
||||
@@ -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<typename T> 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<mozilla::TimeStamp>;
|
||||
@@ -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
|
||||
@@ -23,7 +23,6 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#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<int64_t>(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
|
||||
@@ -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 <pthread.h>
|
||||
|
||||
// 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<uint64_t*>(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;
|
||||
}
|
||||
@@ -8,37 +8,31 @@
|
||||
// values of GetTickCount().
|
||||
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "nsWindowsHelpers.h"
|
||||
#include <windows.h>
|
||||
|
||||
#include "nsCRT.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "prprf.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include <intrin.h>
|
||||
#include <windows.h>
|
||||
|
||||
// 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<int64_t>(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;
|
||||
@@ -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
|
||||
{
|
||||
@@ -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 <new>); 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
|
||||
+4
-1
@@ -7,7 +7,10 @@
|
||||
if CONFIG['MOZ_LINKER']:
|
||||
DIRS += ['linker']
|
||||
|
||||
DIRS += ['build']
|
||||
DIRS += [
|
||||
'build',
|
||||
'misc',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_CRT']:
|
||||
DIRS += ['crt']
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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("&");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,12 @@
|
||||
<p>Request params type test</p>
|
||||
|
||||
<script type="text/javascript">
|
||||
function get(aAddress, aQuery) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", aAddress + aQuery, true);
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
function post(aAddress, aQuery, aContentType, aPostBody) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", aAddress + aQuery, true);
|
||||
@@ -43,7 +49,11 @@
|
||||
setTimeout(function() {
|
||||
post("baz", "?a=b", undefined, '?foo=bar');
|
||||
|
||||
// Done.
|
||||
setTimeout(function() {
|
||||
get("baz", "");
|
||||
|
||||
// Done.
|
||||
}, 10);
|
||||
}, 10);
|
||||
}, 10);
|
||||
}, 10);
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
# Timeline Markers
|
||||
|
||||
## Common
|
||||
|
||||
* DOMHighResTimeStamp start
|
||||
* DOMHighResTimeStamp end
|
||||
* DOMString name
|
||||
* object? stack
|
||||
* object? endStack
|
||||
|
||||
## DOMEvent
|
||||
|
||||
Triggered when a DOM event occurs, like a click or a keypress.
|
||||
|
||||
* unsigned short eventPhase - a number indicating what phase this event is
|
||||
in (target, bubbling, capturing, maps to Ci.nsIDOMEvent constants)
|
||||
* DOMString type - the type of event, like "keypress" or "click"
|
||||
|
||||
## Reflow
|
||||
|
||||
Reflow markers (labeled as "Layout") indicate when a change has occurred to
|
||||
a DOM element's positioning that requires the frame tree (rendering
|
||||
representation of the DOM) to figure out the new position of a handful of
|
||||
elements. Fired via `PresShell::DoReflow`
|
||||
|
||||
## Paint
|
||||
|
||||
* sequence<{ long height, long width, long x, long y }> rectangles - An array
|
||||
of rectangle objects indicating where painting has occurred.
|
||||
|
||||
## Styles
|
||||
|
||||
Style markers (labeled as "Recalculating Styles") are triggered when Gecko
|
||||
needs to figure out the computational style of an element. Fired via
|
||||
`RestyleTracker::DoProcessRestyles` when there are elements to restyle.
|
||||
|
||||
* DOMString restyleHint - A string indicating what kind of restyling will need
|
||||
to be processed; for example "eRestyle_StyleAttribute" is relatively cheap,
|
||||
whereas "eRestyle_Subtree" is more expensive. The hint can be a string of
|
||||
any amount of the following, separated via " | ". All future restyleHints
|
||||
are from `RestyleManager::RestyleHintToString`.
|
||||
|
||||
* "eRestyle_Self"
|
||||
* "eRestyle_Subtree"
|
||||
* "eRestyle_LaterSiblings"
|
||||
* "eRestyle_CSSTransitions"
|
||||
* "eRestyle_CSSAnimations"
|
||||
* "eRestyle_SVGAttrAnimations"
|
||||
* "eRestyle_StyleAttribute"
|
||||
* "eRestyle_StyleAttribute_Animations"
|
||||
* "eRestyle_Force"
|
||||
* "eRestyle_ForceDescendants"
|
||||
|
||||
|
||||
## Javascript
|
||||
|
||||
`Javascript` markers are emitted indicating when JS execution begins and ends,
|
||||
with a reason that triggered it (causeName), like a requestAnimationFrame or
|
||||
a setTimeout.
|
||||
|
||||
* string causeName - The reason that JS was entered. There are many possible
|
||||
reasons, and the interesting ones to show web developers (triggered by content) are:
|
||||
|
||||
* "\<script\> element"
|
||||
* "EventListener.handleEvent"
|
||||
* "setInterval handler"
|
||||
* "setTimeout handler"
|
||||
* "FrameRequestCallback"
|
||||
* "EventHandlerNonNull"
|
||||
* "promise callback"
|
||||
* "promise initializer"
|
||||
* "Worker runnable"
|
||||
|
||||
There are also many more potential JS causes, some which are just internally
|
||||
used and won't emit a marker, but the below ones are only of interest to
|
||||
Gecko hackers, most likely
|
||||
|
||||
* "promise thenable"
|
||||
* "worker runnable"
|
||||
* "nsHTTPIndex set HTTPIndex property"
|
||||
* "XPCWrappedJS method call"
|
||||
* "nsHTTPIndex OnFTPControlLog"
|
||||
* "XPCWrappedJS QueryInterface"
|
||||
* "xpcshell argument processing”
|
||||
* "XPConnect sandbox evaluation "
|
||||
* "component loader report global"
|
||||
* "component loader load module"
|
||||
* "Cross-Process Object Wrapper call/construct"
|
||||
* "Cross-Process Object Wrapper ’set'"
|
||||
* "Cross-Process Object Wrapper 'get'"
|
||||
* "nsXULTemplateBuilder creation"
|
||||
* "TestShellCommand"
|
||||
* "precompiled XUL \<script\> element"
|
||||
* "XBL \<field\> initialization "
|
||||
* "NPAPI NPN_evaluate"
|
||||
* "NPAPI get"
|
||||
* "NPAPI set"
|
||||
* "NPAPI doInvoke"
|
||||
* "javascript: URI"
|
||||
* "geolocation.always_precise indexing"
|
||||
* "geolocation.app_settings enumeration"
|
||||
* "WebIDL dictionary creation"
|
||||
* "XBL \<constructor\>/\<destructor\> invocation"
|
||||
* "message manager script load"
|
||||
* "message handler script load"
|
||||
* "nsGlobalWindow report new global"
|
||||
|
||||
## GarbageCollection
|
||||
|
||||
Emitted after a full GC cycle has completed (which is after any number of
|
||||
incremental slices).
|
||||
|
||||
* DOMString causeName - The reason for a GC event to occur. A full list of
|
||||
GC reasons can be found [on MDN](https://developer.mozilla.org/en-US/docs/Tools/Debugger-API/Debugger.Memory#Debugger.Memory_Handler_Functions).
|
||||
* DOMString nonincremenetalReason - If the GC could not do an incremental
|
||||
GC (smaller, quick GC events), and we have to walk the entire heap and
|
||||
GC everything marked, then the reason listed here is why.
|
||||
|
||||
## nsCycleCollector::Collect
|
||||
|
||||
An `nsCycleCollector::Collect` marker is emitted for each incremental cycle
|
||||
collection slice and each non-incremental cycle collection.
|
||||
|
||||
# nsCycleCollector::ForgetSkippable
|
||||
|
||||
`nsCycleCollector::ForgetSkippable` is presented as "Cycle Collection", but in
|
||||
reality it is preparation/pre-optimization for cycle collection, and not the
|
||||
actual tracing of edges and collecting of cycles.
|
||||
|
||||
## ConsoleTime
|
||||
|
||||
A marker generated via `console.time()` and `console.timeEnd()`.
|
||||
|
||||
* DOMString causeName - the label passed into `console.time(label)` and
|
||||
`console.timeEnd(label)` if passed in.
|
||||
|
||||
## TimeStamp
|
||||
|
||||
A marker generated via `console.timeStamp(label)`.
|
||||
|
||||
* DOMString causeName - the label passed into `console.timeStamp(label)`
|
||||
if passed in.
|
||||
|
||||
## Parse HTML
|
||||
|
||||
## Parse XML
|
||||
@@ -3,12 +3,8 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { Cc, Ci, Cu, Cr } = require("chrome");
|
||||
const { ViewHelpers } = require("resource:///modules/devtools/ViewHelpers.jsm");
|
||||
|
||||
// String used to fill in platform data when it should be hidden.
|
||||
const GECKO_SYMBOL = "(Gecko)";
|
||||
|
||||
/**
|
||||
* Localization convenience methods.
|
||||
+ TODO: merge these into a single file: Bug 1082695.
|
||||
@@ -87,307 +83,6 @@ const CATEGORY_MAPPINGS = {
|
||||
"4096": CATEGORIES[7], // js::ProfileEntry::Category::EVENTS
|
||||
};
|
||||
|
||||
/**
|
||||
* A simple schema for mapping markers to the timeline UI. The keys correspond
|
||||
* to marker names, while the values are objects with the following format:
|
||||
*
|
||||
* - group: The row index in the timeline overview graph; multiple markers
|
||||
* can be added on the same row. @see <overview.js/buildGraphImage>
|
||||
* - label: The label used in the waterfall to identify the marker. Can be a
|
||||
* string or just a function that accepts the marker and returns a
|
||||
* string, if you want to use a dynamic property for the main label.
|
||||
* If you use a function for a label, it *must* handle the case where
|
||||
* no marker is provided for a main label to describe all markers of
|
||||
* this type.
|
||||
* - colorName: The label of the DevTools color used for this marker. If
|
||||
* adding a new color, be sure to check that there's an entry
|
||||
* for `.marker-details-bullet.{COLORNAME}` for the equivilent
|
||||
* entry in ./browser/themes/shared/devtools/performance.inc.css
|
||||
* https://developer.mozilla.org/en-US/docs/Tools/DevToolsColors
|
||||
* - collapseFunc: A function determining how markers are collapsed together.
|
||||
* Invoked with 3 arguments: the current parent marker, the
|
||||
* current marker and a method for peeking i markers ahead. If
|
||||
* nothing is returned, the marker is added as a standalone entry
|
||||
* in the waterfall. Otherwise, an object needs to be returned
|
||||
* with the following properties:
|
||||
* - toParent: The parent marker name (needs to be an entry in
|
||||
* the `TIMELINE_BLUEPRINT` itself).
|
||||
* - withData: An object containing some properties to staple
|
||||
* on the parent marker.
|
||||
* - forceNew: True if a new parent marker needs to be created
|
||||
* even though there is one currently available
|
||||
* with the same name.
|
||||
* - forceEnd: True if the current parent marker is full after
|
||||
* this collapse operation and should be finalized.
|
||||
* - fields: An optional array of marker properties you wish to display in the
|
||||
* marker details view. For example, a field in the array such as
|
||||
* { property: "aCauseName", label: "Cause" } would render a string
|
||||
* like `Cause: ${marker.aCauseName}` in the marker details view.
|
||||
* Each `field` item may take the following properties:
|
||||
* - property: The property that must exist on the marker to render,
|
||||
* and the value of the property will be displayed.
|
||||
* - label: The name of the property that should be displayed.
|
||||
* - formatter: If a formatter is provided, instead of directly using
|
||||
* the `property` property on the marker, the marker is
|
||||
* passed into the formatter function to determine the
|
||||
* displayed value.
|
||||
* Can also be a function that returns an object. Each key in the object
|
||||
* will be rendered as a field, with its value rendering as the value.
|
||||
*
|
||||
* Whenever this is changed, browser_timeline_waterfall-styles.js *must* be
|
||||
* updated as well.
|
||||
*/
|
||||
const TIMELINE_BLUEPRINT = {
|
||||
/* Group 0 - Reflow and Rendering pipeline */
|
||||
"Styles": {
|
||||
group: 0,
|
||||
colorName: "graphs-purple",
|
||||
collapseFunc: collapseConsecutiveIdentical,
|
||||
label: L10N.getStr("timeline.label.styles2"),
|
||||
fields: getStylesFields,
|
||||
},
|
||||
"Reflow": {
|
||||
group: 0,
|
||||
colorName: "graphs-purple",
|
||||
collapseFunc: collapseConsecutiveIdentical,
|
||||
label: L10N.getStr("timeline.label.reflow2"),
|
||||
},
|
||||
"Paint": {
|
||||
group: 0,
|
||||
colorName: "graphs-green",
|
||||
collapseFunc: collapseConsecutiveIdentical,
|
||||
label: L10N.getStr("timeline.label.paint"),
|
||||
},
|
||||
|
||||
/* Group 1 - JS */
|
||||
"DOMEvent": {
|
||||
group: 1,
|
||||
colorName: "graphs-yellow",
|
||||
collapseFunc: collapseDOMIntoDOMJS,
|
||||
label: L10N.getStr("timeline.label.domevent"),
|
||||
fields: getDOMEventFields,
|
||||
},
|
||||
"Javascript": {
|
||||
group: 1,
|
||||
colorName: "graphs-yellow",
|
||||
collapseFunc: either(collapseJSIntoDOMJS, collapseConsecutiveIdentical),
|
||||
label: getJSLabel,
|
||||
fields: getJSFields,
|
||||
},
|
||||
"meta::DOMEvent+JS": {
|
||||
colorName: "graphs-yellow",
|
||||
label: getDOMJSLabel,
|
||||
fields: getDOMEventFields,
|
||||
},
|
||||
"Parse HTML": {
|
||||
group: 1,
|
||||
colorName: "graphs-yellow",
|
||||
collapseFunc: collapseConsecutiveIdentical,
|
||||
label: L10N.getStr("timeline.label.parseHTML"),
|
||||
},
|
||||
"Parse XML": {
|
||||
group: 1,
|
||||
colorName: "graphs-yellow",
|
||||
collapseFunc: collapseConsecutiveIdentical,
|
||||
label: L10N.getStr("timeline.label.parseXML"),
|
||||
},
|
||||
"GarbageCollection": {
|
||||
group: 1,
|
||||
colorName: "graphs-red",
|
||||
collapseFunc: collapseAdjacentGC,
|
||||
label: getGCLabel,
|
||||
fields: [
|
||||
{ property: "causeName", label: "Reason:" },
|
||||
{ property: "nonincrementalReason", label: "Non-incremental Reason:" }
|
||||
],
|
||||
},
|
||||
|
||||
/* Group 2 - User Controlled */
|
||||
"ConsoleTime": {
|
||||
group: 2,
|
||||
colorName: "graphs-grey",
|
||||
label: sublabelForProperty(L10N.getStr("timeline.label.consoleTime"), "causeName"),
|
||||
fields: [{
|
||||
property: "causeName",
|
||||
label: L10N.getStr("timeline.markerDetail.consoleTimerName")
|
||||
}],
|
||||
},
|
||||
"TimeStamp": {
|
||||
group: 2,
|
||||
colorName: "graphs-blue",
|
||||
label: sublabelForProperty(L10N.getStr("timeline.label.timestamp"), "causeName"),
|
||||
fields: [{
|
||||
property: "causeName",
|
||||
label: "Label:"
|
||||
}],
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper for creating a function that returns the first defined result from
|
||||
* a list of functions passed in as params, in order.
|
||||
* @param ...function fun
|
||||
* @return any
|
||||
*/
|
||||
function either(...fun) {
|
||||
return function() {
|
||||
for (let f of fun) {
|
||||
let result = f.apply(null, arguments);
|
||||
if (result !== undefined) return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A series of collapsers used by the blueprint. These functions are
|
||||
* consecutively invoked on a moving window of two markers.
|
||||
*/
|
||||
|
||||
function collapseConsecutiveIdentical(parent, curr, peek) {
|
||||
// If there is a parent marker currently being filled and the current marker
|
||||
// should go into the parent marker, make it so.
|
||||
if (parent && parent.name == curr.name) {
|
||||
return { toParent: parent.name };
|
||||
}
|
||||
// Otherwise if the current marker is the same type as the next marker type,
|
||||
// create a new parent marker containing the current marker.
|
||||
let next = peek(1);
|
||||
if (next && curr.name == next.name) {
|
||||
return { toParent: curr.name };
|
||||
}
|
||||
}
|
||||
|
||||
function collapseAdjacentGC(parent, curr, peek) {
|
||||
let next = peek(1);
|
||||
if (next && (next.start < curr.end || next.start - curr.end <= 10 /* ms */)) {
|
||||
return collapseConsecutiveIdentical(parent, curr, peek);
|
||||
}
|
||||
}
|
||||
|
||||
function collapseDOMIntoDOMJS(parent, curr, peek) {
|
||||
// If the next marker is a JavaScript marker, create a new meta parent marker
|
||||
// containing the current marker.
|
||||
let next = peek(1);
|
||||
if (next && next.name == "Javascript") {
|
||||
return {
|
||||
forceNew: true,
|
||||
toParent: "meta::DOMEvent+JS",
|
||||
withData: {
|
||||
type: curr.type,
|
||||
eventPhase: curr.eventPhase
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function collapseJSIntoDOMJS(parent, curr, peek) {
|
||||
// If there is a parent marker currently being filled, and it's the one
|
||||
// created from a `DOMEvent` via `collapseDOMIntoDOMJS`, then the current
|
||||
// marker has to go into that one.
|
||||
if (parent && parent.name == "meta::DOMEvent+JS") {
|
||||
return {
|
||||
forceEnd: true,
|
||||
toParent: "meta::DOMEvent+JS",
|
||||
withData: {
|
||||
stack: curr.stack,
|
||||
endStack: curr.endStack
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A series of formatters used by the blueprint.
|
||||
*/
|
||||
|
||||
function getGCLabel (marker={}) {
|
||||
let label = L10N.getStr("timeline.label.garbageCollection");
|
||||
// Only if a `nonincrementalReason` exists, do we want to label
|
||||
// this as a non incremental GC event.
|
||||
if ("nonincrementalReason" in marker) {
|
||||
label = `${label} (Non-incremental)`;
|
||||
}
|
||||
return label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mapping of JS marker causes to a friendlier form. Only
|
||||
* markers that are considered "from content" should be labeled here.
|
||||
*/
|
||||
const JS_MARKER_MAP = {
|
||||
"<script> element": "Script Tag",
|
||||
"setInterval handler": "setInterval",
|
||||
"setTimeout handler": "setTimeout",
|
||||
"FrameRequestCallback": "requestAnimationFrame",
|
||||
"promise callback": "Promise Callback",
|
||||
"promise initializer": "Promise Init",
|
||||
"Worker runnable": "Worker",
|
||||
"javascript: URI": "JavaScript URI",
|
||||
// The difference between these two event handler markers are differences
|
||||
// in their WebIDL implementation, so distinguishing them is not necessary.
|
||||
"EventHandlerNonNull": "Event Handler",
|
||||
"EventListener.handleEvent": "Event Handler",
|
||||
};
|
||||
|
||||
function getJSLabel (marker={}) {
|
||||
let generic = L10N.getStr("timeline.label.javascript2");
|
||||
if ("causeName" in marker) {
|
||||
return JS_MARKER_MAP[marker.causeName] || generic;
|
||||
}
|
||||
return generic;
|
||||
}
|
||||
|
||||
function getDOMJSLabel (marker={}) {
|
||||
return `Event (${marker.type})`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hash for computing a fields object for a JS marker. If the cause
|
||||
* is considered content (so an entry exists in the JS_MARKER_MAP), do not display it
|
||||
* since it's redundant with the label. Otherwise for Gecko code, either display
|
||||
* the cause, or "(Gecko)", depending on if "show-platform-data" is set.
|
||||
*/
|
||||
function getJSFields (marker) {
|
||||
if ("causeName" in marker && !JS_MARKER_MAP[marker.causeName]) {
|
||||
return { Reason: PREFS["show-platform-data"] ? marker.causeName : GECKO_SYMBOL };
|
||||
}
|
||||
}
|
||||
|
||||
function getDOMEventFields (marker) {
|
||||
let fields = Object.create(null);
|
||||
if ("type" in marker) {
|
||||
fields[L10N.getStr("timeline.markerDetail.DOMEventType")] = marker.type;
|
||||
}
|
||||
if ("eventPhase" in marker) {
|
||||
let phase;
|
||||
if (marker.eventPhase === Ci.nsIDOMEvent.AT_TARGET) {
|
||||
phase = L10N.getStr("timeline.markerDetail.DOMEventTargetPhase");
|
||||
} else if (marker.eventPhase === Ci.nsIDOMEvent.CAPTURING_PHASE) {
|
||||
phase = L10N.getStr("timeline.markerDetail.DOMEventCapturingPhase");
|
||||
} else if (marker.eventPhase === Ci.nsIDOMEvent.BUBBLING_PHASE) {
|
||||
phase = L10N.getStr("timeline.markerDetail.DOMEventBubblingPhase");
|
||||
}
|
||||
fields[L10N.getStr("timeline.markerDetail.DOMEventPhase")] = phase;
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
|
||||
function getStylesFields (marker) {
|
||||
if ("restyleHint" in marker) {
|
||||
return { "Restyle Hint": marker.restyleHint.replace(/eRestyle_/g, "") };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a main label (like "Timestamp") and a property,
|
||||
* and returns a marker that will print out the property
|
||||
* value for a marker if it exists ("Timestamp (rendering)"),
|
||||
* or just the main label if it does not.
|
||||
*/
|
||||
function sublabelForProperty (mainLabel, prop) {
|
||||
return (marker={}) => marker[prop] ? `${mainLabel} (${marker[prop]})` : mainLabel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the numeric bitmask (or set of masks) for the given category
|
||||
* abbreviation. See CATEGORIES and CATEGORY_MAPPINGS above.
|
||||
@@ -449,7 +144,6 @@ const CATEGORY_JIT = CATEGORY_MASK('js');
|
||||
// Exported symbols.
|
||||
exports.L10N = L10N;
|
||||
exports.PREFS = PREFS;
|
||||
exports.TIMELINE_BLUEPRINT = TIMELINE_BLUEPRINT;
|
||||
exports.CATEGORIES = CATEGORIES;
|
||||
exports.CATEGORY_MAPPINGS = CATEGORY_MAPPINGS;
|
||||
exports.CATEGORY_MASK = CATEGORY_MASK;
|
||||
|
||||
@@ -8,13 +8,20 @@
|
||||
* and parsing out the blueprint to generate correct values for markers.
|
||||
*/
|
||||
|
||||
const { Ci } = require("chrome");
|
||||
|
||||
loader.lazyRequireGetter(this, "L10N",
|
||||
"devtools/performance/global", true);
|
||||
loader.lazyRequireGetter(this, "TIMELINE_BLUEPRINT",
|
||||
loader.lazyRequireGetter(this, "PREFS",
|
||||
"devtools/performance/global", true);
|
||||
loader.lazyRequireGetter(this, "TIMELINE_BLUEPRINT",
|
||||
"devtools/performance/markers", true);
|
||||
loader.lazyRequireGetter(this, "WebConsoleUtils",
|
||||
"devtools/toolkit/webconsole/utils");
|
||||
|
||||
// String used to fill in platform data when it should be hidden.
|
||||
const GECKO_SYMBOL = "(Gecko)";
|
||||
|
||||
/**
|
||||
* Returns the correct label to display for passed in marker, based
|
||||
* off of the blueprints.
|
||||
@@ -270,7 +277,159 @@ const DOM = {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A series of collapsers used by the blueprint. These functions are
|
||||
* invoked on a moving window of two markers.
|
||||
*/
|
||||
|
||||
const CollapseFunctions = {
|
||||
identical: function (parent, curr, peek) {
|
||||
// If there is a parent marker currently being filled and the current marker
|
||||
// should go into the parent marker, make it so.
|
||||
if (parent && parent.name == curr.name) {
|
||||
return { toParent: parent.name };
|
||||
}
|
||||
// Otherwise if the current marker is the same type as the next marker type,
|
||||
// create a new parent marker containing the current marker.
|
||||
let next = peek(1);
|
||||
if (next && curr.name == next.name) {
|
||||
return { toParent: curr.name };
|
||||
}
|
||||
},
|
||||
|
||||
adjacent: function (parent, curr, peek) {
|
||||
let next = peek(1);
|
||||
if (next && (next.start < curr.end || next.start - curr.end <= 10 /* ms */)) {
|
||||
return CollapseFunctions.identical(parent, curr, peek);
|
||||
}
|
||||
},
|
||||
|
||||
DOMtoDOMJS: function (parent, curr, peek) {
|
||||
// If the next marker is a JavaScript marker, create a new meta parent marker
|
||||
// containing the current marker.
|
||||
let next = peek(1);
|
||||
if (next && next.name == "Javascript") {
|
||||
return {
|
||||
forceNew: true,
|
||||
toParent: "meta::DOMEvent+JS",
|
||||
withData: {
|
||||
type: curr.type,
|
||||
eventPhase: curr.eventPhase
|
||||
},
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
JStoDOMJS: function (parent, curr, peek) {
|
||||
// If there is a parent marker currently being filled, and it's the one
|
||||
// created from a `DOMEvent` via `collapseDOMIntoDOMJS`, then the current
|
||||
// marker has to go into that one.
|
||||
if (parent && parent.name == "meta::DOMEvent+JS") {
|
||||
return {
|
||||
forceEnd: true,
|
||||
toParent: "meta::DOMEvent+JS",
|
||||
withData: {
|
||||
stack: curr.stack,
|
||||
endStack: curr.endStack
|
||||
},
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Mapping of JS marker causes to a friendlier form. Only
|
||||
* markers that are considered "from content" should be labeled here.
|
||||
*/
|
||||
const JS_MARKER_MAP = {
|
||||
"<script> element": "Script Tag",
|
||||
"setInterval handler": "setInterval",
|
||||
"setTimeout handler": "setTimeout",
|
||||
"FrameRequestCallback": "requestAnimationFrame",
|
||||
"promise callback": "Promise Callback",
|
||||
"promise initializer": "Promise Init",
|
||||
"Worker runnable": "Worker",
|
||||
"javascript: URI": "JavaScript URI",
|
||||
// The difference between these two event handler markers are differences
|
||||
// in their WebIDL implementation, so distinguishing them is not necessary.
|
||||
"EventHandlerNonNull": "Event Handler",
|
||||
"EventListener.handleEvent": "Event Handler",
|
||||
};
|
||||
|
||||
/**
|
||||
* A series of formatters used by the blueprint.
|
||||
*/
|
||||
const Formatters = {
|
||||
GCLabel: function (marker={}) {
|
||||
let label = L10N.getStr("timeline.label.garbageCollection");
|
||||
// Only if a `nonincrementalReason` exists, do we want to label
|
||||
// this as a non incremental GC event.
|
||||
if ("nonincrementalReason" in marker) {
|
||||
label = `${label} (Non-incremental)`;
|
||||
}
|
||||
return label;
|
||||
},
|
||||
|
||||
JSLabel: function (marker={}) {
|
||||
let generic = L10N.getStr("timeline.label.javascript2");
|
||||
if ("causeName" in marker) {
|
||||
return JS_MARKER_MAP[marker.causeName] || generic;
|
||||
}
|
||||
return generic;
|
||||
},
|
||||
|
||||
DOMJSLabel: function (marker={}) {
|
||||
return `Event (${marker.type})`;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a hash for computing a fields object for a JS marker. If the cause
|
||||
* is considered content (so an entry exists in the JS_MARKER_MAP), do not display it
|
||||
* since it's redundant with the label. Otherwise for Gecko code, either display
|
||||
* the cause, or "(Gecko)", depending on if "show-platform-data" is set.
|
||||
*/
|
||||
JSFields: function (marker) {
|
||||
if ("causeName" in marker && !JS_MARKER_MAP[marker.causeName]) {
|
||||
return { Reason: PREFS["show-platform-data"] ? marker.causeName : GECKO_SYMBOL };
|
||||
}
|
||||
},
|
||||
|
||||
DOMEventFields: function (marker) {
|
||||
let fields = Object.create(null);
|
||||
if ("type" in marker) {
|
||||
fields[L10N.getStr("timeline.markerDetail.DOMEventType")] = marker.type;
|
||||
}
|
||||
if ("eventPhase" in marker) {
|
||||
let phase;
|
||||
if (marker.eventPhase === Ci.nsIDOMEvent.AT_TARGET) {
|
||||
phase = L10N.getStr("timeline.markerDetail.DOMEventTargetPhase");
|
||||
} else if (marker.eventPhase === Ci.nsIDOMEvent.CAPTURING_PHASE) {
|
||||
phase = L10N.getStr("timeline.markerDetail.DOMEventCapturingPhase");
|
||||
} else if (marker.eventPhase === Ci.nsIDOMEvent.BUBBLING_PHASE) {
|
||||
phase = L10N.getStr("timeline.markerDetail.DOMEventBubblingPhase");
|
||||
}
|
||||
fields[L10N.getStr("timeline.markerDetail.DOMEventPhase")] = phase;
|
||||
}
|
||||
return fields;
|
||||
},
|
||||
|
||||
StylesFields: function (marker) {
|
||||
if ("restyleHint" in marker) {
|
||||
return { "Restyle Hint": marker.restyleHint.replace(/eRestyle_/g, "") };
|
||||
}
|
||||
},
|
||||
|
||||
CycleCollectionFields: function (marker) {
|
||||
let Type = PREFS["show-platform-data"]
|
||||
? marker.name
|
||||
: marker.name.replace(/nsCycleCollector::/g, "");
|
||||
return { Type };
|
||||
},
|
||||
};
|
||||
|
||||
exports.getMarkerLabel = getMarkerLabel;
|
||||
exports.getMarkerClassName = getMarkerClassName;
|
||||
exports.getMarkerFields = getMarkerFields;
|
||||
exports.DOM = DOM;
|
||||
exports.CollapseFunctions = CollapseFunctions;
|
||||
exports.Formatters = Formatters;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
loader.lazyRequireGetter(this, "TIMELINE_BLUEPRINT",
|
||||
"devtools/performance/global", true);
|
||||
"devtools/performance/markers", true);
|
||||
|
||||
/**
|
||||
* Collapses markers into a tree-like structure. Currently, this only goes
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { L10N } = require("devtools/performance/global");
|
||||
const { Formatters, CollapseFunctions } = require("devtools/performance/marker-utils");
|
||||
|
||||
/**
|
||||
* A simple schema for mapping markers to the timeline UI. The keys correspond
|
||||
* to marker names, while the values are objects with the following format:
|
||||
*
|
||||
* - group: The row index in the timeline overview graph; multiple markers
|
||||
* can be added on the same row. @see <overview.js/buildGraphImage>
|
||||
* - label: The label used in the waterfall to identify the marker. Can be a
|
||||
* string or just a function that accepts the marker and returns a
|
||||
* string, if you want to use a dynamic property for the main label.
|
||||
* If you use a function for a label, it *must* handle the case where
|
||||
* no marker is provided for a main label to describe all markers of
|
||||
* this type.
|
||||
* - colorName: The label of the DevTools color used for this marker. If
|
||||
* adding a new color, be sure to check that there's an entry
|
||||
* for `.marker-details-bullet.{COLORNAME}` for the equivilent
|
||||
* entry in ./browser/themes/shared/devtools/performance.inc.css
|
||||
* https://developer.mozilla.org/en-US/docs/Tools/DevToolsColors
|
||||
* - collapseFunc: A function determining how markers are collapsed together.
|
||||
* Invoked with 3 arguments: the current parent marker, the
|
||||
* current marker and a method for peeking i markers ahead. If
|
||||
* nothing is returned, the marker is added as a standalone entry
|
||||
* in the waterfall. Otherwise, an object needs to be returned
|
||||
* with the following properties:
|
||||
* - toParent: The parent marker name (needs to be an entry in
|
||||
* the `TIMELINE_BLUEPRINT` itself).
|
||||
* - withData: An object containing some properties to staple
|
||||
* on the parent marker.
|
||||
* - forceNew: True if a new parent marker needs to be created
|
||||
* even though there is one currently available
|
||||
* with the same name.
|
||||
* - forceEnd: True if the current parent marker is full after
|
||||
* this collapse operation and should be finalized.
|
||||
* - fields: An optional array of marker properties you wish to display in the
|
||||
* marker details view. For example, a field in the array such as
|
||||
* { property: "aCauseName", label: "Cause" } would render a string
|
||||
* like `Cause: ${marker.aCauseName}` in the marker details view.
|
||||
* Each `field` item may take the following properties:
|
||||
* - property: The property that must exist on the marker to render,
|
||||
* and the value of the property will be displayed.
|
||||
* - label: The name of the property that should be displayed.
|
||||
* - formatter: If a formatter is provided, instead of directly using
|
||||
* the `property` property on the marker, the marker is
|
||||
* passed into the formatter function to determine the
|
||||
* displayed value.
|
||||
* Can also be a function that returns an object. Each key in the object
|
||||
* will be rendered as a field, with its value rendering as the value.
|
||||
*
|
||||
* Whenever this is changed, browser_timeline_waterfall-styles.js *must* be
|
||||
* updated as well.
|
||||
*/
|
||||
const TIMELINE_BLUEPRINT = {
|
||||
/* Group 0 - Reflow and Rendering pipeline */
|
||||
"Styles": {
|
||||
group: 0,
|
||||
colorName: "graphs-purple",
|
||||
collapseFunc: CollapseFunctions.identical,
|
||||
label: L10N.getStr("timeline.label.styles2"),
|
||||
fields: Formatters.StylesFields,
|
||||
},
|
||||
"Reflow": {
|
||||
group: 0,
|
||||
colorName: "graphs-purple",
|
||||
collapseFunc: CollapseFunctions.identical,
|
||||
label: L10N.getStr("timeline.label.reflow2"),
|
||||
},
|
||||
"Paint": {
|
||||
group: 0,
|
||||
colorName: "graphs-green",
|
||||
collapseFunc: CollapseFunctions.identical,
|
||||
label: L10N.getStr("timeline.label.paint"),
|
||||
},
|
||||
|
||||
/* Group 1 - JS */
|
||||
"DOMEvent": {
|
||||
group: 1,
|
||||
colorName: "graphs-yellow",
|
||||
collapseFunc: CollapseFunctions.DOMtoDOMJS,
|
||||
label: L10N.getStr("timeline.label.domevent"),
|
||||
fields: Formatters.DOMEventFields,
|
||||
},
|
||||
"Javascript": {
|
||||
group: 1,
|
||||
colorName: "graphs-yellow",
|
||||
collapseFunc: either(CollapseFunctions.JStoDOMJS, CollapseFunctions.identical),
|
||||
label: Formatters.JSLabel,
|
||||
fields: Formatters.JSFields
|
||||
},
|
||||
"meta::DOMEvent+JS": {
|
||||
colorName: "graphs-yellow",
|
||||
label: Formatters.DOMJSLabel,
|
||||
fields: Formatters.DOMJSFields,
|
||||
},
|
||||
"Parse HTML": {
|
||||
group: 1,
|
||||
colorName: "graphs-yellow",
|
||||
collapseFunc: CollapseFunctions.identical,
|
||||
label: L10N.getStr("timeline.label.parseHTML"),
|
||||
},
|
||||
"Parse XML": {
|
||||
group: 1,
|
||||
colorName: "graphs-yellow",
|
||||
collapseFunc: CollapseFunctions.identical,
|
||||
label: L10N.getStr("timeline.label.parseXML"),
|
||||
},
|
||||
"GarbageCollection": {
|
||||
group: 1,
|
||||
colorName: "graphs-red",
|
||||
collapseFunc: CollapseFunctions.adjacent,
|
||||
label: Formatters.GCLabel,
|
||||
fields: [
|
||||
{ property: "causeName", label: "Reason:" },
|
||||
{ property: "nonincrementalReason", label: "Non-incremental Reason:" }
|
||||
],
|
||||
},
|
||||
"nsCycleCollector::Collect": {
|
||||
group: 1,
|
||||
colorName: "graphs-red",
|
||||
collapseFunc: either(collapse.parent, collapse.child),
|
||||
label: "Cycle Collection",
|
||||
fields: Formatters.CycleCollectionFields,
|
||||
},
|
||||
"nsCycleCollector::ForgetSkippable": {
|
||||
group: 1,
|
||||
colorName: "graphs-red",
|
||||
collapseFunc: either(collapse.parent, collapse.child),
|
||||
label: "Cycle Collection",
|
||||
fields: Formatters.CycleCollectionFields,
|
||||
},
|
||||
|
||||
/* Group 2 - User Controlled */
|
||||
"ConsoleTime": {
|
||||
group: 2,
|
||||
colorName: "graphs-grey",
|
||||
label: sublabelForProperty(L10N.getStr("timeline.label.consoleTime"), "causeName"),
|
||||
fields: [{
|
||||
property: "causeName",
|
||||
label: L10N.getStr("timeline.markerDetail.consoleTimerName")
|
||||
}],
|
||||
},
|
||||
"TimeStamp": {
|
||||
group: 2,
|
||||
colorName: "graphs-blue",
|
||||
label: sublabelForProperty(L10N.getStr("timeline.label.timestamp"), "causeName"),
|
||||
fields: [{
|
||||
property: "causeName",
|
||||
label: "Label:"
|
||||
}],
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper for creating a function that returns the first defined result from
|
||||
* a list of functions passed in as params, in order.
|
||||
* @param ...function fun
|
||||
* @return any
|
||||
*/
|
||||
function either(...fun) {
|
||||
return function() {
|
||||
for (let f of fun) {
|
||||
let result = f.apply(null, arguments);
|
||||
if (result !== undefined) return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a main label (like "Timestamp") and a property,
|
||||
* and returns a marker that will print out the property
|
||||
* value for a marker if it exists ("Timestamp (rendering)"),
|
||||
* or just the main label if it does not.
|
||||
*/
|
||||
function sublabelForProperty (mainLabel, prop) {
|
||||
return (marker={}) => marker[prop] ? `${mainLabel} (${marker[prop]})` : mainLabel;
|
||||
}
|
||||
|
||||
// Exported symbols.
|
||||
exports.TIMELINE_BLUEPRINT = TIMELINE_BLUEPRINT;
|
||||
@@ -14,7 +14,7 @@ loader.lazyRequireGetter(this, "EventEmitter",
|
||||
loader.lazyRequireGetter(this, "L10N",
|
||||
"devtools/performance/global", true);
|
||||
loader.lazyRequireGetter(this, "TIMELINE_BLUEPRINT",
|
||||
"devtools/performance/global", true);
|
||||
"devtools/performance/markers", true);
|
||||
loader.lazyRequireGetter(this, "MarkerUtils",
|
||||
"devtools/performance/marker-utils");
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
const { Cc, Ci, Cu, Cr } = require("chrome");
|
||||
const { Heritage } = require("resource:///modules/devtools/ViewHelpers.jsm");
|
||||
const { AbstractTreeItem } = require("resource:///modules/devtools/AbstractTreeItem.jsm");
|
||||
const { TIMELINE_BLUEPRINT: ORIGINAL_BP } = require("devtools/performance/global");
|
||||
const { TIMELINE_BLUEPRINT: ORIGINAL_BP } = require("devtools/performance/markers");
|
||||
|
||||
loader.lazyRequireGetter(this, "MarkerUtils",
|
||||
"devtools/performance/marker-utils");
|
||||
|
||||
@@ -16,6 +16,7 @@ EXTRA_JS_MODULES.devtools.performance += [
|
||||
'modules/logic/recording-utils.js',
|
||||
'modules/logic/tree-model.js',
|
||||
'modules/logic/waterfall-utils.js',
|
||||
'modules/markers.js',
|
||||
'modules/widgets/graphs.js',
|
||||
'modules/widgets/marker-details.js',
|
||||
'modules/widgets/marker-view.js',
|
||||
|
||||
@@ -56,7 +56,9 @@ PerformancePanel.prototype = {
|
||||
|
||||
// DevToolPanel API
|
||||
|
||||
get target() this._toolbox.target,
|
||||
get target() {
|
||||
return this._toolbox.target;
|
||||
},
|
||||
|
||||
destroy: Task.async(function*() {
|
||||
// Make sure this panel is not already destroyed.
|
||||
|
||||
@@ -18,7 +18,7 @@ loader.lazyRequireGetter(this, "DevToolsUtils",
|
||||
loader.lazyRequireGetter(this, "L10N",
|
||||
"devtools/performance/global", true);
|
||||
loader.lazyRequireGetter(this, "TIMELINE_BLUEPRINT",
|
||||
"devtools/performance/global", true);
|
||||
"devtools/performance/markers", true);
|
||||
loader.lazyRequireGetter(this, "RecordingUtils",
|
||||
"devtools/performance/recording-utils");
|
||||
loader.lazyRequireGetter(this, "RecordingModel",
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* You can also use this initialization format as a template for other tests.
|
||||
*/
|
||||
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { target, panel, toolbox } = yield initPerformance(SIMPLE_URL);
|
||||
|
||||
ok(target, "Should have a target available.");
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
* Tests the marker utils methods.
|
||||
*/
|
||||
|
||||
function spawnTest () {
|
||||
let { TIMELINE_BLUEPRINT } = devtools.require("devtools/performance/global");
|
||||
function* spawnTest() {
|
||||
let { TIMELINE_BLUEPRINT } = devtools.require("devtools/performance/markers");
|
||||
let Utils = devtools.require("devtools/performance/marker-utils");
|
||||
|
||||
Services.prefs.setBoolPref(PLATFORM_DATA_PREF, false);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Tests that the categories are shown in the js call tree when platform data
|
||||
* is enabled.
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, $, DetailsView, JsCallTreeView } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/**
|
||||
* Tests that the js call tree view renders the correct columns.
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, $, $$, DetailsView, JsCallTreeView } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/**
|
||||
* Tests that the memory call tree view renders the correct columns.
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, $, $$, DetailsView, MemoryCallTreeView } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
let WAIT_TIME = 100;
|
||||
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { target, front } = yield initBackend(SIMPLE_URL, {
|
||||
TEST_MOCK_MEMORY_ACTOR: true,
|
||||
TEST_MOCK_TIMELINE_ACTOR: true
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
let WAIT_TIME = 100;
|
||||
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { target, front } = yield initBackend(SIMPLE_URL, {
|
||||
TEST_MOCK_MEMORY_ACTOR: true
|
||||
});
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
const WAIT_TIME = 1000; // ms
|
||||
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { gFront: front, gTarget: target } = panel.panelWin;
|
||||
let connection = getPerformanceActorsConnection(target);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* `getBufferUsage()` values.
|
||||
*/
|
||||
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { target, front } = yield initBackend(SIMPLE_URL, {
|
||||
TEST_MOCK_PROFILER_CHECK_TIMER: 10,
|
||||
TEST_PROFILER_FILTER_STATUS: ["position", "totalSize", "generation"]
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Tests that recording notices does not display any buffer
|
||||
* status on servers that do not support buffer statuses.
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL, void 0, {
|
||||
TEST_MOCK_PROFILER_CHECK_TIMER: 10,
|
||||
TEST_PROFILER_FILTER_STATUS: ["position", "totalSize", "generation"]
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
let { getPerformanceActorsConnection } = devtools.require("devtools/performance/front");
|
||||
let WAIT_TIME = 10;
|
||||
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let profilerConnected = waitForProfilerConnection();
|
||||
let { target, toolbox, console } = yield initConsole(SIMPLE_URL);
|
||||
yield profilerConnected;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
let { getPerformanceActorsConnection } = devtools.require("devtools/performance/front");
|
||||
let WAIT_TIME = 10;
|
||||
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let profilerConnected = waitForProfilerConnection();
|
||||
let { target, toolbox, console } = yield initConsole(SIMPLE_URL);
|
||||
yield profilerConnected;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
let { getPerformanceActorsConnection } = devtools.require("devtools/performance/front");
|
||||
let WAIT_TIME = 10;
|
||||
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let profilerConnected = waitForProfilerConnection();
|
||||
let { target, toolbox, console } = yield initConsole(SIMPLE_URL);
|
||||
yield profilerConnected;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* after being opened.
|
||||
*/
|
||||
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
loadFrameScripts();
|
||||
let { target, toolbox, panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { $, EVENTS, gFront, PerformanceController, OverviewView, RecordingsView } = panel.panelWin;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* in the recording list.
|
||||
*/
|
||||
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
loadFrameScripts();
|
||||
let { target, toolbox, panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { $, EVENTS, gFront, PerformanceController, OverviewView, RecordingsView } = panel.panelWin;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Tests that console recordings can overlap (not completely nested).
|
||||
*/
|
||||
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
loadFrameScripts();
|
||||
let { target, toolbox, panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { $, EVENTS, gFront, PerformanceController, OverviewView, RecordingsView, WaterfallView } = panel.panelWin;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* match any pending recordings does nothing.
|
||||
*/
|
||||
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
loadFrameScripts();
|
||||
let { target, toolbox, panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { $, EVENTS, gFront, PerformanceController, OverviewView, RecordingsView, WaterfallView } = panel.panelWin;
|
||||
|
||||
@@ -21,7 +21,7 @@ function testRecordings (win, expected) {
|
||||
});
|
||||
}
|
||||
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
loadFrameScripts();
|
||||
let { target, toolbox, panel } = yield initPerformance(SIMPLE_URL);
|
||||
let win = panel.panelWin;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
const WAIT_TIME = 1000; // ms
|
||||
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let front = panel.panelWin.gFront;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
const WAIT_TIME = 1000; // ms
|
||||
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let front = panel.panelWin.gFront;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/**
|
||||
* Tests that the details view toggles subviews.
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, $, DetailsView, document: doc } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/**
|
||||
* Tests that the details view utility functions work as advertised.
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView } = panel.panelWin;
|
||||
let { WaterfallView, JsCallTreeView, JsFlameGraphView } = panel.panelWin;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* have memory data (withMemory: false), and that when a memory panel is selected,
|
||||
* switching to a panel that does not have memory goes to a default panel instead.
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, PerformanceController, OverviewView, DetailsView } = panel.panelWin;
|
||||
let { $, RecordingsView, WaterfallView, MemoryCallTreeView, MemoryFlameGraphView } = panel.panelWin;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Tests that the details view hides the toolbar buttons when a recording
|
||||
* doesn't exist or is in progress.
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, $, $$, PerformanceController, RecordingsView, WaterfallView } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/**
|
||||
* Tests that the details view utility functions work as advertised.
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView } = panel.panelWin;
|
||||
let { PerformanceController, WaterfallView, JsCallTreeView } = panel.panelWin;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/**
|
||||
* Tests that the views with `shouldUpdateWhileMouseIsActive` works as intended.
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, PerformanceController, OverviewView, DetailsView, WaterfallView, JsFlameGraphView } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/**
|
||||
* Tests that the call tree view renders content after recording.
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView, JsCallTreeView } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/**
|
||||
* Tests that the flamegraph view renders content after recording.
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView, JsFlameGraphView } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/**
|
||||
* Tests that the memory call tree view renders content after recording.
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView, MemoryCallTreeView } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/**
|
||||
* Tests that the memory flamegraph view renders content after recording.
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView, MemoryFlameGraphView } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/**
|
||||
* Tests that the waterfall view renders content after recording.
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, PerformanceController, DetailsView, WaterfallView } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
const { ThreadNode } = devtools.require("devtools/performance/tree-model");
|
||||
const RecordingUtils = devtools.require("devtools/performance/recording-utils")
|
||||
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let focus = 0;
|
||||
let focusEvent = () => focus++;
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
let WAIT_TIME = 1000;
|
||||
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { target, front } = yield initBackend(SIMPLE_URL);
|
||||
|
||||
let recording = yield front.startRecording({
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
let WAIT_TIME = 1000;
|
||||
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { target, front } = yield initBackend(SIMPLE_URL);
|
||||
let config = { withMarkers: true, withMemory: true, withTicks: true };
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
let WAIT_TIME = 1000;
|
||||
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { target, front } = yield initBackend(SIMPLE_URL);
|
||||
|
||||
let startModel = yield front.startRecording();
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Test basic functionality of PerformanceFront, retrieving timeline data.
|
||||
*/
|
||||
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { target, front } = yield initBackend(SIMPLE_URL);
|
||||
|
||||
let lastMemoryDelta = 0;
|
||||
@@ -68,8 +68,11 @@ function spawnTest () {
|
||||
counters.ticks.push({ delta, timestamps });
|
||||
lastTickDelta = delta;
|
||||
}
|
||||
else if (name === "frames") {
|
||||
// Nothing to do here.
|
||||
}
|
||||
else {
|
||||
throw new Error("unknown event " + name);
|
||||
ok(false, `Received unknown event: ${name}`);
|
||||
}
|
||||
|
||||
if (name === "markers" && counters[name].length === 1 ||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
let { getPerformanceActorsConnection } = devtools.require("devtools/performance/front");
|
||||
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let profilerConnected = waitForProfilerConnection();
|
||||
let { target, toolbox, console } = yield initConsole(SIMPLE_URL);
|
||||
yield profilerConnected;
|
||||
|
||||
@@ -10,7 +10,7 @@ const RecordingUtils = devtools.require("devtools/performance/recording-utils");
|
||||
|
||||
Services.prefs.setBoolPref(INVERT_PREF, false);
|
||||
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, $, $$, window, PerformanceController } = panel.panelWin;
|
||||
let { OverviewView, DetailsView, JITOptimizationsView, JsCallTreeView, RecordingsView } = panel.panelWin;
|
||||
|
||||
@@ -12,7 +12,7 @@ const RecordingUtils = devtools.require("devtools/performance/recording-utils");
|
||||
Services.prefs.setBoolPref(INVERT_PREF, false);
|
||||
Services.prefs.setBoolPref(PLATFORM_DATA_PREF, false);
|
||||
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, $, $$, window, PerformanceController } = panel.panelWin;
|
||||
let { OverviewView, DetailsView, JITOptimizationsView, JsCallTreeView, RecordingsView } = panel.panelWin;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/**
|
||||
* Tests that toggling preferences before there are any recordings does not throw.
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView, JsCallTreeView } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/**
|
||||
* Tests that toggling preferences during a recording does not throw.
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView, JsCallTreeView } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
Services.prefs.setBoolPref(EXPERIMENTAL_PREF, false);
|
||||
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { $, EVENTS, PerformanceController } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/**
|
||||
* Tests that setting the `devtools.performance.memory.` prefs propagate to the memory actor.
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, PerformanceController, $, gFront } = panel.panelWin;
|
||||
Services.prefs.setBoolPref(MEMORY_PREF, true);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Tests that `enable-framerate` toggles the visibility of the fps graph,
|
||||
* as well as enabling ticks data on the PerformanceFront.
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, PerformanceController, $ } = panel.panelWin;
|
||||
Services.prefs.setBoolPref(FRAMERATE_PREF, false);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Tests that `enable-memory` toggles the visibility of the memory graph,
|
||||
* as well as enabling memory data on the PerformanceFront.
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, PerformanceController, $ } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Tests that toggling `enable-memory` during a recording doesn't change that
|
||||
* recording's state and does not break.
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, PerformanceController, $ } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/**
|
||||
* Tests that the js flamegraphs get rerendered when toggling `flatten-tree-recursion`
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, PerformanceController, DetailsView, JsFlameGraphView, FlameGraphUtils } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/**
|
||||
* Tests that the memory flamegraphs get rerendered when toggling `flatten-tree-recursion`
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, PerformanceController, DetailsView, MemoryFlameGraphView, RecordingUtils, FlameGraphUtils } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/**
|
||||
* Tests that the js call tree views get rerendered when toggling `invert-call-tree`
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView, JsCallTreeView } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/**
|
||||
* Tests that the memory call tree views get rerendered when toggling `invert-call-tree`
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView, MemoryCallTreeView } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/**
|
||||
* Tests that the js Flamegraphs gets rerendered when toggling `invert-flame-graph`
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView, JsFlameGraphView } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/**
|
||||
* Tests that the memory Flamegraphs gets rerendered when toggling `invert-flame-graph`
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView, MemoryFlameGraphView } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
/**
|
||||
* Tests that setting the `devtools.performance.profiler.` prefs propagate to the profiler actor.
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { gFront } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/**
|
||||
* Tests that the js flamegraphs get rerendered when toggling `show-idle-blocks`
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView, JsFlameGraphView } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/**
|
||||
* Tests that the memory flamegraphs get rerendered when toggling `show-idle-blocks`
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView, MemoryFlameGraphView } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/**
|
||||
* Tests that the js call tree views get rerendered when toggling `show-platform-data`
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView, JsCallTreeView } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/**
|
||||
* Tests that the js flamegraphs get rerendered when toggling `show-platform-data`
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, DetailsView, JsFlameGraphView } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/**
|
||||
* Tests that the overview continuously renders content when recording.
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, OverviewView } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Tests that the overview graphs cannot be selected during recording
|
||||
* and that they're cleared upon rerecording.
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, OverviewView } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/**
|
||||
* Tests that the overview graphs share the exact same width and scaling.
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, PerformanceController, OverviewView } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Tests that the overview graphs do not render when realtime rendering is off
|
||||
* due to lack of e10s.
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { $, EVENTS, PerformanceController, OverviewView, RecordingsView } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/**
|
||||
* Tests that events are fired from OverviewView from selection manipulation.
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, PerformanceController, OverviewView } = panel.panelWin;
|
||||
let startTime, endTime, params, _;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/**
|
||||
* Tests that the graphs' selection is correctly disabled or enabled.
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, OverviewView } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/**
|
||||
* Tests that the graphs' selections are linked.
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, OverviewView } = panel.panelWin;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Tests that the `setTimeInterval` and `getTimeInterval` functions
|
||||
* work properly.
|
||||
*/
|
||||
function spawnTest () {
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, PerformanceController, OverviewView } = panel.panelWin;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user