diff --git a/accessible/atk/AccessibleWrap.cpp b/accessible/atk/AccessibleWrap.cpp index 6df4f57cc17d..0dd7dfec2013 100644 --- a/accessible/atk/AccessibleWrap.cpp +++ b/accessible/atk/AccessibleWrap.cpp @@ -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); + } } } diff --git a/browser/base/content/browser.xul b/browser/base/content/browser.xul index a2a8161ff2e0..e419ecba3a43 100644 --- a/browser/base/content/browser.xul +++ b/browser/base/content/browser.xul @@ -152,7 +152,11 @@ work correctly on the menupopup. ContentSelectDropdown expects the popuponly menulist to be its immediate parent. --> diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp index 1e2e179c5b17..1b24cb4233d6 100644 --- a/gfx/thebes/gfxWindowsPlatform.cpp +++ b/gfx/thebes/gfxWindowsPlatform.cpp @@ -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 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; } diff --git a/js/src/jit/MacroAssembler-inl.h b/js/src/jit/MacroAssembler-inl.h index 490543e36f89..fb898d8c71ec 100644 --- a/js/src/jit/MacroAssembler-inl.h +++ b/js/src/jit/MacroAssembler-inl.h @@ -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)); } // =============================================================== diff --git a/js/src/jit/MacroAssembler.h b/js/src/jit/MacroAssembler.h index cf57663828af..0fae63acb5df 100644 --- a/js/src/jit/MacroAssembler.h +++ b/js/src/jit/MacroAssembler.h @@ -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 diff --git a/js/src/jit/RangeAnalysis.cpp b/js/src/jit/RangeAnalysis.cpp index 75d3f924c594..955d9ca38600 100644 --- a/js/src/jit/RangeAnalysis.cpp +++ b/js/src/jit/RangeAnalysis.cpp @@ -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; diff --git a/js/src/jsprf.cpp b/js/src/jsprf.cpp index cc2db3246c17..b5bdb7cc3523 100644 --- a/js/src/jsprf.cpp +++ b/js/src/jsprf.cpp @@ -12,6 +12,7 @@ #include "jsprf.h" +#include "mozilla/Snprintf.h" #include "mozilla/Vector.h" #include @@ -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)); } diff --git a/media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp b/media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp index 253ca8cc75ff..e56ac9c54a94 100644 --- a/media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp +++ b/media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp @@ -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 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 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 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 diff --git a/media/webrtc/signaling/src/jsep/JsepSessionImpl.h b/media/webrtc/signaling/src/jsep/JsepSessionImpl.h index a6bfcc2e01b6..12a823dbf0da 100644 --- a/media/webrtc/signaling/src/jsep/JsepSessionImpl.h +++ b/media/webrtc/signaling/src/jsep/JsepSessionImpl.h @@ -32,6 +32,7 @@ public: JsepSessionImpl(const std::string& name, UniquePtr 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& 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& 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 mNegotiatedTrackPairs; bool mIsOfferer; + bool mWasOffererLastTime; bool mIceControlling; std::string mIceUfrag; std::string mIcePwd; diff --git a/media/webrtc/signaling/test/jsep_session_unittest.cpp b/media/webrtc/signaling/test/jsep_session_unittest.cpp index 7d802561ed23..d2fa350e61f4 100644 --- a/media/webrtc/signaling/test/jsep_session_unittest.cpp +++ b/media/webrtc/signaling/test/jsep_session_unittest.cpp @@ -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 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& 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 candidates; + for (size_t i = 0; i < kNumCandidatesPerComponent; ++i) { + ++port; + std::ostringstream candidate; + candidate << "0 " << static_cast(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( + 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>> mDefaultCandidates; + std::map>> mCandidates; + // Level/candidate pairs that need to be trickled + std::vector> 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 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 parsed = parser.Parse(*sdp); + UniquePtr parsed(Parse(*sdp)); ASSERT_TRUE(parsed.get()); ASSERT_LT(level, parsed->GetMediaSectionCount()); parsed->GetMediaSection(level).SetPort(0); @@ -813,18 +867,29 @@ protected: } } + UniquePtr + Parse(const std::string& sdp) const + { + SipccSdpParser parser; + UniquePtr 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 types; + std::vector> 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(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 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 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 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 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 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 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 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 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 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 parsedOffer = parser.Parse(offer); - ASSERT_TRUE(!!parsedOffer) << "Should have valid SDP" << std::endl - << "Errors were: " << GetParseErrors(parser); + UniquePtr 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 parsedAnswer = parser.Parse(answer); + UniquePtr 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 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 offer(parser.Parse(mSessionOff.GetLocalDescription())); + UniquePtr 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 answer(parser.Parse(mSessionAns.GetLocalDescription())); + UniquePtr 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 offer(parser.Parse(mSessionOff.GetLocalDescription())); + UniquePtr 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 answer(parser.Parse(mSessionAns.GetLocalDescription())); + UniquePtr 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 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 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 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 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 parsedOffer = parser.Parse(offer); + UniquePtr 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 parsedOffer = parser.Parse(offer); + UniquePtr 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 parsedAnswer = parser.Parse(answer); + UniquePtr 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 parsedOffer = parser.Parse(offer); + UniquePtr parsedOffer(Parse(offer)); auto* rtcpfbs = new SdpRtcpFbAttributeList; rtcpfbs->PushEntry("*", SdpRtcpFbAttributeList::kNack); parsedOffer->GetMediaSection(0).GetAttributeList().SetAttribute(rtcpfbs); diff --git a/python/mozbuild/mozbuild/frontend/context.py b/python/mozbuild/mozbuild/frontend/context.py index 11b089545f70..eb552058e2dc 100644 --- a/python/mozbuild/mozbuild/frontend/context.py +++ b/python/mozbuild/mozbuild/frontend/context.py @@ -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. # diff --git a/python/mozbuild/mozbuild/test/frontend/test_context.py b/python/mozbuild/mozbuild/test/frontend/test_context.py index f59c7de60088..74c971e69b18 100644 --- a/python/mozbuild/mozbuild/test/frontend/test_context.py +++ b/python/mozbuild/mozbuild/test/frontend/test_context.py @@ -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() diff --git a/python/mozbuild/setup.py b/python/mozbuild/setup.py index 285bfd5a0364..448a1362a3d9 100644 --- a/python/mozbuild/setup.py +++ b/python/mozbuild/setup.py @@ -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', ) diff --git a/security/manager/ssl/SSLServerCertVerification.cpp b/security/manager/ssl/SSLServerCertVerification.cpp index 406f4de254e9..7a04f2feb30d 100644 --- a/security/manager/ssl/SSLServerCertVerification.cpp +++ b/security/manager/ssl/SSLServerCertVerification.cpp @@ -462,16 +462,6 @@ CertErrorRunnable::CheckCertOverrides() mDefaultErrorCodeToReport); } - nsCOMPtr 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 sslSocketControl = do_QueryInterface( + NS_ISUPPORTS_CAST(nsITransportSecurityInfo*, mInfoObject)); if (sslSocketControl) { nsCOMPtr 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 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 sts diff --git a/services/common/tests/mach_commands.py b/services/common/tests/mach_commands.py index c45904971fb9..b48cfbdf3c35 100644 --- a/services/common/tests/mach_commands.py +++ b/services/common/tests/mach_commands.py @@ -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();', diff --git a/testing/tools/screenshot/gdk-screenshot.cpp b/testing/tools/screenshot/gdk-screenshot.cpp index 9cdeac577ace..cdf3eee5608a 100644 --- a/testing/tools/screenshot/gdk-screenshot.cpp +++ b/testing/tools/screenshot/gdk-screenshot.cpp @@ -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; diff --git a/toolkit/components/jsdownloads/test/unit/head.js b/toolkit/components/jsdownloads/test/unit/head.js index 70d34f1e2a7a..e03e672f8a06 100644 --- a/toolkit/components/jsdownloads/test/unit/head.js +++ b/toolkit/components/jsdownloads/test/unit/head.js @@ -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. } }); diff --git a/toolkit/themes/osx/global/menu.css b/toolkit/themes/osx/global/menu.css index 1805e68d3347..87c1b36a4c6d 100644 --- a/toolkit/themes/osx/global/menu.css +++ b/toolkit/themes/osx/global/menu.css @@ -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; } diff --git a/toolkit/themes/windows/global/menu.css b/toolkit/themes/windows/global/menu.css index 0c74e7a566c8..a526a708195c 100644 --- a/toolkit/themes/windows/global/menu.css +++ b/toolkit/themes/windows/global/menu.css @@ -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; } diff --git a/widget/gtk/nsNativeThemeGTK.cpp b/widget/gtk/nsNativeThemeGTK.cpp index 233d769ecce7..b310002de947 100644 --- a/widget/gtk/nsNativeThemeGTK.cpp +++ b/widget/gtk/nsNativeThemeGTK.cpp @@ -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