Merge inbound to central, a=merge

This commit is contained in:
Wes Kocher 2015-06-12 17:17:43 -07:00
Родитель 551f69887c 6ad3c672b5
Коммит a9e2fe1637
20 изменённых файлов: 848 добавлений и 317 удалений

Просмотреть файл

@ -805,7 +805,11 @@ getParentCB(AtkObject *aAtkObj)
atkParent = GetWrapperFor(parent);
} else {
// Otherwise this should be the proxy for the tab's top level document.
atkParent = AccessibleWrap::GetAtkObject(proxy->OuterDocOfRemoteBrowser());
Accessible* outerDocParent = proxy->OuterDocOfRemoteBrowser();
NS_ASSERTION(outerDocParent, "this document should have an outerDoc as a parent");
if (outerDocParent) {
atkParent = AccessibleWrap::GetAtkObject(outerDocParent);
}
}
}

Просмотреть файл

@ -152,7 +152,11 @@
work correctly on the menupopup. ContentSelectDropdown expects the
popuponly menulist to be its immediate parent. -->
<menulist popuponly="true" id="ContentSelectDropdown" hidden="true">
<menupopup rolluponmousewheel="true"/>
<menupopup rolluponmousewheel="true"
#ifdef XP_WIN
consumeoutsideclicks="false"
#endif
/>
</menulist>
<!-- for invalid form error message -->

Просмотреть файл

@ -73,10 +73,6 @@
#include "SurfaceCache.h"
#include "gfxPrefs.h"
#if defined(MOZ_CRASHREPORTER)
#include "nsExceptionHandler.h"
#endif
#include "VsyncSource.h"
#include "DriverInitCrashDetection.h"
@ -1721,16 +1717,12 @@ bool DoesD3D11DeviceWork(ID3D11Device *device)
gfxWindowsPlatform::GetDLLVersion(L"dlumd32.dll", displayLinkModuleVersionString);
uint64_t displayLinkModuleVersion;
if (!ParseDriverVersion(displayLinkModuleVersionString, &displayLinkModuleVersion)) {
#if defined(MOZ_CRASHREPORTER)
CrashReporter::AppendAppNotesToCrashReport(NS_LITERAL_CSTRING("DisplayLink: could not parse version\n"));
#endif
gfxCriticalError() << "DisplayLink: could not parse version";
gANGLESupportsD3D11 = false;
return false;
}
if (displayLinkModuleVersion <= V(8,6,1,36484)) {
#if defined(MOZ_CRASHREPORTER)
CrashReporter::AppendAppNotesToCrashReport(NS_LITERAL_CSTRING("DisplayLink: too old version\n"));
#endif
gfxCriticalError(CriticalLog::DefaultOptions(false)) << "DisplayLink: too old version";
gANGLESupportsD3D11 = false;
return false;
}
@ -1762,9 +1754,7 @@ bool DoesD3D11TextureSharingWorkInternal(ID3D11Device *device, DXGI_FORMAT forma
gfxInfo->GetAdapterVendorID(vendorID);
gfxInfo->GetAdapterVendorID2(vendorID2);
if (vendorID.EqualsLiteral("0x8086") && vendorID2.IsEmpty()) {
#if defined(MOZ_CRASHREPORTER)
CrashReporter::AppendAppNotesToCrashReport(NS_LITERAL_CSTRING("Unexpected Intel/AMD dual-GPU setup\n"));
#endif
gfxCriticalError(CriticalLog::DefaultOptions(false)) << "Unexpected Intel/AMD dual-GPU setup";
return false;
}
}
@ -1804,6 +1794,7 @@ bool DoesD3D11TextureSharingWorkInternal(ID3D11Device *device, DXGI_FORMAT forma
if (FAILED(device->OpenSharedResource(shareHandle, __uuidof(ID3D11Resource),
getter_AddRefs(sharedResource))))
{
gfxCriticalError(CriticalLog::DefaultOptions(false)) << "OpenSharedResource failed for format " << format;
return false;
}
@ -1817,9 +1808,7 @@ bool DoesD3D11TextureSharingWorkInternal(ID3D11Device *device, DXGI_FORMAT forma
// This if(FAILED()) is the one that actually fails on systems affected by bug 1083071.
if (FAILED(device->CreateShaderResourceView(sharedTexture, NULL, byRef(sharedView)))) {
#if defined(MOZ_CRASHREPORTER)
CrashReporter::AppendAppNotesToCrashReport(NS_LITERAL_CSTRING("CreateShaderResourceView failed\n"));
#endif
gfxCriticalError(CriticalLog::DefaultOptions(false)) << "CreateShaderResourceView failed for format" << format;
return false;
}
@ -1843,13 +1832,17 @@ bool DoesD3D11AlphaTextureSharingWork(ID3D11Device *device)
{
nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
if (gfxInfo) {
// Disable texture sharing if we're blocking d2d since that's the only other time we use it
// and it might be broken.
int32_t status;
if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT2D, &status))) {
if (status != nsIGfxInfo::FEATURE_STATUS_OK) {
return false;
}
// A8 texture sharing crashes on this intel driver version (and no others)
// so just avoid using it in that case.
nsString adapterVendor;
nsString driverVersion;
gfxInfo->GetAdapterVendorID(adapterVendor);
gfxInfo->GetAdapterDriverVersion(driverVersion);
nsAString &intelVendorID = (nsAString &)GfxDriverInfo::GetDeviceVendor(VendorIntel);
if (adapterVendor.Equals(intelVendorID, nsCaseInsensitiveStringComparator()) &&
driverVersion.Equals(NS_LITERAL_STRING("8.15.10.2086"))) {
return false;
}
}
@ -1951,6 +1944,8 @@ gfxWindowsPlatform::InitD3D11Devices()
featureLevels.Elements(), featureLevels.Length(),
D3D11_SDK_VERSION, byRef(mD3D11Device), nullptr, nullptr);
} MOZ_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER) {
gfxCriticalError() << "Crash during D3D11 device creation";
if (gfxPrefs::LayersD3D11DisableWARP()) {
return;
}
@ -1960,6 +1955,7 @@ gfxWindowsPlatform::InitD3D11Devices()
}
if (FAILED(hr) || !DoesD3D11DeviceWork(mD3D11Device)) {
gfxCriticalError() << "D3D11 device creation failed" << hexa(hr);
if (gfxPrefs::LayersD3D11DisableWARP()) {
return;
}

Просмотреть файл

@ -28,8 +28,9 @@ MacroAssembler::setFramePushed(uint32_t framePushed)
}
void
MacroAssembler::adjustFrame(int value)
MacroAssembler::adjustFrame(int32_t value)
{
MOZ_ASSERT_IF(value < 0, framePushed_ >= uint32_t(-value));
setFramePushed(framePushed_ + value);
}
@ -37,7 +38,8 @@ void
MacroAssembler::implicitPop(uint32_t bytes)
{
MOZ_ASSERT(bytes % sizeof(intptr_t) == 0);
adjustFrame(-bytes);
MOZ_ASSERT(bytes <= INT32_MAX);
adjustFrame(-int32_t(bytes));
}
// ===============================================================

Просмотреть файл

@ -280,7 +280,7 @@ class MacroAssembler : public MacroAssemblerSpecific
inline uint32_t framePushed() const;
inline void setFramePushed(uint32_t framePushed);
inline void adjustFrame(int value);
inline void adjustFrame(int32_t value);
// Adjust the frame, to account for implicit modification of the stack
// pointer, such that callee can remove arguments on the behalf of the

Просмотреть файл

@ -3340,7 +3340,7 @@ bool RangeAnalysis::tryRemovingGuards()
MDefinitionVector guards(alloc());
for (ReversePostorderIterator block = graph_.rpoBegin(); block != graph_.rpoEnd(); block++) {
for (MInstructionReverseIterator iter = block->rbegin(); iter != block->rend(); iter++) {
for (MDefinitionIterator iter(*block); iter; iter++) {
if (!iter->isGuardRangeBailouts())
continue;

Просмотреть файл

@ -12,6 +12,7 @@
#include "jsprf.h"
#include "mozilla/Snprintf.h"
#include "mozilla/Vector.h"
#include <stdarg.h>
@ -286,8 +287,6 @@ static bool cvt_ll(SprintfState* ss, int64_t num, int width, int prec, int radix
/*
* Convert a double precision floating point number into its printable
* form.
*
* XXX stop using sprintf to convert floating point
*/
static bool cvt_f(SprintfState* ss, double d, const char* fmt0, const char* fmt1)
{
@ -303,7 +302,7 @@ static bool cvt_f(SprintfState* ss, double d, const char* fmt0, const char* fmt1
js_memcpy(fin, fmt0, (size_t)amount);
fin[amount] = 0;
// Convert floating point using the native sprintf code
// Convert floating point using the native snprintf code
#ifdef DEBUG
{
const char* p = fin;
@ -313,12 +312,7 @@ static bool cvt_f(SprintfState* ss, double d, const char* fmt0, const char* fmt1
}
}
#endif
sprintf(fout, fin, d);
// This assert will catch overflow's of fout, when building with
// debugging on. At least this way we can track down the evil piece
// of calling code and fix it!
MOZ_ASSERT(strlen(fout) < sizeof(fout));
snprintf_literal(fout, fin, d);
return (*ss->stuff)(ss, fout, strlen(fout));
}

Просмотреть файл

@ -533,19 +533,18 @@ JsepSessionImpl::SetupBundle(Sdp* sdp) const
}
nsresult
JsepSessionImpl::FinalizeTransportAttributes(Sdp* offer)
JsepSessionImpl::SetupTransportAttributes(const Sdp& newOffer, Sdp* local)
{
const Sdp* oldAnswer = GetAnswer();
if (oldAnswer) {
// Renegotiation, we might have transport attributes to copy over
for (size_t i = 0; i < oldAnswer->GetMediaSectionCount(); ++i) {
if (!MsectionIsDisabled(offer->GetMediaSection(i)) &&
!MsectionIsDisabled(oldAnswer->GetMediaSection(i)) &&
!IsBundleSlave(*oldAnswer, i)) {
if (!MsectionIsDisabled(local->GetMediaSection(i)) &&
AreOldTransportParamsValid(*oldAnswer, newOffer, i)) {
nsresult rv = CopyTransportParams(
mCurrentLocalDescription->GetMediaSection(i),
&offer->GetMediaSection(i));
&local->GetMediaSection(i));
NS_ENSURE_SUCCESS(rv, rv);
}
}
@ -769,7 +768,7 @@ JsepSessionImpl::CreateOffer(const JsepOfferOptions& options,
SetupBundle(sdp.get());
rv = FinalizeTransportAttributes(sdp.get());
rv = SetupTransportAttributes(*sdp, sdp.get());
NS_ENSURE_SUCCESS(rv,rv);
*offer = sdp->ToString();
@ -1022,6 +1021,9 @@ JsepSessionImpl::CreateAnswer(const JsepAnswerOptions& options,
NS_ENSURE_SUCCESS(rv, rv);
}
rv = SetupTransportAttributes(offer, sdp.get());
NS_ENSURE_SUCCESS(rv,rv);
*answer = sdp->ToString();
mGeneratedLocalDescription = Move(sdp);
@ -1416,6 +1418,7 @@ JsepSessionImpl::SetLocalDescriptionAnswer(JsepSdpType type,
mCurrentRemoteDescription = Move(mPendingRemoteDescription);
mCurrentLocalDescription = Move(mPendingLocalDescription);
mWasOffererLastTime = mIsOfferer;
SetState(kJsepStateStable);
return NS_OK;
@ -1865,6 +1868,37 @@ JsepSessionImpl::FinalizeTransport(const SdpAttributeList& remote,
return NS_OK;
}
bool
JsepSessionImpl::AreOldTransportParamsValid(const Sdp& oldAnswer,
const Sdp& newOffer,
size_t level)
{
if (MsectionIsDisabled(oldAnswer.GetMediaSection(level)) ||
MsectionIsDisabled(newOffer.GetMediaSection(level))) {
// Obvious
return false;
}
if (IsBundleSlave(oldAnswer, level)) {
// The transport attributes on this m-section were thrown away, because it
// was bundled.
return false;
}
if (newOffer.GetMediaSection(level).GetAttributeList().HasAttribute(
SdpAttribute::kBundleOnlyAttribute) &&
IsBundleSlave(newOffer, level)) {
// It never makes sense to put transport attributes in a bundle-only
// m-section
return false;
}
// TODO(bug 906986): Check for ICE restart (will need to pass the offerer's
// old SDP to compare it against |newOffer|)
return true;
}
nsresult
JsepSessionImpl::AddTransportAttributes(SdpMediaSection* msection,
SdpSetupAttribute::Role dtlsRole)
@ -1886,33 +1920,43 @@ JsepSessionImpl::AddTransportAttributes(SdpMediaSection* msection,
}
nsresult
JsepSessionImpl::CopyTransportParams(const SdpMediaSection& source,
SdpMediaSection* dest)
JsepSessionImpl::CopyTransportParams(const SdpMediaSection& oldLocal,
SdpMediaSection* newLocal)
{
// Copy over m-section details
dest->SetPort(source.GetPort());
dest->GetConnection() = source.GetConnection();
newLocal->SetPort(oldLocal.GetPort());
newLocal->GetConnection() = oldLocal.GetConnection();
auto& sourceAttrs = source.GetAttributeList();
auto& destAttrs = dest->GetAttributeList();
const SdpAttributeList& oldLocalAttrs = oldLocal.GetAttributeList();
SdpAttributeList& newLocalAttrs = newLocal->GetAttributeList();
// If newLocal is an offer, this will be the number of components we used
// last time, and if it is an answer, this will be the number of components
// we know we're using now.
size_t components = mTransports[oldLocal.GetLevel()]->mComponents;
// Now we copy over attributes that won't be added by the usual logic
if (sourceAttrs.HasAttribute(SdpAttribute::kCandidateAttribute)) {
auto* candidateAttrs =
new SdpMultiStringAttribute(SdpAttribute::kCandidateAttribute);
candidateAttrs->mValues = sourceAttrs.GetCandidate();
destAttrs.SetAttribute(candidateAttrs);
if (oldLocalAttrs.HasAttribute(SdpAttribute::kCandidateAttribute) &&
components) {
UniquePtr<SdpMultiStringAttribute> candidateAttrs(
new SdpMultiStringAttribute(SdpAttribute::kCandidateAttribute));
for (const std::string& candidate : oldLocalAttrs.GetCandidate()) {
size_t component;
nsresult rv = GetComponent(candidate, &component);
NS_ENSURE_SUCCESS(rv, rv);
if (components >= component) {
candidateAttrs->mValues.push_back(candidate);
}
}
if (candidateAttrs->mValues.size()) {
newLocalAttrs.SetAttribute(candidateAttrs.release());
}
}
if (sourceAttrs.HasAttribute(SdpAttribute::kEndOfCandidatesAttribute)) {
destAttrs.SetAttribute(
new SdpFlagAttribute(SdpAttribute::kEndOfCandidatesAttribute));
}
if (!destAttrs.HasAttribute(SdpAttribute::kRtcpMuxAttribute) &&
sourceAttrs.HasAttribute(SdpAttribute::kRtcpAttribute)) {
// copy rtcp attribute
destAttrs.SetAttribute(new SdpRtcpAttribute(sourceAttrs.GetRtcp()));
if (components == 2 &&
oldLocalAttrs.HasAttribute(SdpAttribute::kRtcpAttribute)) {
// copy rtcp attribute if we had one that we are using
newLocalAttrs.SetAttribute(new SdpRtcpAttribute(oldLocalAttrs.GetRtcp()));
}
return NS_OK;
@ -2075,6 +2119,7 @@ JsepSessionImpl::SetRemoteDescriptionAnswer(JsepSdpType type,
mCurrentRemoteDescription = Move(mPendingRemoteDescription);
mCurrentLocalDescription = Move(mPendingLocalDescription);
mWasOffererLastTime = mIsOfferer;
SetState(kJsepStateStable);
return NS_OK;
@ -2567,6 +2612,21 @@ JsepSessionImpl::AddCandidateToSdp(Sdp* sdp,
return NS_OK;
}
// TODO(bug 1142105): Move this into an SDP helper class. Ideally, we'd like
// to have real parse code and a useful representation of candidate attrs.
nsresult
JsepSessionImpl::GetComponent(const std::string& candidate, size_t* component)
{
unsigned int temp;
int32_t result = PR_sscanf(candidate.c_str(), "%*s %u", &temp);
if (result == 1) {
*component = temp;
return NS_OK;
}
JSEP_SET_ERROR("Malformed local ICE candidate: " << candidate);
return NS_ERROR_INVALID_ARG;
}
nsresult
JsepSessionImpl::AddRemoteIceCandidate(const std::string& candidate,
const std::string& mid,
@ -2636,6 +2696,7 @@ static void SetDefaultAddresses(const std::string& defaultCandidateAddr,
{
msection->GetConnection().SetAddress(defaultCandidateAddr);
msection->SetPort(defaultCandidatePort);
if (!defaultRtcpCandidateAddr.empty()) {
sdp::AddrType ipVersion = sdp::kIPv4;
if (defaultRtcpCandidateAddr.find(':') != std::string::npos) {
@ -2669,17 +2730,30 @@ JsepSessionImpl::EndOfLocalCandidates(const std::string& defaultCandidateAddr,
return NS_ERROR_UNEXPECTED;
}
std::set<std::string> bundleMids;
const SdpMediaSection* bundleMsection;
nsresult rv = GetNegotiatedBundleInfo(&bundleMids, &bundleMsection);
if (NS_FAILED(rv)) {
MOZ_ASSERT(false);
mLastError += " (This should have been caught sooner!)";
return NS_ERROR_FAILURE;
if (level >= sdp->GetMediaSectionCount()) {
return NS_OK;
}
if (level < sdp->GetMediaSectionCount()) {
SdpMediaSection& msection = sdp->GetMediaSection(level);
std::string defaultRtcpCandidateAddrCopy(defaultRtcpCandidateAddr);
if (mState == kJsepStateStable && mTransports[level]->mComponents == 1) {
// We know we're doing rtcp-mux by now. Don't create an rtcp attr.
defaultRtcpCandidateAddrCopy = "";
defaultRtcpCandidatePort = 0;
}
SdpMediaSection& msection = sdp->GetMediaSection(level);
if (mState == kJsepStateStable) {
// offer/answer is done. Do we actually incorporate these defaults?
const Sdp* answer(GetAnswer());
std::set<std::string> bundleMids;
const SdpMediaSection* bundleMsection;
nsresult rv = GetBundleInfo(*answer, &bundleMids, &bundleMsection);
if (NS_FAILED(rv)) {
MOZ_ASSERT(false);
mLastError += " (This should have been caught sooner!)";
return NS_ERROR_FAILURE;
}
if (msection.GetAttributeList().HasAttribute(SdpAttribute::kMidAttribute) &&
bundleMids.count(msection.GetAttributeList().GetMid())) {
@ -2698,26 +2772,26 @@ JsepSessionImpl::EndOfLocalCandidates(const std::string& defaultCandidateAddr,
}
SetDefaultAddresses(defaultCandidateAddr,
defaultCandidatePort,
defaultRtcpCandidateAddr,
defaultRtcpCandidateAddrCopy,
defaultRtcpCandidatePort,
bundledMsection);
}
}
}
SetDefaultAddresses(defaultCandidateAddr,
defaultCandidatePort,
defaultRtcpCandidateAddr,
defaultRtcpCandidatePort,
&msection);
SetDefaultAddresses(defaultCandidateAddr,
defaultCandidatePort,
defaultRtcpCandidateAddrCopy,
defaultRtcpCandidatePort,
&msection);
// TODO(bug 1095793): Will this have an mid someday?
// TODO(bug 1095793): Will this have an mid someday?
SdpAttributeList& attrs = msection.GetAttributeList();
attrs.SetAttribute(
new SdpFlagAttribute(SdpAttribute::kEndOfCandidatesAttribute));
if (!mIsOfferer) {
attrs.RemoveAttribute(SdpAttribute::kIceOptionsAttribute);
}
SdpAttributeList& attrs = msection.GetAttributeList();
attrs.SetAttribute(
new SdpFlagAttribute(SdpAttribute::kEndOfCandidatesAttribute));
if (!mIsOfferer) {
attrs.RemoveAttribute(SdpAttribute::kIceOptionsAttribute);
}
return NS_OK;
@ -3039,10 +3113,8 @@ JsepSessionImpl::MsectionIsDisabled(const SdpMediaSection& msection) const
const Sdp*
JsepSessionImpl::GetAnswer() const
{
MOZ_ASSERT(mState == kJsepStateStable);
return mIsOfferer ? mCurrentRemoteDescription.get()
: mCurrentLocalDescription.get();
return mWasOffererLastTime ? mCurrentRemoteDescription.get()
: mCurrentLocalDescription.get();
}
nsresult

Просмотреть файл

@ -32,6 +32,7 @@ public:
JsepSessionImpl(const std::string& name, UniquePtr<JsepUuidGenerator> uuidgen)
: JsepSession(name),
mIsOfferer(false),
mWasOffererLastTime(false),
mIceControlling(false),
mRemoteIsIceLite(false),
mSessionId(0),
@ -240,7 +241,7 @@ private:
const Sdp& oldAnswer,
Sdp* newSdp);
void SetupBundle(Sdp* sdp) const;
nsresult FinalizeTransportAttributes(Sdp* sdp);
nsresult SetupTransportAttributes(const Sdp& newOffer, Sdp* local);
void SetupMsidSemantic(const std::vector<std::string>& msids, Sdp* sdp) const;
nsresult GetIdsFromMsid(const Sdp& sdp,
const SdpMediaSection& msection,
@ -286,11 +287,15 @@ private:
nsresult FinalizeTransport(const SdpAttributeList& remote,
const SdpAttributeList& answer,
const RefPtr<JsepTransport>& transport);
bool AreOldTransportParamsValid(const Sdp& oldAnswer,
const Sdp& newOffer,
size_t level);
nsresult AddCandidateToSdp(Sdp* sdp,
const std::string& candidate,
const std::string& mid,
uint16_t level);
nsresult GetComponent(const std::string& candidate, size_t* component);
SdpMediaSection* FindMsectionByMid(Sdp& sdp,
const std::string& mid) const;
@ -330,6 +335,7 @@ private:
std::vector<JsepTrackPair> mNegotiatedTrackPairs;
bool mIsOfferer;
bool mWasOffererLastTime;
bool mIceControlling;
std::string mIceUfrag;
std::string mIcePwd;

Просмотреть файл

@ -31,27 +31,8 @@
#include "mtransport_test_utils.h"
namespace mozilla {
static const char* kCandidates[] = {
"0 1 UDP 9999 192.168.0.1 2000 typ host",
"0 1 UDP 9999 192.168.0.1 2001 typ host",
"0 1 UDP 9999 192.168.0.2 2002 typ srflx raddr 10.252.34.97 rport 53594",
// Mix up order
"0 1 UDP 9999 192.168.1.2 2012 typ srflx raddr 10.252.34.97 rport 53595",
"0 1 UDP 9999 192.168.1.1 2010 typ host",
"0 1 UDP 9999 192.168.1.1 2011 typ host"
};
static const char* kRtcpCandidates[] = {
"0 2 UDP 9999 192.168.0.1 3000 typ host",
"0 2 UDP 9999 192.168.0.1 3001 typ host",
"0 2 UDP 9999 192.168.0.2 3002 typ srflx raddr 10.252.34.97 rport 53596",
// Mix up order
"0 2 UDP 9999 192.168.1.2 3012 typ srflx raddr 10.252.34.97 rport 53597",
"0 2 UDP 9999 192.168.1.1 3010 typ host",
"0 2 UDP 9999 192.168.1.1 3011 typ host"
};
static std::string kAEqualsCandidate("a=candidate:");
const static size_t kNumCandidatesPerComponent = 3;
class JsepSessionTestBase : public ::testing::Test
{
@ -372,8 +353,7 @@ protected:
}
UniquePtr<Sdp> GetParsedLocalDescription(const JsepSessionImpl& side) const {
SipccSdpParser parser;
return mozilla::Move(parser.Parse(side.GetLocalDescription()));
return Parse(side.GetLocalDescription());
}
SdpMediaSection* GetMsection(Sdp& sdp,
@ -591,62 +571,203 @@ protected:
DumpTrackPairs(mSessionAns);
}
void
GatherCandidates(JsepSession& session)
{
bool skipped;
for (size_t i = 0; i < 3; ++i) {
session.AddLocalIceCandidate(
kAEqualsCandidate + kCandidates[i], "", 0, &skipped);
session.AddLocalIceCandidate(
kAEqualsCandidate + kRtcpCandidates[i], "", 0, &skipped);
}
session.EndOfLocalCandidates("192.168.0.2", 2002, "192.168.0.2", 3002, 0);
typedef enum {
RTP = 1,
RTCP = 2
} ComponentType;
for (size_t i = 3; i < 6; ++i) {
session.AddLocalIceCandidate(
kAEqualsCandidate + kCandidates[i], "", 1, &skipped);
session.AddLocalIceCandidate(
kAEqualsCandidate + kRtcpCandidates[i], "", 1, &skipped);
}
session.EndOfLocalCandidates("192.168.1.2", 2012, "192.168.1.2", 3012, 1);
class CandidateSet {
public:
CandidateSet() {}
std::cerr << "local SDP after candidates: "
<< session.GetLocalDescription();
}
void Gather(JsepSession& session,
const std::vector<SdpMediaSection::MediaType>& types,
ComponentType maxComponent = RTCP)
{
for (size_t level = 0; level < types.size(); ++level) {
Gather(session, level, RTP);
if (types[level] != SdpMediaSection::kApplication &&
maxComponent == RTCP) {
Gather(session, level, RTCP);
}
}
FinishGathering(session);
}
void
TrickleCandidates(JsepSession& session)
{
for (size_t i = 0; i < 3; ++i) {
session.AddRemoteIceCandidate(
kAEqualsCandidate + kCandidates[i], "", 0);
session.AddRemoteIceCandidate(
kAEqualsCandidate + kRtcpCandidates[i], "", 0);
}
void Gather(JsepSession& session, size_t level, ComponentType component)
{
static uint16_t port = 1000;
std::vector<std::string> candidates;
for (size_t i = 0; i < kNumCandidatesPerComponent; ++i) {
++port;
std::ostringstream candidate;
candidate << "0 " << static_cast<uint16_t>(component)
<< " UDP 9999 192.168.0.1 " << port << " typ host";
bool skipped;
session.AddLocalIceCandidate(kAEqualsCandidate + candidate.str(),
"", level, &skipped);
if (!skipped) {
mCandidatesToTrickle.push_back(
std::pair<uint16_t, std::string>(
level, kAEqualsCandidate + candidate.str()));
candidates.push_back(candidate.str());
}
}
for (size_t i = 3; i < 6; ++i) {
session.AddRemoteIceCandidate(
kAEqualsCandidate + kCandidates[i], "", 1);
session.AddRemoteIceCandidate(
kAEqualsCandidate + kRtcpCandidates[i], "", 1);
}
// Stomp existing candidates
mCandidates[level][component] = candidates;
std::cerr << "remote SDP after candidates: "
<< session.GetRemoteDescription();
}
// Stomp existing defaults
mDefaultCandidates[level][component] =
std::make_pair("192.168.0.1", port);
}
void
GatherOffererCandidates()
{
GatherCandidates(mSessionOff);
}
void FinishGathering(JsepSession& session) const
{
// Copy so we can be terse and use []
for (auto levelAndCandidates : mDefaultCandidates) {
ASSERT_EQ(1U, levelAndCandidates.second.count(RTP));
session.EndOfLocalCandidates(
levelAndCandidates.second[RTP].first,
levelAndCandidates.second[RTP].second,
// Will be empty string if not present, which is how we indicate
// that there is no default for RTCP
levelAndCandidates.second[RTCP].first,
levelAndCandidates.second[RTCP].second,
levelAndCandidates.first);
}
}
void
TrickleOffererCandidates()
{
TrickleCandidates(mSessionAns);
}
void Trickle(JsepSession& session)
{
for (const auto& levelAndCandidate : mCandidatesToTrickle) {
session.AddRemoteIceCandidate(levelAndCandidate.second,
"",
levelAndCandidate.first);
}
mCandidatesToTrickle.clear();
}
void CheckRtpCandidates(bool expectRtpCandidates,
const SdpMediaSection& msection,
size_t transportLevel,
const std::string& context) const
{
auto& attrs = msection.GetAttributeList();
ASSERT_EQ(expectRtpCandidates,
attrs.HasAttribute(SdpAttribute::kCandidateAttribute))
<< context << " (level " << msection.GetLevel() << ")";
if (expectRtpCandidates) {
// Copy so we can be terse and use []
auto expectedCandidates = mCandidates;
ASSERT_LE(kNumCandidatesPerComponent,
expectedCandidates[transportLevel][RTP].size());
auto& candidates = attrs.GetCandidate();
ASSERT_LE(kNumCandidatesPerComponent, candidates.size())
<< context << " (level " << msection.GetLevel() << ")";
for (size_t i = 0; i < kNumCandidatesPerComponent; ++i) {
ASSERT_EQ(expectedCandidates[transportLevel][RTP][i], candidates[i])
<< context << " (level " << msection.GetLevel() << ")";
}
}
}
void CheckRtcpCandidates(bool expectRtcpCandidates,
const SdpMediaSection& msection,
size_t transportLevel,
const std::string& context) const
{
auto& attrs = msection.GetAttributeList();
if (expectRtcpCandidates) {
// Copy so we can be terse and use []
auto expectedCandidates = mCandidates;
ASSERT_LE(kNumCandidatesPerComponent,
expectedCandidates[transportLevel][RTCP].size());
ASSERT_TRUE(attrs.HasAttribute(SdpAttribute::kCandidateAttribute))
<< context << " (level " << msection.GetLevel() << ")";
auto& candidates = attrs.GetCandidate();
ASSERT_EQ(kNumCandidatesPerComponent * 2, candidates.size())
<< context << " (level " << msection.GetLevel() << ")";
for (size_t i = 0; i < kNumCandidatesPerComponent; ++i) {
ASSERT_EQ(expectedCandidates[transportLevel][RTCP][i],
candidates[i + kNumCandidatesPerComponent])
<< context << " (level " << msection.GetLevel() << ")";
}
}
}
void CheckDefaultRtpCandidate(bool expectDefault,
const SdpMediaSection& msection,
size_t transportLevel,
const std::string& context) const
{
if (expectDefault) {
// Copy so we can be terse and use []
auto defaultCandidates = mDefaultCandidates;
ASSERT_EQ(defaultCandidates[transportLevel][RTP].first,
msection.GetConnection().GetAddress())
<< context << " (level " << msection.GetLevel() << ")";
ASSERT_EQ(defaultCandidates[transportLevel][RTP].second,
msection.GetPort())
<< context << " (level " << msection.GetLevel() << ")";
} else {
ASSERT_EQ("0.0.0.0", msection.GetConnection().GetAddress())
<< context << " (level " << msection.GetLevel() << ")";
ASSERT_EQ(9U, msection.GetPort())
<< context << " (level " << msection.GetLevel() << ")";
}
}
void CheckDefaultRtcpCandidate(bool expectDefault,
const SdpMediaSection& msection,
size_t transportLevel,
const std::string& context) const
{
if (expectDefault) {
// Copy so we can be terse and use []
auto defaultCandidates = mDefaultCandidates;
ASSERT_TRUE(msection.GetAttributeList().HasAttribute(
SdpAttribute::kRtcpAttribute))
<< context << " (level " << msection.GetLevel() << ")";
auto& rtcpAttr = msection.GetAttributeList().GetRtcp();
ASSERT_EQ(defaultCandidates[transportLevel][RTCP].second,
rtcpAttr.mPort)
<< context << " (level " << msection.GetLevel() << ")";
ASSERT_EQ(sdp::kInternet, rtcpAttr.mNetType)
<< context << " (level " << msection.GetLevel() << ")";
ASSERT_EQ(sdp::kIPv4, rtcpAttr.mAddrType)
<< context << " (level " << msection.GetLevel() << ")";
ASSERT_EQ(defaultCandidates[transportLevel][RTCP].first,
rtcpAttr.mAddress)
<< context << " (level " << msection.GetLevel() << ")";
} else {
ASSERT_FALSE(msection.GetAttributeList().HasAttribute(
SdpAttribute::kRtcpAttribute))
<< context << " (level " << msection.GetLevel() << ")";
}
}
private:
typedef size_t Level;
typedef std::string Candidate;
typedef std::string Address;
typedef uint16_t Port;
// Default candidates are put into the m-line, c-line, and rtcp
// attribute for endpoints that don't support ICE.
std::map<Level,
std::map<ComponentType,
std::pair<Address, Port>>> mDefaultCandidates;
std::map<Level,
std::map<ComponentType,
std::vector<Candidate>>> mCandidates;
// Level/candidate pairs that need to be trickled
std::vector<std::pair<Level, Candidate>> mCandidatesToTrickle;
};
// For streaming parse errors
std::string
@ -661,85 +782,19 @@ protected:
return output.str();
}
void
ValidateCandidates(JsepSession& session, bool local)
void CheckEndOfCandidates(bool expectEoc,
const SdpMediaSection& msection,
const std::string& context)
{
std::string sdp =
local ? session.GetLocalDescription() : session.GetRemoteDescription();
SipccSdpParser parser;
UniquePtr<Sdp> parsed = parser.Parse(sdp);
ASSERT_TRUE(!!parsed) << "Parse failed on " << std::endl << sdp << std::endl
<< "Errors were: " << GetParseErrors(parser);
ASSERT_LT(0U, parsed->GetMediaSectionCount());
auto& msection_0 = parsed->GetMediaSection(0);
// We should not be doing things like setting the c-line on remote SDP
if (local) {
ASSERT_EQ("192.168.0.2", msection_0.GetConnection().GetAddress());
ASSERT_EQ(2002U, msection_0.GetPort());
ASSERT_TRUE(msection_0.GetAttributeList().HasAttribute(
SdpAttribute::kRtcpAttribute));
auto& rtcpAttr = msection_0.GetAttributeList().GetRtcp();
ASSERT_EQ(3002U, rtcpAttr.mPort);
ASSERT_EQ(sdp::kInternet, rtcpAttr.mNetType);
ASSERT_EQ(sdp::kIPv4, rtcpAttr.mAddrType);
ASSERT_EQ("192.168.0.2", rtcpAttr.mAddress);
ASSERT_TRUE(msection_0.GetAttributeList().HasAttribute(
SdpAttribute::kEndOfCandidatesAttribute));
if (expectEoc) {
ASSERT_TRUE(msection.GetAttributeList().HasAttribute(
SdpAttribute::kEndOfCandidatesAttribute))
<< context << " (level " << msection.GetLevel() << ")";
} else {
ASSERT_FALSE(msection.GetAttributeList().HasAttribute(
SdpAttribute::kEndOfCandidatesAttribute))
<< context << " (level " << msection.GetLevel() << ")";
}
auto& attrs_0 = msection_0.GetAttributeList();
ASSERT_TRUE(attrs_0.HasAttribute(SdpAttribute::kCandidateAttribute));
auto& candidates_0 = attrs_0.GetCandidate();
ASSERT_EQ(6U, candidates_0.size());
ASSERT_EQ(kCandidates[0], candidates_0[0]);
ASSERT_EQ(kRtcpCandidates[0], candidates_0[1]);
ASSERT_EQ(kCandidates[1], candidates_0[2]);
ASSERT_EQ(kRtcpCandidates[1], candidates_0[3]);
ASSERT_EQ(kCandidates[2], candidates_0[4]);
ASSERT_EQ(kRtcpCandidates[2], candidates_0[5]);
if (parsed->GetMediaSectionCount() > 1) {
auto& msection_1 = parsed->GetMediaSection(1);
if (local) {
ASSERT_EQ("192.168.1.2", msection_1.GetConnection().GetAddress());
ASSERT_EQ(2012U, msection_1.GetPort());
auto& rtcpAttr = msection_1.GetAttributeList().GetRtcp();
ASSERT_EQ(3012U, rtcpAttr.mPort);
ASSERT_EQ(sdp::kInternet, rtcpAttr.mNetType);
ASSERT_EQ(sdp::kIPv4, rtcpAttr.mAddrType);
ASSERT_EQ("192.168.1.2", rtcpAttr.mAddress);
ASSERT_TRUE(msection_0.GetAttributeList().HasAttribute(
SdpAttribute::kEndOfCandidatesAttribute));
}
auto& attrs_1 = msection_1.GetAttributeList();
ASSERT_TRUE(attrs_1.HasAttribute(SdpAttribute::kCandidateAttribute));
auto& candidates_1 = attrs_1.GetCandidate();
ASSERT_EQ(6U, candidates_1.size());
ASSERT_EQ(kCandidates[3], candidates_1[0]);
ASSERT_EQ(kRtcpCandidates[3], candidates_1[1]);
ASSERT_EQ(kCandidates[4], candidates_1[2]);
ASSERT_EQ(kRtcpCandidates[4], candidates_1[3]);
ASSERT_EQ(kCandidates[5], candidates_1[4]);
ASSERT_EQ(kRtcpCandidates[5], candidates_1[5]);
}
}
void
ValidateOffererCandidates()
{
ValidateCandidates(mSessionOff, true);
}
void
ValidateAnswererCandidates()
{
ValidateCandidates(mSessionAns, false);
}
void
@ -758,8 +813,7 @@ protected:
void
DisableMsection(std::string* sdp, size_t level) const {
SipccSdpParser parser;
UniquePtr<Sdp> parsed = parser.Parse(*sdp);
UniquePtr<Sdp> parsed(Parse(*sdp));
ASSERT_TRUE(parsed.get());
ASSERT_LT(level, parsed->GetMediaSectionCount());
parsed->GetMediaSection(level).SetPort(0);
@ -813,18 +867,29 @@ protected:
}
}
UniquePtr<Sdp>
Parse(const std::string& sdp) const
{
SipccSdpParser parser;
UniquePtr<Sdp> parsed = parser.Parse(sdp);
EXPECT_TRUE(parsed.get()) << "Should have valid SDP" << std::endl
<< "Errors were: " << GetParseErrors(parser);
return parsed;
}
JsepSessionImpl mSessionOff;
CandidateSet mOffCandidates;
JsepSessionImpl mSessionAns;
CandidateSet mAnsCandidates;
std::vector<SdpMediaSection::MediaType> types;
std::vector<std::pair<std::string, uint16_t>> mGatheredCandidates;
private:
void
ValidateTransport(TransportData& source, const std::string& sdp_str)
{
SipccSdpParser parser;
auto sdp = parser.Parse(sdp_str);
ASSERT_TRUE(!!sdp) << "Should have valid SDP" << std::endl
<< "Errors were: " << GetParseErrors(parser);
UniquePtr<Sdp> sdp(Parse(sdp_str));
ASSERT_TRUE(!!sdp);
size_t num_m_sections = sdp->GetMediaSectionCount();
for (size_t i = 0; i < num_m_sections; ++i) {
auto& msection = sdp->GetMediaSection(i);
@ -1993,17 +2058,289 @@ TEST_P(JsepSessionTest, FullCallWithCandidates)
AddTracks(mSessionOff);
std::string offer = CreateOffer();
SetLocalOffer(offer);
GatherOffererCandidates();
ValidateOffererCandidates();
mOffCandidates.Gather(mSessionOff, types);
UniquePtr<Sdp> localOffer(Parse(mSessionOff.GetLocalDescription()));
for (size_t i = 0; i < localOffer->GetMediaSectionCount(); ++i) {
mOffCandidates.CheckRtpCandidates(
true, localOffer->GetMediaSection(i), i,
"Local offer after gathering should have RTP candidates.");
mOffCandidates.CheckDefaultRtpCandidate(
true, localOffer->GetMediaSection(i), i,
"Local offer after gathering should have a default RTP candidate.");
mOffCandidates.CheckRtcpCandidates(
types[i] != SdpMediaSection::kApplication,
localOffer->GetMediaSection(i), i,
"Local offer after gathering should have RTCP candidates "
"(unless m=application)");
mOffCandidates.CheckDefaultRtcpCandidate(
types[i] != SdpMediaSection::kApplication,
localOffer->GetMediaSection(i), i,
"Local offer after gathering should have a default RTCP candidate "
"(unless m=application)");
CheckEndOfCandidates(true, localOffer->GetMediaSection(i),
"Local offer after gathering should have an end-of-candidates.");
}
SetRemoteOffer(offer);
TrickleOffererCandidates();
ValidateAnswererCandidates();
mOffCandidates.Trickle(mSessionAns);
UniquePtr<Sdp> remoteOffer(Parse(mSessionAns.GetRemoteDescription()));
for (size_t i = 0; i < remoteOffer->GetMediaSectionCount(); ++i) {
mOffCandidates.CheckRtpCandidates(
true, remoteOffer->GetMediaSection(i), i,
"Remote offer after trickle should have RTP candidates.");
mOffCandidates.CheckDefaultRtpCandidate(
false, remoteOffer->GetMediaSection(i), i,
"Initial remote offer should not have a default RTP candidate.");
mOffCandidates.CheckRtcpCandidates(
types[i] != SdpMediaSection::kApplication,
remoteOffer->GetMediaSection(i), i,
"Remote offer after trickle should have RTCP candidates "
"(unless m=application)");
mOffCandidates.CheckDefaultRtcpCandidate(
false, remoteOffer->GetMediaSection(i), i,
"Initial remote offer should not have a default RTCP candidate.");
CheckEndOfCandidates(false, remoteOffer->GetMediaSection(i),
"Initial remote offer should not have an end-of-candidates.");
}
AddTracks(mSessionAns);
std::string answer = CreateAnswer();
SetLocalAnswer(answer);
// This will gather candidates that mSessionAns knows it doesn't need.
// They should not be present in the SDP.
mAnsCandidates.Gather(mSessionAns, types);
UniquePtr<Sdp> localAnswer(Parse(mSessionAns.GetLocalDescription()));
for (size_t i = 0; i < localAnswer->GetMediaSectionCount(); ++i) {
mAnsCandidates.CheckRtpCandidates(
i == 0, localAnswer->GetMediaSection(i), i,
"Local answer after gathering should have RTP candidates on level 0.");
mAnsCandidates.CheckDefaultRtpCandidate(
true, localAnswer->GetMediaSection(i), 0,
"Local answer after gathering should have a default RTP candidate "
"on all levels that matches transport level 0.");
mAnsCandidates.CheckRtcpCandidates(
false, localAnswer->GetMediaSection(i), i,
"Local answer after gathering should not have RTCP candidates "
"(because we're answering with rtcp-mux)");
mAnsCandidates.CheckDefaultRtcpCandidate(
false, localAnswer->GetMediaSection(i), i,
"Local answer after gathering should not have a default RTCP candidate "
"(because we're answering with rtcp-mux)");
CheckEndOfCandidates(i == 0, localAnswer->GetMediaSection(i),
"Local answer after gathering should have an end-of-candidates only for"
" level 0.");
}
SetRemoteAnswer(answer);
mAnsCandidates.Trickle(mSessionOff);
UniquePtr<Sdp> remoteAnswer(Parse(mSessionOff.GetRemoteDescription()));
for (size_t i = 0; i < remoteAnswer->GetMediaSectionCount(); ++i) {
mAnsCandidates.CheckRtpCandidates(
i == 0, remoteAnswer->GetMediaSection(i), i,
"Remote answer after trickle should have RTP candidates on level 0.");
mAnsCandidates.CheckDefaultRtpCandidate(
false, remoteAnswer->GetMediaSection(i), i,
"Remote answer after trickle should not have a default RTP candidate.");
mAnsCandidates.CheckRtcpCandidates(
false, remoteAnswer->GetMediaSection(i), i,
"Remote answer after trickle should not have RTCP candidates "
"(because we're answering with rtcp-mux)");
mAnsCandidates.CheckDefaultRtcpCandidate(
false, remoteAnswer->GetMediaSection(i), i,
"Remote answer after trickle should not have a default RTCP "
"candidate.");
CheckEndOfCandidates(false, remoteAnswer->GetMediaSection(i),
"Remote answer after trickle should not have an end-of-candidates.");
}
}
TEST_P(JsepSessionTest, RenegotiationWithCandidates)
{
AddTracks(mSessionOff);
std::string offer = CreateOffer();
SetLocalOffer(offer);
mOffCandidates.Gather(mSessionOff, types);
SetRemoteOffer(offer);
mOffCandidates.Trickle(mSessionAns);
AddTracks(mSessionAns);
std::string answer = CreateAnswer();
SetLocalAnswer(answer);
mAnsCandidates.Gather(mSessionAns, types);
SetRemoteAnswer(answer);
mAnsCandidates.Trickle(mSessionOff);
offer = CreateOffer();
SetLocalOffer(offer);
UniquePtr<Sdp> parsedOffer(Parse(offer));
for (size_t i = 0; i < parsedOffer->GetMediaSectionCount(); ++i) {
mOffCandidates.CheckRtpCandidates(
i == 0, parsedOffer->GetMediaSection(i), i,
"Local reoffer before gathering should have RTP candidates on level 0"
" only.");
mOffCandidates.CheckDefaultRtpCandidate(
i == 0, parsedOffer->GetMediaSection(i), 0,
"Local reoffer before gathering should have a default RTP candidate "
"on level 0 only.");
mOffCandidates.CheckRtcpCandidates(
false, parsedOffer->GetMediaSection(i), i,
"Local reoffer before gathering should not have RTCP candidates.");
mOffCandidates.CheckDefaultRtcpCandidate(
false, parsedOffer->GetMediaSection(i), i,
"Local reoffer before gathering should not have a default RTCP "
"candidate.");
CheckEndOfCandidates(false, parsedOffer->GetMediaSection(i),
"Local reoffer before gathering should not have an end-of-candidates.");
}
// mSessionAns should generate a reoffer that is similar
std::string otherOffer;
JsepOfferOptions defaultOptions;
nsresult rv = mSessionAns.CreateOffer(defaultOptions, &otherOffer);
ASSERT_EQ(NS_OK, rv);
parsedOffer = Parse(otherOffer);
for (size_t i = 0; i < parsedOffer->GetMediaSectionCount(); ++i) {
mAnsCandidates.CheckRtpCandidates(
i == 0, parsedOffer->GetMediaSection(i), i,
"Local reoffer before gathering should have RTP candidates on level 0"
" only. (previous answerer)");
mAnsCandidates.CheckDefaultRtpCandidate(
i == 0, parsedOffer->GetMediaSection(i), 0,
"Local reoffer before gathering should have a default RTP candidate "
"on level 0 only. (previous answerer)");
mAnsCandidates.CheckRtcpCandidates(
false, parsedOffer->GetMediaSection(i), i,
"Local reoffer before gathering should not have RTCP candidates."
" (previous answerer)");
mAnsCandidates.CheckDefaultRtcpCandidate(
false, parsedOffer->GetMediaSection(i), i,
"Local reoffer before gathering should not have a default RTCP "
"candidate. (previous answerer)");
CheckEndOfCandidates(false, parsedOffer->GetMediaSection(i),
"Local reoffer before gathering should not have an end-of-candidates. "
"(previous answerer)");
}
// Ok, let's continue with the renegotiation
SetRemoteOffer(offer);
// PeerConnection will not re-gather for RTP, but it will for RTCP in case
// the answerer decides to turn off rtcp-mux.
if (types[0] != SdpMediaSection::kApplication) {
mOffCandidates.Gather(mSessionOff, 0, RTCP);
}
// Since the remaining levels were bundled, PeerConnection will re-gather for
// both RTP and RTCP, in case the answerer rejects bundle.
for (size_t level = 1; level < types.size(); ++level) {
mOffCandidates.Gather(mSessionOff, level, RTP);
if (types[level] != SdpMediaSection::kApplication) {
mOffCandidates.Gather(mSessionOff, level, RTCP);
}
}
mOffCandidates.FinishGathering(mSessionOff);
mOffCandidates.Trickle(mSessionAns);
UniquePtr<Sdp> localOffer(Parse(mSessionOff.GetLocalDescription()));
for (size_t i = 0; i < localOffer->GetMediaSectionCount(); ++i) {
mOffCandidates.CheckRtpCandidates(
true, localOffer->GetMediaSection(i), i,
"Local reoffer after gathering should have RTP candidates.");
mOffCandidates.CheckDefaultRtpCandidate(
true, localOffer->GetMediaSection(i), i,
"Local reoffer after gathering should have a default RTP candidate.");
mOffCandidates.CheckRtcpCandidates(
types[i] != SdpMediaSection::kApplication,
localOffer->GetMediaSection(i), i,
"Local reoffer after gathering should have RTCP candidates "
"(unless m=application)");
mOffCandidates.CheckDefaultRtcpCandidate(
types[i] != SdpMediaSection::kApplication,
localOffer->GetMediaSection(i), i,
"Local reoffer after gathering should have a default RTCP candidate "
"(unless m=application)");
CheckEndOfCandidates(true, localOffer->GetMediaSection(i),
"Local reoffer after gathering should have an end-of-candidates.");
}
UniquePtr<Sdp> remoteOffer(Parse(mSessionAns.GetRemoteDescription()));
for (size_t i = 0; i < remoteOffer->GetMediaSectionCount(); ++i) {
mOffCandidates.CheckRtpCandidates(
true, remoteOffer->GetMediaSection(i), i,
"Remote reoffer after trickle should have RTP candidates.");
mOffCandidates.CheckDefaultRtpCandidate(
i == 0, remoteOffer->GetMediaSection(i), i,
"Remote reoffer should have a default RTP candidate on level 0 "
"(because it was gathered last offer/answer).");
mOffCandidates.CheckRtcpCandidates(
types[i] != SdpMediaSection::kApplication,
remoteOffer->GetMediaSection(i), i,
"Remote reoffer after trickle should have RTCP candidates.");
mOffCandidates.CheckDefaultRtcpCandidate(
false, remoteOffer->GetMediaSection(i), i,
"Remote reoffer should not have a default RTCP candidate.");
CheckEndOfCandidates(false, remoteOffer->GetMediaSection(i),
"Remote reoffer should not have an end-of-candidates.");
}
answer = CreateAnswer();
SetLocalAnswer(answer);
SetRemoteAnswer(answer);
// No candidates should be gathered at the answerer, but default candidates
// should be set.
mAnsCandidates.FinishGathering(mSessionAns);
UniquePtr<Sdp> localAnswer(Parse(mSessionAns.GetLocalDescription()));
for (size_t i = 0; i < localAnswer->GetMediaSectionCount(); ++i) {
mAnsCandidates.CheckRtpCandidates(
i == 0, localAnswer->GetMediaSection(i), i,
"Local reanswer after gathering should have RTP candidates on level "
"0.");
mAnsCandidates.CheckDefaultRtpCandidate(
true, localAnswer->GetMediaSection(i), 0,
"Local reanswer after gathering should have a default RTP candidate "
"on all levels that matches transport level 0.");
mAnsCandidates.CheckRtcpCandidates(
false, localAnswer->GetMediaSection(i), i,
"Local reanswer after gathering should not have RTCP candidates "
"(because we're reanswering with rtcp-mux)");
mAnsCandidates.CheckDefaultRtcpCandidate(
false, localAnswer->GetMediaSection(i), i,
"Local reanswer after gathering should not have a default RTCP "
"candidate (because we're reanswering with rtcp-mux)");
CheckEndOfCandidates(i == 0, localAnswer->GetMediaSection(i),
"Local reanswer after gathering should have an end-of-candidates only "
"for level 0.");
}
UniquePtr<Sdp> remoteAnswer(Parse(mSessionOff.GetRemoteDescription()));
for (size_t i = 0; i < localAnswer->GetMediaSectionCount(); ++i) {
mAnsCandidates.CheckRtpCandidates(
i == 0, remoteAnswer->GetMediaSection(i), i,
"Remote reanswer after trickle should have RTP candidates on level 0.");
mAnsCandidates.CheckDefaultRtpCandidate(
i == 0, remoteAnswer->GetMediaSection(i), i,
"Remote reanswer should have a default RTP candidate on level 0 "
"(because it was gathered last offer/answer).");
mAnsCandidates.CheckRtcpCandidates(
false, remoteAnswer->GetMediaSection(i), i,
"Remote reanswer after trickle should not have RTCP candidates "
"(because we're reanswering with rtcp-mux)");
mAnsCandidates.CheckDefaultRtcpCandidate(
false, remoteAnswer->GetMediaSection(i), i,
"Remote reanswer after trickle should not have a default RTCP "
"candidate.");
CheckEndOfCandidates(false, remoteAnswer->GetMediaSection(i),
"Remote reanswer after trickle should not have an end-of-candidates.");
}
}
INSTANTIATE_TEST_CASE_P(
Variants,
JsepSessionTest,
@ -2039,10 +2376,8 @@ TEST_F(JsepSessionTest, OfferAnswerRecvOnlyLines)
options.mDontOfferDataChannel = Some(true);
std::string offer = CreateOffer(Some(options));
SipccSdpParser parser;
UniquePtr<Sdp> parsedOffer = parser.Parse(offer);
ASSERT_TRUE(!!parsedOffer) << "Should have valid SDP" << std::endl
<< "Errors were: " << GetParseErrors(parser);
UniquePtr<Sdp> parsedOffer(Parse(offer));
ASSERT_TRUE(!!parsedOffer);
ASSERT_EQ(3U, parsedOffer->GetMediaSectionCount());
ASSERT_EQ(SdpMediaSection::kAudio,
@ -2079,7 +2414,7 @@ TEST_F(JsepSessionTest, OfferAnswerRecvOnlyLines)
SetRemoteOffer(offer, CHECK_SUCCESS);
std::string answer = CreateAnswer();
UniquePtr<Sdp> parsedAnswer = parser.Parse(answer);
UniquePtr<Sdp> parsedAnswer(Parse(answer));
ASSERT_EQ(3U, parsedAnswer->GetMediaSectionCount());
ASSERT_EQ(SdpMediaSection::kAudio,
@ -2118,10 +2453,8 @@ TEST_F(JsepSessionTest, OfferAnswerSendOnlyLines)
options.mDontOfferDataChannel = Some(true);
std::string offer = CreateOffer(Some(options));
SipccSdpParser parser;
auto outputSdp = parser.Parse(offer);
ASSERT_TRUE(!!outputSdp) << "Should have valid SDP" << std::endl
<< "Errors were: " << GetParseErrors(parser);
UniquePtr<Sdp> outputSdp(Parse(offer));
ASSERT_TRUE(!!outputSdp);
ASSERT_EQ(3U, outputSdp->GetMediaSectionCount());
ASSERT_EQ(SdpMediaSection::kAudio,
@ -2150,7 +2483,7 @@ TEST_F(JsepSessionTest, OfferAnswerSendOnlyLines)
SetRemoteOffer(offer, CHECK_SUCCESS);
std::string answer = CreateAnswer();
outputSdp = parser.Parse(answer);
outputSdp = Parse(answer);
ASSERT_EQ(3U, outputSdp->GetMediaSectionCount());
ASSERT_EQ(SdpMediaSection::kAudio,
@ -2174,8 +2507,7 @@ TEST_F(JsepSessionTest, OfferToReceiveAudioNotUsed)
OfferAnswer(CHECK_SUCCESS, Some(options));
SipccSdpParser parser;
UniquePtr<Sdp> offer(parser.Parse(mSessionOff.GetLocalDescription()));
UniquePtr<Sdp> offer(Parse(mSessionOff.GetLocalDescription()));
ASSERT_TRUE(offer.get());
ASSERT_EQ(1U, offer->GetMediaSectionCount());
ASSERT_EQ(SdpMediaSection::kAudio,
@ -2183,7 +2515,7 @@ TEST_F(JsepSessionTest, OfferToReceiveAudioNotUsed)
ASSERT_EQ(SdpDirectionAttribute::kRecvonly,
offer->GetMediaSection(0).GetAttributeList().GetDirection());
UniquePtr<Sdp> answer(parser.Parse(mSessionAns.GetLocalDescription()));
UniquePtr<Sdp> answer(Parse(mSessionAns.GetLocalDescription()));
ASSERT_TRUE(answer.get());
ASSERT_EQ(1U, answer->GetMediaSectionCount());
ASSERT_EQ(SdpMediaSection::kAudio,
@ -2199,8 +2531,7 @@ TEST_F(JsepSessionTest, OfferToReceiveVideoNotUsed)
OfferAnswer(CHECK_SUCCESS, Some(options));
SipccSdpParser parser;
UniquePtr<Sdp> offer(parser.Parse(mSessionOff.GetLocalDescription()));
UniquePtr<Sdp> offer(Parse(mSessionOff.GetLocalDescription()));
ASSERT_TRUE(offer.get());
ASSERT_EQ(1U, offer->GetMediaSectionCount());
ASSERT_EQ(SdpMediaSection::kVideo,
@ -2208,7 +2539,7 @@ TEST_F(JsepSessionTest, OfferToReceiveVideoNotUsed)
ASSERT_EQ(SdpDirectionAttribute::kRecvonly,
offer->GetMediaSection(0).GetAttributeList().GetDirection());
UniquePtr<Sdp> answer(parser.Parse(mSessionAns.GetLocalDescription()));
UniquePtr<Sdp> answer(Parse(mSessionAns.GetLocalDescription()));
ASSERT_TRUE(answer.get());
ASSERT_EQ(1U, answer->GetMediaSectionCount());
ASSERT_EQ(SdpMediaSection::kVideo,
@ -2229,10 +2560,8 @@ TEST_F(JsepSessionTest, CreateOfferNoDatachannelDefault)
std::string offer = CreateOffer();
SipccSdpParser parser;
auto outputSdp = parser.Parse(offer);
ASSERT_TRUE(!!outputSdp) << "Should have valid SDP" << std::endl
<< "Errors were: " << GetParseErrors(parser);
UniquePtr<Sdp> outputSdp(Parse(offer));
ASSERT_TRUE(!!outputSdp);
ASSERT_EQ(2U, outputSdp->GetMediaSectionCount());
ASSERT_EQ(SdpMediaSection::kAudio,
@ -2255,10 +2584,8 @@ TEST_F(JsepSessionTest, ValidateOfferedCodecParams)
std::string offer = CreateOffer();
SipccSdpParser parser;
auto outputSdp = parser.Parse(offer);
ASSERT_TRUE(!!outputSdp) << "Should have valid SDP" << std::endl
<< "Errors were: " << GetParseErrors(parser);
UniquePtr<Sdp> outputSdp(Parse(offer));
ASSERT_TRUE(!!outputSdp);
ASSERT_EQ(2U, outputSdp->GetMediaSectionCount());
auto& video_section = outputSdp->GetMediaSection(1);
@ -2389,10 +2716,8 @@ TEST_F(JsepSessionTest, ValidateAnsweredCodecParams)
std::string answer = CreateAnswer();
SipccSdpParser parser;
auto outputSdp = parser.Parse(answer);
ASSERT_TRUE(!!outputSdp) << "Should have valid SDP" << std::endl
<< "Errors were: " << GetParseErrors(parser);
UniquePtr<Sdp> outputSdp(Parse(answer));
ASSERT_TRUE(!!outputSdp);
ASSERT_EQ(2U, outputSdp->GetMediaSectionCount());
auto& video_section = outputSdp->GetMediaSection(1);
@ -2889,10 +3214,8 @@ TEST_P(JsepSessionTest, TestRejectMline)
std::string answer = CreateAnswer();
SipccSdpParser parser;
auto outputSdp = parser.Parse(answer);
ASSERT_TRUE(!!outputSdp) << "Should have valid SDP" << std::endl
<< "Errors were: " << GetParseErrors(parser);
UniquePtr<Sdp> outputSdp(Parse(answer));
ASSERT_TRUE(!!outputSdp);
ASSERT_NE(0U, outputSdp->GetMediaSectionCount());
SdpMediaSection* failed_section = nullptr;
@ -2942,8 +3265,7 @@ TEST_F(JsepSessionTest, TestIceLite)
std::string offer = CreateOffer();
SetLocalOffer(offer, CHECK_SUCCESS);
SipccSdpParser parser;
UniquePtr<Sdp> parsedOffer = parser.Parse(offer);
UniquePtr<Sdp> parsedOffer(Parse(offer));
parsedOffer->GetAttributeList().SetAttribute(
new SdpFlagAttribute(SdpAttribute::kIceLiteAttribute));
@ -2988,8 +3310,7 @@ TEST_F(JsepSessionTest, TestExtmap)
SetLocalAnswer(answer, CHECK_SUCCESS);
SetRemoteAnswer(answer, CHECK_SUCCESS);
SipccSdpParser parser;
UniquePtr<Sdp> parsedOffer = parser.Parse(offer);
UniquePtr<Sdp> parsedOffer(Parse(offer));
ASSERT_EQ(1U, parsedOffer->GetMediaSectionCount());
auto& offerMediaAttrs = parsedOffer->GetMediaSection(0).GetAttributeList();
@ -3004,7 +3325,7 @@ TEST_F(JsepSessionTest, TestExtmap)
ASSERT_EQ("bar", offerExtmap[2].extensionname);
ASSERT_EQ(3U, offerExtmap[2].entry);
UniquePtr<Sdp> parsedAnswer = parser.Parse(answer);
UniquePtr<Sdp> parsedAnswer(Parse(answer));
ASSERT_EQ(1U, parsedAnswer->GetMediaSectionCount());
auto& answerMediaAttrs = parsedAnswer->GetMediaSection(0).GetAttributeList();
@ -3026,8 +3347,7 @@ TEST_F(JsepSessionTest, TestRtcpFbStar)
std::string offer = CreateOffer();
SipccSdpParser parser;
UniquePtr<Sdp> parsedOffer = parser.Parse(offer);
UniquePtr<Sdp> parsedOffer(Parse(offer));
auto* rtcpfbs = new SdpRtcpFbAttributeList;
rtcpfbs->PushEntry("*", SdpRtcpFbAttributeList::kNack);
parsedOffer->GetMediaSection(0).GetAttributeList().SetAttribute(rtcpfbs);

Просмотреть файл

@ -18,7 +18,10 @@ from __future__ import unicode_literals
import os
from collections import OrderedDict
from collections import (
Counter,
OrderedDict,
)
from mozbuild.util import (
HierarchicalStringList,
HierarchicalStringListWithFlagsFactory,
@ -576,6 +579,49 @@ class Files(SubContext):
return d
@staticmethod
def aggregate(files):
"""Given a mapping of path to Files, obtain aggregate results.
Consumers may want to extract useful information from a collection of
Files describing paths. e.g. given the files info data for N paths,
recommend a single bug component based on the most frequent one. This
function provides logic for deriving aggregate knowledge from a
collection of path File metadata.
Note: the intent of this function is to operate on the result of
:py:func:`mozbuild.frontend.reader.BuildReader.files_info`. The
:py:func:`mozbuild.frontend.context.Files` instances passed in are
thus the "collapsed" (``__iadd__``ed) results of all ``Files`` from all
moz.build files relevant to a specific path, not individual ``Files``
instances from a single moz.build file.
"""
d = {}
bug_components = Counter()
for f in files.values():
bug_component = f.get('BUG_COMPONENT')
if bug_component:
bug_components[bug_component] += 1
d['bug_component_counts'] = []
for c, count in bug_components.most_common():
component = (c.product, c.component)
d['bug_component_counts'].append((c, count))
if 'recommended_bug_component' not in d:
d['recommended_bug_component'] = component
recommended_count = count
elif count == recommended_count:
# Don't recommend a component if it doesn't have a clear lead.
d['recommended_bug_component'] = None
# In case no bug components.
d.setdefault('recommended_bug_component', None)
return d
# This defines functions that create sub-contexts.
#

Просмотреть файл

@ -11,6 +11,7 @@ from mozbuild.frontend.context import (
Context,
ContextDerivedTypedList,
ContextDerivedTypedListWithItems,
Files,
FUNCTIONS,
ObjDirPath,
Path,
@ -565,5 +566,64 @@ class TestPaths(unittest.TestCase):
self.assertEqual(l[p_str].foo, True)
self.assertEqual(l[p_path].foo, True)
class TestFiles(unittest.TestCase):
def test_aggregate_empty(self):
c = Context({})
files = {'moz.build': Files(c, pattern='**')}
self.assertEqual(Files.aggregate(files), {
'bug_component_counts': [],
'recommended_bug_component': None,
})
def test_single_bug_component(self):
c = Context({})
f = Files(c, pattern='**')
f['BUG_COMPONENT'] = (u'Product1', u'Component1')
files = {'moz.build': f}
self.assertEqual(Files.aggregate(files), {
'bug_component_counts': [((u'Product1', u'Component1'), 1)],
'recommended_bug_component': (u'Product1', u'Component1'),
})
def test_multiple_bug_components(self):
c = Context({})
f1 = Files(c, pattern='**')
f1['BUG_COMPONENT'] = (u'Product1', u'Component1')
f2 = Files(c, pattern='**')
f2['BUG_COMPONENT'] = (u'Product2', u'Component2')
files = {'a': f1, 'b': f2, 'c': f1}
self.assertEqual(Files.aggregate(files), {
'bug_component_counts': [
((u'Product1', u'Component1'), 2),
((u'Product2', u'Component2'), 1),
],
'recommended_bug_component': (u'Product1', u'Component1'),
})
def test_no_recommended_bug_component(self):
"""If there is no clear count winner, we don't recommend a bug component."""
c = Context({})
f1 = Files(c, pattern='**')
f1['BUG_COMPONENT'] = (u'Product1', u'Component1')
f2 = Files(c, pattern='**')
f2['BUG_COMPONENT'] = (u'Product2', u'Component2')
files = {'a': f1, 'b': f2}
self.assertEqual(Files.aggregate(files), {
'bug_component_counts': [
((u'Product1', u'Component1'), 1),
((u'Product2', u'Component2'), 1),
],
'recommended_bug_component': None,
})
if __name__ == '__main__':
main()

Просмотреть файл

@ -1,15 +1,29 @@
# 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/.
# 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/.
from setuptools import setup
from setuptools import setup, find_packages
VERSION = '0.1'
VERSION = '0.2'
setup(
author='Mozilla Foundation',
author_email='dev-builds@lists.mozilla.org',
name='mozbuild',
description='Mozilla build system functionality.',
license='MPL 2.0',
packages=['mach', 'mozbuild', 'mozpack'],
version=VERSION
packages=find_packages(),
version=VERSION,
install_requires=[
'jsmin',
'mozfile',
],
classifiers=[
'Development Status :: 3 - Alpha',
'Topic :: Software Development :: Build Tools',
'License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: Implementation :: CPython',
],
keywords='mozilla build',
)

Просмотреть файл

@ -462,16 +462,6 @@ CertErrorRunnable::CheckCertOverrides()
mDefaultErrorCodeToReport);
}
nsCOMPtr<nsISSLSocketControl> sslSocketControl = do_QueryInterface(
NS_ISUPPORTS_CAST(nsITransportSecurityInfo*, mInfoObject));
if (sslSocketControl &&
sslSocketControl->GetBypassAuthentication()) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("[%p][%p] Bypass Auth in CheckCertOverrides\n",
mFdForLogging, this));
return new SSLServerCertVerificationResult(mInfoObject, 0);
}
int32_t port;
mInfoObject->GetPort(&port);
@ -580,6 +570,8 @@ CertErrorRunnable::CheckCertOverrides()
// First, deliver the technical details of the broken SSL status.
// Try to get a nsIBadCertListener2 implementation from the socket consumer.
nsCOMPtr<nsISSLSocketControl> sslSocketControl = do_QueryInterface(
NS_ISUPPORTS_CAST(nsITransportSecurityInfo*, mInfoObject));
if (sslSocketControl) {
nsCOMPtr<nsIInterfaceRequestor> cb;
sslSocketControl->GetNotificationCallbacks(getter_AddRefs(cb));
@ -1462,6 +1454,14 @@ AuthCertificateHook(void* arg, PRFileDesc* fd, PRBool checkSig, PRBool isServer)
if (BlockServerCertChangeForSpdy(socketInfo, serverCert) != SECSuccess)
return SECFailure;
nsCOMPtr<nsISSLSocketControl> sslSocketControl = do_QueryInterface(
NS_ISUPPORTS_CAST(nsITransportSecurityInfo*, socketInfo));
if (sslSocketControl && sslSocketControl->GetBypassAuthentication()) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("[%p] Bypass Auth in AuthCertificateHook\n", fd));
return SECSuccess;
}
bool onSTSThread;
nsresult nrv;
nsCOMPtr<nsIEventTarget> sts

Просмотреть файл

@ -86,9 +86,9 @@ class SyncTestCommands(MachCommandBase):
'-r', '%s/components/httpd.manifest' % self.bindir,
'-m',
'-s',
'-e', 'const _TESTING_MODULES_DIR = "%s/_tests/modules";' % topobjdir,
'-f', '%s/testing/xpcshell/head.js' % topsrcdir,
'-e', 'const _SERVER_ADDR = "%s";' % hostname,
'-e', 'const _TESTING_MODULES_DIR = "%s/_tests/modules";' % topobjdir,
'-e', 'const SERVER_PORT = "%s";' % port,
'-e', 'const INCLUDE_FILES = [%s];' % ', '.join(head_paths),
'-e', '_register_protocol_handlers();',

Просмотреть файл

@ -63,7 +63,8 @@ int main(int argc, char** argv)
#if defined(HAVE_LIBXSS) && defined(MOZ_WIDGET_GTK)
int event_base, error_base;
Bool have_xscreensaver =
XScreenSaverQueryExtension(GDK_DISPLAY(), &event_base, &error_base);
XScreenSaverQueryExtension(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()),
&event_base, &error_base);
if (!have_xscreensaver) {
fprintf(stderr, "No XScreenSaver extension on display\n");
@ -73,7 +74,8 @@ int main(int argc, char** argv)
fprintf(stderr, "%s: Out of memory\n", argv[0]);
return 1;
}
XScreenSaverQueryInfo(GDK_DISPLAY(), GDK_ROOT_WINDOW(), info);
XScreenSaverQueryInfo(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()),
GDK_ROOT_WINDOW(), info);
const char* state;
const char* til_or_since = nullptr;

Просмотреть файл

@ -137,8 +137,19 @@ function getTempFile(aLeafName)
do_check_false(file.exists());
do_register_cleanup(function () {
if (file.exists()) {
file.remove(false);
try {
file.remove(false)
} catch (e) {
if (!(e instanceof Components.Exception &&
(e.result == Cr.NS_ERROR_FILE_ACCESS_DENIED ||
e.result == Cr.NS_ERROR_FILE_TARGET_DOES_NOT_EXIST ||
e.result == Cr.NS_ERROR_FILE_NOT_FOUND))) {
throw e;
}
// On Windows, we may get an access denied error if the file existed before,
// and was recently deleted.
// Don't bother checking file.exists() as that may also cause an access
// denied error.
}
});

Просмотреть файл

@ -161,7 +161,7 @@ menulist[editable="true"] > menupopup > menucaption {
-moz-appearance: none;
}
menulist[editable="true"] > menupopup > :moz-any(menuitem, menucaption) > .menu-iconic-left
menulist[editable="true"] > menupopup > :-moz-any(menuitem, menucaption) > .menu-iconic-left {
display: none;
}

Просмотреть файл

@ -239,7 +239,7 @@ menulist > menupopup > menuitem[disabled="true"]:not([_moz-menuactive="true"]):-
text-shadow: none;
}
menulist > menupopup > :moz-any(menuitem, menucaption):not(.menuitem-iconic) > .menu-iconic-text,
menulist > menupopup > :-moz-any(menuitem, menucaption):not(.menuitem-iconic) > .menu-iconic-text {
margin: 0 !important;
}

Просмотреть файл

@ -822,13 +822,13 @@ DrawThemeWithCairo(gfxContext* aContext, DrawTarget* aDrawTarget,
#ifndef MOZ_TREE_CAIRO
// Directly use the Cairo draw target to render the widget if using system Cairo everywhere.
BorrowedCairoContext borrow(aDrawTarget);
if (borrow.mCairo) {
cairo_set_matrix(borrow.mCairo, &mat);
BorrowedCairoContext borrowCairo(aDrawTarget);
if (borrowCairo.mCairo) {
cairo_set_matrix(borrowCairo.mCairo, &mat);
moz_gtk_widget_paint(aGTKWidgetType, borrow.mCairo, &aGDKRect, &aState, aFlags, aDirection);
moz_gtk_widget_paint(aGTKWidgetType, borrowCairo.mCairo, &aGDKRect, &aState, aFlags, aDirection);
borrow.Finish();
borrowCairo.Finish();
return;
}
#endif