Files
tubestation/toolkit/components/backgroundhangmonitor/HangStack.cpp
Michael Layzell f2fe978e6f Bug 1380081 - Part 7: Add all necessary data for BHR to nsIHangDetails, r=froydnj
We're going to use HangDetails as the type containing hang information. We'll
have a JS component which reads the data out of nsIHangDetails, builds the
payload, and submits it to telemetry for us.

We'll do it in JS because telemetry has to be submitted from JS.

This patch also adds IPC serization for the relevant types so that we can send
HangDetails objects over IPDL.

MozReview-Commit-ID: CeikKabY9Vs
2017-08-15 16:35:39 -04:00

104 lines
2.7 KiB
C++

#include "HangStack.h"
namespace mozilla {
HangStack::HangStack(const HangStack& aOther)
{
if (NS_WARN_IF(!mBuffer.reserve(aOther.mBuffer.length()) ||
!mImpl.reserve(aOther.mImpl.length()))) {
return;
}
// XXX: I should be able to just memcpy the other stack's mImpl and mBuffer,
// and then just re-offset pointers.
for (size_t i = 0; i < aOther.length(); ++i) {
const char* s = aOther[i];
if (aOther.IsInBuffer(s)) {
InfallibleAppendViaBuffer(s, strlen(s));
} else {
infallibleAppend(s);
}
}
MOZ_ASSERT(mImpl.length() == aOther.mImpl.length());
MOZ_ASSERT(mBuffer.length() == aOther.mBuffer.length());
}
const char*
HangStack::InfallibleAppendViaBuffer(const char* aText, size_t aLength)
{
MOZ_ASSERT(this->canAppendWithoutRealloc(1));
// Include null-terminator in length count.
MOZ_ASSERT(mBuffer.canAppendWithoutRealloc(aLength + 1));
const char* const entry = mBuffer.end();
mBuffer.infallibleAppend(aText, aLength);
mBuffer.infallibleAppend('\0'); // Explicitly append null-terminator
this->infallibleAppend(entry);
return entry;
}
const char*
HangStack::AppendViaBuffer(const char* aText, size_t aLength)
{
if (!this->reserve(this->length() + 1)) {
return nullptr;
}
// Keep track of the previous buffer in case we need to adjust pointers later.
const char* const prevStart = mBuffer.begin();
const char* const prevEnd = mBuffer.end();
// Include null-terminator in length count.
if (!mBuffer.reserve(mBuffer.length() + aLength + 1)) {
return nullptr;
}
if (prevStart != mBuffer.begin()) {
// The buffer has moved; we have to adjust pointers in the stack.
for (auto & entry : *this) {
if (entry >= prevStart && entry < prevEnd) {
// Move from old buffer to new buffer.
entry += mBuffer.begin() - prevStart;
}
}
}
return InfallibleAppendViaBuffer(aText, aLength);
}
} // namespace mozilla
namespace IPC {
void
ParamTraits<mozilla::HangStack>::Write(Message* aMsg, const mozilla::HangStack& aParam)
{
size_t length = aParam.length();
WriteParam(aMsg, length);
for (size_t i = 0; i < length; ++i) {
nsDependentCString str(aParam[i]);
WriteParam(aMsg, static_cast<nsACString&>(str));
}
}
bool
ParamTraits<mozilla::HangStack>::Read(const Message* aMsg,
PickleIterator* aIter,
mozilla::HangStack* aResult)
{
size_t length;
if (!ReadParam(aMsg, aIter, &length)) {
return false;
}
for (size_t i = 0; i < length; ++i) {
nsAutoCString str;
if (!ReadParam(aMsg, aIter, &str)) {
return false;
}
aResult->AppendViaBuffer(str.get(), str.Length());
}
return true;
}
} // namespace IPC