From 78670a91d55478ffed437cb4932d5ff56f65d0a0 Mon Sep 17 00:00:00 2001 From: Tom Tung Date: Thu, 8 Sep 2016 09:59:40 +0800 Subject: [PATCH] Bug 1187335 - P2 - Modify the way to report to console for worker and use LoadTainting to decide CORS or not. r=bkelly. r=francois. --- dom/base/nsScriptLoader.cpp | 36 +++++++-- dom/base/nsScriptLoader.h | 2 + dom/security/SRICheck.cpp | 156 ++++++++++++++++++++---------------- dom/security/SRICheck.h | 19 +++-- layout/style/Loader.cpp | 20 ++++- layout/style/Loader.h | 3 + 6 files changed, 148 insertions(+), 88 deletions(-) diff --git a/dom/base/nsScriptLoader.cpp b/dom/base/nsScriptLoader.cpp index 8ddfbc930bbb..4413c4837ab7 100644 --- a/dom/base/nsScriptLoader.cpp +++ b/dom/base/nsScriptLoader.cpp @@ -51,6 +51,7 @@ #include "nsINetworkPredictor.h" #include "ImportManager.h" #include "mozilla/dom/EncodingUtils.h" +#include "mozilla/ConsoleReportCollector.h" #include "mozilla/Attributes.h" #include "mozilla/Unused.h" @@ -514,7 +515,8 @@ nsScriptLoader::nsScriptLoader(nsIDocument *aDocument) mEnabled(true), mDeferEnabled(false), mDocumentParsingDone(false), - mBlockingDOMContentLoaded(false) + mBlockingDOMContentLoaded(false), + mReporter(new ConsoleReportCollector()) { } @@ -1279,7 +1281,12 @@ nsScriptLoader::StartLoad(nsScriptLoadRequest *aRequest, const nsAString &aType, nsAutoPtr sriDataVerifier; if (!aRequest->mIntegrity.IsEmpty()) { - sriDataVerifier = new SRICheckDataVerifier(aRequest->mIntegrity, mDocument); + nsAutoCString sourceUri; + if (mDocument && mDocument->GetDocumentURI()) { + mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri); + } + sriDataVerifier = new SRICheckDataVerifier(aRequest->mIntegrity, sourceUri, + mReporter); } RefPtr handler = @@ -1505,7 +1512,12 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement) MOZ_LOG(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug, ("nsScriptLoader::ProcessScriptElement, integrity=%s", NS_ConvertUTF16toUTF8(integrity).get())); - SRICheck::IntegrityMetadata(integrity, mDocument, &sriMetadata); + nsAutoCString sourceUri; + if (mDocument && mDocument->GetDocumentURI()) { + mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri); + } + SRICheck::IntegrityMetadata(integrity, sourceUri, mReporter, + &sriMetadata); } } @@ -2451,8 +2463,16 @@ nsScriptLoader::OnStreamComplete(nsIIncrementalStreamLoader* aLoader, if (!request->mIntegrity.IsEmpty() && NS_SUCCEEDED((rv = aSRIStatus))) { MOZ_ASSERT(aSRIDataVerifier); - if (NS_FAILED(aSRIDataVerifier->Verify(request->mIntegrity, channel, - request->mCORSMode, mDocument))) { + MOZ_ASSERT(mReporter); + + nsAutoCString sourceUri; + if (mDocument && mDocument->GetDocumentURI()) { + mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri); + } + rv = aSRIDataVerifier->Verify(request->mIntegrity, channel, sourceUri, + mReporter); + mReporter->FlushConsoleReports(mDocument); + if (NS_FAILED(rv)) { rv = NS_ERROR_SRI_CORRUPT; } } else { @@ -2757,7 +2777,11 @@ nsScriptLoader::PreloadURI(nsIURI *aURI, const nsAString &aCharset, MOZ_LOG(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug, ("nsScriptLoader::PreloadURI, integrity=%s", NS_ConvertUTF16toUTF8(aIntegrity).get())); - SRICheck::IntegrityMetadata(aIntegrity, mDocument, &sriMetadata); + nsAutoCString sourceUri; + if (mDocument && mDocument->GetDocumentURI()) { + mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri); + } + SRICheck::IntegrityMetadata(aIntegrity, sourceUri, mReporter, &sriMetadata); } RefPtr request = diff --git a/dom/base/nsScriptLoader.h b/dom/base/nsScriptLoader.h index 63ac43a56b78..085d20e6a0a6 100644 --- a/dom/base/nsScriptLoader.h +++ b/dom/base/nsScriptLoader.h @@ -638,6 +638,8 @@ private: // Module map nsRefPtrHashtable mFetchingModules; nsRefPtrHashtable mFetchedModules; + + nsCOMPtr mReporter; }; class nsScriptLoadHandler final : public nsIIncrementalStreamLoaderObserver diff --git a/dom/security/SRICheck.cpp b/dom/security/SRICheck.cpp index b6a28cd0d693..df61dd94d8d1 100644 --- a/dom/security/SRICheck.cpp +++ b/dom/security/SRICheck.cpp @@ -7,15 +7,15 @@ #include "SRICheck.h" #include "mozilla/Base64.h" +#include "mozilla/LoadTainting.h" #include "mozilla/Logging.h" #include "mozilla/Preferences.h" #include "mozilla/dom/SRILogHelper.h" #include "nsContentUtils.h" #include "nsIChannel.h" -#include "nsIDocument.h" +#include "nsIConsoleReportCollector.h" #include "nsIProtocolHandler.h" #include "nsIScriptError.h" -#include "nsIScriptSecurityManager.h" #include "nsIIncrementalStreamLoader.h" #include "nsIUnicharStreamLoader.h" #include "nsIURI.h" @@ -36,10 +36,11 @@ namespace dom { * sub-resource will be loaded. */ static nsresult -IsEligible(nsIChannel* aChannel, const CORSMode aCORSMode, - const nsIDocument* aDocument) +IsEligible(nsIChannel* aChannel, mozilla::LoadTainting aTainting, + const nsACString& aSourceFileURI, + nsIConsoleReportCollector* aReporter) { - NS_ENSURE_ARG_POINTER(aDocument); + NS_ENSURE_ARG_POINTER(aReporter); if (!aChannel) { SRILOG(("SRICheck::IsEligible, null channel")); @@ -47,7 +48,7 @@ IsEligible(nsIChannel* aChannel, const CORSMode aCORSMode, } // Was the sub-resource loaded via CORS? - if (aCORSMode != CORS_NONE) { + if (aTainting == LoadTainting::CORS) { SRILOG(("SRICheck::IsEligible, CORS mode")); return NS_OK; } @@ -63,40 +64,38 @@ IsEligible(nsIChannel* aChannel, const CORSMode aCORSMode, NS_ENSURE_SUCCESS(rv, rv); if (MOZ_LOG_TEST(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug)) { - nsAutoCString documentSpec; - aDocument->GetDocumentURI()->GetAsciiSpec(documentSpec); - SRILOG(("SRICheck::IsEligible, documentURI=%s; requestURI=%s; finalURI=%s", - documentSpec.get(), requestSpec.get(), + SRILOG(("SRICheck::IsEligible, requestURI=%s; finalURI=%s", + requestSpec.get(), finalURI ? finalURI->GetSpecOrDefault().get() : "")); } // Is the sub-resource same-origin? - nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager(); - if (NS_SUCCEEDED(ssm->CheckSameOriginURI(aDocument->GetDocumentURI(), - finalURI, false))) { + if (aTainting == LoadTainting::Basic) { SRILOG(("SRICheck::IsEligible, same-origin")); return NS_OK; } SRILOG(("SRICheck::IsEligible, NOT same origin")); NS_ConvertUTF8toUTF16 requestSpecUTF16(requestSpec); - const char16_t* params[] = { requestSpecUTF16.get() }; - nsContentUtils::ReportToConsole(nsIScriptError::errorFlag, - NS_LITERAL_CSTRING("Sub-resource Integrity"), - aDocument, - nsContentUtils::eSECURITY_PROPERTIES, - "IneligibleResource", - params, ArrayLength(params)); + nsTArray params; + params.AppendElement(requestSpecUTF16); + aReporter->AddConsoleReport(nsIScriptError::errorFlag, + NS_LITERAL_CSTRING("Sub-resource Integrity"), + nsContentUtils::eSECURITY_PROPERTIES, + aSourceFileURI, 0, 0, + NS_LITERAL_CSTRING("IneligibleResource"), + const_cast&>(params)); return NS_ERROR_SRI_NOT_ELIGIBLE; } /* static */ nsresult SRICheck::IntegrityMetadata(const nsAString& aMetadataList, - const nsIDocument* aDocument, + const nsACString& aSourceFileURI, + nsIConsoleReportCollector* aReporter, SRIMetadata* outMetadata) { NS_ENSURE_ARG_POINTER(outMetadata); - NS_ENSURE_ARG_POINTER(aDocument); + NS_ENSURE_ARG_POINTER(aReporter); MOZ_ASSERT(outMetadata->IsEmpty()); // caller must pass empty metadata if (!Preferences::GetBool("security.sri.enable", false)) { @@ -123,24 +122,26 @@ SRICheck::IntegrityMetadata(const nsAString& aMetadataList, SRIMetadata metadata(token); if (metadata.IsMalformed()) { NS_ConvertUTF8toUTF16 tokenUTF16(token); - const char16_t* params[] = { tokenUTF16.get() }; - nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, - NS_LITERAL_CSTRING("Sub-resource Integrity"), - aDocument, - nsContentUtils::eSECURITY_PROPERTIES, - "MalformedIntegrityHash", - params, ArrayLength(params)); + nsTArray params; + params.AppendElement(tokenUTF16); + aReporter->AddConsoleReport(nsIScriptError::warningFlag, + NS_LITERAL_CSTRING("Sub-resource Integrity"), + nsContentUtils::eSECURITY_PROPERTIES, + aSourceFileURI, 0, 0, + NS_LITERAL_CSTRING("MalformedIntegrityHash"), + const_cast&>(params)); } else if (!metadata.IsAlgorithmSupported()) { nsAutoCString alg; metadata.GetAlgorithm(&alg); NS_ConvertUTF8toUTF16 algUTF16(alg); - const char16_t* params[] = { algUTF16.get() }; - nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, - NS_LITERAL_CSTRING("Sub-resource Integrity"), - aDocument, - nsContentUtils::eSECURITY_PROPERTIES, - "UnsupportedHashAlg", - params, ArrayLength(params)); + nsTArray params; + params.AppendElement(algUTF16); + aReporter->AddConsoleReport(nsIScriptError::warningFlag, + NS_LITERAL_CSTRING("Sub-resource Integrity"), + nsContentUtils::eSECURITY_PROPERTIES, + aSourceFileURI, 0, 0, + NS_LITERAL_CSTRING("UnsupportedHashAlg"), + const_cast&>(params)); } nsAutoCString alg1, alg2; @@ -176,11 +177,12 @@ SRICheck::IntegrityMetadata(const nsAString& aMetadataList, /* static */ nsresult SRICheck::VerifyIntegrity(const SRIMetadata& aMetadata, nsIUnicharStreamLoader* aLoader, - const CORSMode aCORSMode, const nsAString& aString, - const nsIDocument* aDocument) + const nsACString& aSourceFileURI, + nsIConsoleReportCollector* aReporter) { NS_ENSURE_ARG_POINTER(aLoader); + NS_ENSURE_ARG_POINTER(aReporter); NS_ConvertUTF16toUTF8 utf8Hash(aString); nsCOMPtr channel; @@ -197,19 +199,20 @@ SRICheck::VerifyIntegrity(const SRIMetadata& aMetadata, SRILOG(("SRICheck::VerifyIntegrity (unichar stream)")); } - SRICheckDataVerifier verifier(aMetadata, aDocument); + SRICheckDataVerifier verifier(aMetadata, aSourceFileURI, aReporter); nsresult rv; rv = verifier.Update(utf8Hash.Length(), (uint8_t*)utf8Hash.get()); NS_ENSURE_SUCCESS(rv, rv); - return verifier.Verify(aMetadata, channel, aCORSMode, aDocument); + return verifier.Verify(aMetadata, channel, aSourceFileURI, aReporter); } ////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////// SRICheckDataVerifier::SRICheckDataVerifier(const SRIMetadata& aMetadata, - const nsIDocument* aDocument) + const nsACString& aSourceFileURI, + nsIConsoleReportCollector* aReporter) : mCryptoHash(nullptr), mBytesHashed(0), mInvalidMetadata(false), @@ -220,13 +223,16 @@ SRICheckDataVerifier::SRICheckDataVerifier(const SRIMetadata& aMetadata, // IntegrityMetadata() checks this and returns "no metadata" if // it's disabled so we should never make it this far MOZ_ASSERT(Preferences::GetBool("security.sri.enable", false)); + MOZ_ASSERT(aReporter); if (!aMetadata.IsValid()) { - nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, - NS_LITERAL_CSTRING("Sub-resource Integrity"), - aDocument, - nsContentUtils::eSECURITY_PROPERTIES, - "NoValidMetadata"); + nsTArray params; + aReporter->AddConsoleReport(nsIScriptError::warningFlag, + NS_LITERAL_CSTRING("Sub-resource Integrity"), + nsContentUtils::eSECURITY_PROPERTIES, + aSourceFileURI, 0, 0, + NS_LITERAL_CSTRING("NoValidMetadata"), + const_cast&>(params)); mInvalidMetadata = true; return; // ignore invalid metadata for forward-compatibility } @@ -292,9 +298,10 @@ SRICheckDataVerifier::Finish() nsresult SRICheckDataVerifier::VerifyHash(const SRIMetadata& aMetadata, uint32_t aHashIndex, - const nsIDocument* aDocument) + const nsACString& aSourceFileURI, + nsIConsoleReportCollector* aReporter) { - NS_ENSURE_ARG_POINTER(aDocument); + NS_ENSURE_ARG_POINTER(aReporter); nsAutoCString base64Hash; aMetadata.GetHash(aHashIndex, &base64Hash); @@ -302,11 +309,13 @@ SRICheckDataVerifier::VerifyHash(const SRIMetadata& aMetadata, nsAutoCString binaryHash; if (NS_WARN_IF(NS_FAILED(Base64Decode(base64Hash, binaryHash)))) { - nsContentUtils::ReportToConsole(nsIScriptError::errorFlag, - NS_LITERAL_CSTRING("Sub-resource Integrity"), - aDocument, - nsContentUtils::eSECURITY_PROPERTIES, - "InvalidIntegrityBase64"); + nsTArray params; + aReporter->AddConsoleReport(nsIScriptError::errorFlag, + NS_LITERAL_CSTRING("Sub-resource Integrity"), + nsContentUtils::eSECURITY_PROPERTIES, + aSourceFileURI, 0, 0, + NS_LITERAL_CSTRING("InvalidIntegrityBase64"), + const_cast&>(params)); return NS_ERROR_SRI_CORRUPT; } @@ -314,11 +323,13 @@ SRICheckDataVerifier::VerifyHash(const SRIMetadata& aMetadata, int8_t hashType; aMetadata.GetHashType(&hashType, &hashLength); if (binaryHash.Length() != hashLength) { - nsContentUtils::ReportToConsole(nsIScriptError::errorFlag, - NS_LITERAL_CSTRING("Sub-resource Integrity"), - aDocument, - nsContentUtils::eSECURITY_PROPERTIES, - "InvalidIntegrityLength"); + nsTArray params; + aReporter->AddConsoleReport(nsIScriptError::errorFlag, + NS_LITERAL_CSTRING("Sub-resource Integrity"), + nsContentUtils::eSECURITY_PROPERTIES, + aSourceFileURI, 0, 0, + NS_LITERAL_CSTRING("InvalidIntegrityLength"), + const_cast&>(params)); return NS_ERROR_SRI_CORRUPT; } @@ -343,10 +354,10 @@ SRICheckDataVerifier::VerifyHash(const SRIMetadata& aMetadata, nsresult SRICheckDataVerifier::Verify(const SRIMetadata& aMetadata, nsIChannel* aChannel, - const CORSMode aCORSMode, - const nsIDocument* aDocument) + const nsACString& aSourceFileURI, + nsIConsoleReportCollector* aReporter) { - NS_ENSURE_ARG_POINTER(aDocument); + NS_ENSURE_ARG_POINTER(aReporter); if (MOZ_LOG_TEST(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug)) { nsAutoCString requestURL; @@ -360,7 +371,11 @@ SRICheckDataVerifier::Verify(const SRIMetadata& aMetadata, nsresult rv = Finish(); NS_ENSURE_SUCCESS(rv, rv); - if (NS_FAILED(IsEligible(aChannel, aCORSMode, aDocument))) { + nsCOMPtr loadInfo = aChannel->GetLoadInfo(); + NS_ENSURE_TRUE(loadInfo, NS_ERROR_FAILURE); + LoadTainting tainting = loadInfo->GetTainting(); + + if (NS_FAILED(IsEligible(aChannel, tainting, aSourceFileURI, aReporter))) { return NS_ERROR_SRI_NOT_ELIGIBLE; } @@ -369,7 +384,7 @@ SRICheckDataVerifier::Verify(const SRIMetadata& aMetadata, } for (uint32_t i = 0; i < aMetadata.HashCount(); i++) { - if (NS_SUCCEEDED(VerifyHash(aMetadata, i, aDocument))) { + if (NS_SUCCEEDED(VerifyHash(aMetadata, i, aSourceFileURI, aReporter))) { return NS_OK; // stop at the first valid hash } } @@ -377,13 +392,14 @@ SRICheckDataVerifier::Verify(const SRIMetadata& aMetadata, nsAutoCString alg; aMetadata.GetAlgorithm(&alg); NS_ConvertUTF8toUTF16 algUTF16(alg); - const char16_t* params[] = { algUTF16.get() }; - nsContentUtils::ReportToConsole(nsIScriptError::errorFlag, - NS_LITERAL_CSTRING("Sub-resource Integrity"), - aDocument, - nsContentUtils::eSECURITY_PROPERTIES, - "IntegrityMismatch", - params, ArrayLength(params)); + nsTArray params; + params.AppendElement(algUTF16); + aReporter->AddConsoleReport(nsIScriptError::errorFlag, + NS_LITERAL_CSTRING("Sub-resource Integrity"), + nsContentUtils::eSECURITY_PROPERTIES, + aSourceFileURI, 0, 0, + NS_LITERAL_CSTRING("IntegrityMismatch"), + const_cast&>(params)); return NS_ERROR_SRI_CORRUPT; } diff --git a/dom/security/SRICheck.h b/dom/security/SRICheck.h index 8734c1f99ba9..0ea7d7b168cd 100644 --- a/dom/security/SRICheck.h +++ b/dom/security/SRICheck.h @@ -7,14 +7,13 @@ #ifndef mozilla_dom_SRICheck_h #define mozilla_dom_SRICheck_h -#include "mozilla/CORSMode.h" #include "nsCOMPtr.h" #include "nsICryptoHash.h" #include "SRIMetadata.h" class nsIChannel; -class nsIDocument; class nsIUnicharStreamLoader; +class nsIConsoleReportCollector; namespace mozilla { namespace dom { @@ -30,7 +29,8 @@ public: * return the strongest supported hash. */ static nsresult IntegrityMetadata(const nsAString& aMetadataList, - const nsIDocument* aDocument, + const nsACString& aSourceFileURI, + nsIConsoleReportCollector* aReporter, SRIMetadata* outMetadata); /** @@ -39,20 +39,22 @@ public: */ static nsresult VerifyIntegrity(const SRIMetadata& aMetadata, nsIUnicharStreamLoader* aLoader, - const CORSMode aCORSMode, const nsAString& aString, - const nsIDocument* aDocument); + const nsACString& aSourceFileURI, + nsIConsoleReportCollector* aReporter); }; class SRICheckDataVerifier final { public: SRICheckDataVerifier(const SRIMetadata& aMetadata, - const nsIDocument* aDocument); + const nsACString& aSourceFileURI, + nsIConsoleReportCollector* aReporter); nsresult Update(uint32_t aStringLen, const uint8_t* aString); nsresult Verify(const SRIMetadata& aMetadata, nsIChannel* aChannel, - const CORSMode aCORSMode, const nsIDocument* aDocument); + const nsACString& aSourceFileURI, + nsIConsoleReportCollector* aReporter); private: nsCOMPtr mCryptoHash; @@ -65,7 +67,8 @@ class SRICheckDataVerifier final nsresult EnsureCryptoHash(); nsresult Finish(); nsresult VerifyHash(const SRIMetadata& aMetadata, uint32_t aHashIndex, - const nsIDocument* aDocument); + const nsACString& aSourceFileURI, + nsIConsoleReportCollector* aReporter); }; } // namespace dom diff --git a/layout/style/Loader.cpp b/layout/style/Loader.cpp index d6ece64034d2..9a58a1855b37 100644 --- a/layout/style/Loader.cpp +++ b/layout/style/Loader.cpp @@ -55,6 +55,7 @@ #include "mozilla/AsyncEventDispatcher.h" #include "mozilla/StyleSheetHandle.h" #include "mozilla/StyleSheetHandleInlines.h" +#include "mozilla/ConsoleReportCollector.h" #ifdef MOZ_XUL #include "nsXULPrototypeCache.h" @@ -520,6 +521,7 @@ Loader::Loader(StyleBackendType aType) , mCompatMode(eCompatibility_FullStandards) , mStyleBackendType(Some(aType)) , mEnabled(true) + , mReporter(new ConsoleReportCollector()) #ifdef DEBUG , mSyncCallback(false) #endif @@ -531,6 +533,7 @@ Loader::Loader(nsIDocument* aDocument) , mDatasToNotifyOn(0) , mCompatMode(eCompatibility_FullStandards) , mEnabled(true) + , mReporter(new ConsoleReportCollector()) #ifdef DEBUG , mSyncCallback(false) #endif @@ -955,9 +958,13 @@ SheetLoadData::OnStreamComplete(nsIUnicharStreamLoader* aLoader, return NS_OK; } } else { - nsresult rv = SRICheck::VerifyIntegrity(sriMetadata, aLoader, - mSheet->GetCORSMode(), aBuffer, - mLoader->mDocument); + nsAutoCString sourceUri; + if (mLoader->mDocument && mLoader->mDocument->GetDocumentURI()) { + mLoader->mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri); + } + nsresult rv = SRICheck::VerifyIntegrity(sriMetadata, aLoader, aBuffer, + sourceUri, mLoader->mReporter); + mLoader->mReporter->FlushConsoleReports(mLoader->mDocument); if (NS_FAILED(rv)) { LOG((" Load was blocked by SRI")); MOZ_LOG(gSriPRLog, mozilla::LogLevel::Debug, @@ -1236,7 +1243,12 @@ Loader::CreateSheet(nsIURI* aURI, MOZ_LOG(gSriPRLog, mozilla::LogLevel::Debug, ("css::Loader::CreateSheet, integrity=%s", NS_ConvertUTF16toUTF8(aIntegrity).get())); - SRICheck::IntegrityMetadata(aIntegrity, mDocument, &sriMetadata); + nsAutoCString sourceUri; + if (mDocument && mDocument->GetDocumentURI()) { + mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri); + } + SRICheck::IntegrityMetadata(aIntegrity, sourceUri, mReporter, + &sriMetadata); } if (GetStyleBackendType() == StyleBackendType::Gecko) { diff --git a/layout/style/Loader.h b/layout/style/Loader.h index 6ea53bd075d4..ba8918cc0e74 100644 --- a/layout/style/Loader.h +++ b/layout/style/Loader.h @@ -28,6 +28,7 @@ #include "mozilla/net/ReferrerPolicy.h" class nsICSSLoaderObserver; +class nsIConsoleReportCollector; class nsIContent; class nsIDocument; class nsMediaList; @@ -584,6 +585,8 @@ private: bool mEnabled; // is enabled to load new styles + nsCOMPtr mReporter; + #ifdef DEBUG bool mSyncCallback; #endif