PrivateAttribution.cpp (4377B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim:set ts=2 sw=2 sts=2 et cindent: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "PrivateAttribution.h" 8 9 #include "mozilla/Components.h" 10 #include "mozilla/StaticPrefs_datareporting.h" 11 #include "mozilla/dom/BindingUtils.h" 12 #include "mozilla/dom/ContentChild.h" 13 #include "mozilla/dom/PrivateAttributionBinding.h" 14 #include "nsIGlobalObject.h" 15 #include "nsIPrivateAttributionService.h" 16 #include "nsURLHelper.h" 17 #include "nsXULAppAPI.h" 18 19 namespace mozilla::dom { 20 21 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(PrivateAttribution, mOwner) 22 23 PrivateAttribution::PrivateAttribution(nsIGlobalObject* aGlobal) 24 : mOwner(aGlobal) { 25 MOZ_ASSERT(aGlobal); 26 } 27 28 JSObject* PrivateAttribution::WrapObject(JSContext* aCx, 29 JS::Handle<JSObject*> aGivenProto) { 30 return PrivateAttribution_Binding::Wrap(aCx, this, aGivenProto); 31 } 32 33 PrivateAttribution::~PrivateAttribution() = default; 34 35 bool PrivateAttribution::ShouldRecord() { 36 #ifdef MOZ_TELEMETRY_REPORTING 37 return (StaticPrefs::dom_private_attribution_submission_enabled() && 38 StaticPrefs::datareporting_healthreport_uploadEnabled()); 39 #else 40 return false; 41 #endif 42 } 43 44 bool PrivateAttribution::GetSourceHostIfNonPrivate(nsACString& aSourceHost, 45 ErrorResult& aRv) { 46 MOZ_ASSERT(mOwner); 47 nsIPrincipal* prin = mOwner->PrincipalOrNull(); 48 if (!prin || NS_FAILED(prin->GetHost(aSourceHost))) { 49 aRv.ThrowInvalidStateError("Couldn't get source host"); 50 return false; 51 } 52 return !prin->GetIsInPrivateBrowsing(); 53 } 54 55 [[nodiscard]] static bool ValidateHost(const nsACString& aHost, 56 ErrorResult& aRv) { 57 if (!net_IsValidDNSHost(aHost)) { 58 aRv.ThrowSyntaxError(aHost + " is not a valid host name"_ns); 59 return false; 60 } 61 return true; 62 } 63 64 void PrivateAttribution::SaveImpression( 65 const PrivateAttributionImpressionOptions& aOptions, ErrorResult& aRv) { 66 nsAutoCString source; 67 if (!GetSourceHostIfNonPrivate(source, aRv)) { 68 return; 69 } 70 71 if (!ValidateHost(aOptions.mTarget, aRv)) { 72 return; 73 } 74 75 if (!ShouldRecord()) { 76 return; 77 } 78 79 if (XRE_IsParentProcess()) { 80 nsCOMPtr<nsIPrivateAttributionService> pa = 81 components::PrivateAttribution::Service(); 82 if (NS_WARN_IF(!pa)) { 83 return; 84 } 85 pa->OnAttributionEvent(source, GetEnumString(aOptions.mType), 86 aOptions.mIndex, aOptions.mAd, aOptions.mTarget); 87 return; 88 } 89 90 auto* content = ContentChild::GetSingleton(); 91 if (NS_WARN_IF(!content)) { 92 return; 93 } 94 content->SendAttributionEvent(source, aOptions.mType, aOptions.mIndex, 95 aOptions.mAd, aOptions.mTarget); 96 } 97 98 void PrivateAttribution::MeasureConversion( 99 const PrivateAttributionConversionOptions& aOptions, ErrorResult& aRv) { 100 nsAutoCString source; 101 if (!GetSourceHostIfNonPrivate(source, aRv)) { 102 return; 103 } 104 for (const nsACString& host : aOptions.mSources) { 105 if (!ValidateHost(host, aRv)) { 106 return; 107 } 108 } 109 110 if (!ShouldRecord()) { 111 return; 112 } 113 114 if (XRE_IsParentProcess()) { 115 nsCOMPtr<nsIPrivateAttributionService> pa = 116 components::PrivateAttribution::Service(); 117 if (NS_WARN_IF(!pa)) { 118 return; 119 } 120 pa->OnAttributionConversion( 121 source, aOptions.mTask, aOptions.mHistogramSize, 122 aOptions.mLookbackDays.WasPassed() ? aOptions.mLookbackDays.Value() : 0, 123 aOptions.mImpression.WasPassed() 124 ? GetEnumString(aOptions.mImpression.Value()) 125 : EmptyCString(), 126 aOptions.mAds, aOptions.mSources); 127 return; 128 } 129 130 auto* content = ContentChild::GetSingleton(); 131 if (NS_WARN_IF(!content)) { 132 return; 133 } 134 content->SendAttributionConversion( 135 source, aOptions.mTask, aOptions.mHistogramSize, 136 aOptions.mLookbackDays.WasPassed() ? Some(aOptions.mLookbackDays.Value()) 137 : Nothing(), 138 aOptions.mImpression.WasPassed() ? Some(aOptions.mImpression.Value()) 139 : Nothing(), 140 aOptions.mAds, aOptions.mSources); 141 } 142 143 } // namespace mozilla::dom