nsHttpActivityDistributor.cpp (9875B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 // HttpLog.h should generally be included first 6 #include "HttpLog.h" 7 8 #include "mozilla/net/SocketProcessChild.h" 9 #include "mozilla/net/SocketProcessParent.h" 10 #include "nsHttpActivityDistributor.h" 11 #include "nsHttpHandler.h" 12 #include "nsCOMPtr.h" 13 #include "nsIOService.h" 14 #include "nsNetUtil.h" 15 #include "nsQueryObject.h" 16 #include "nsThreadUtils.h" 17 #include "NullHttpChannel.h" 18 19 namespace mozilla { 20 namespace net { 21 22 using ObserverHolder = nsMainThreadPtrHolder<nsIHttpActivityObserver>; 23 using ObserverHandle = nsMainThreadPtrHandle<nsIHttpActivityObserver>; 24 25 NS_IMPL_ISUPPORTS(nsHttpActivityDistributor, nsIHttpActivityDistributor, 26 nsIHttpActivityObserver) 27 28 NS_IMETHODIMP 29 nsHttpActivityDistributor::ObserveActivity(nsISupports* aHttpChannel, 30 uint32_t aActivityType, 31 uint32_t aActivitySubtype, 32 PRTime aTimestamp, 33 uint64_t aExtraSizeData, 34 const nsACString& aExtraStringData) { 35 MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread()); 36 37 for (size_t i = 0; i < mObservers.Length(); i++) { 38 (void)mObservers[i]->ObserveActivity(aHttpChannel, aActivityType, 39 aActivitySubtype, aTimestamp, 40 aExtraSizeData, aExtraStringData); 41 } 42 return NS_OK; 43 } 44 45 NS_IMETHODIMP 46 nsHttpActivityDistributor::ObserveConnectionActivity( 47 const nsACString& aHost, int32_t aPort, bool aSSL, bool aHasECH, 48 bool aIsHttp3, uint32_t aActivityType, uint32_t aActivitySubtype, 49 PRTime aTimestamp, const nsACString& aExtraStringData) { 50 MOZ_ASSERT(XRE_IsParentProcess() && NS_IsMainThread()); 51 52 for (size_t i = 0; i < mObservers.Length(); i++) { 53 (void)mObservers[i]->ObserveConnectionActivity( 54 aHost, aPort, aSSL, aHasECH, aIsHttp3, aActivityType, aActivitySubtype, 55 aTimestamp, aExtraStringData); 56 } 57 return NS_OK; 58 } 59 60 NS_IMETHODIMP 61 nsHttpActivityDistributor::ObserveActivityWithArgs( 62 const HttpActivityArgs& aArgs, uint32_t aActivityType, 63 uint32_t aActivitySubtype, PRTime aTimestamp, uint64_t aExtraSizeData, 64 const nsACString& aExtraStringData) { 65 HttpActivityArgs args(aArgs); 66 nsCString extraStringData(aExtraStringData); 67 if (XRE_IsSocketProcess()) { 68 auto task = [args{std::move(args)}, aActivityType, aActivitySubtype, 69 aTimestamp, aExtraSizeData, 70 extraStringData{std::move(extraStringData)}]() { 71 SocketProcessChild::GetSingleton()->SendObserveHttpActivity( 72 args, aActivityType, aActivitySubtype, aTimestamp, aExtraSizeData, 73 extraStringData); 74 }; 75 76 if (!NS_IsMainThread()) { 77 return NS_DispatchToMainThread(NS_NewRunnableFunction( 78 "net::nsHttpActivityDistributor::ObserveActivityWithArgs", task)); 79 } 80 81 task(); 82 return NS_OK; 83 } 84 85 MOZ_ASSERT(XRE_IsParentProcess()); 86 87 RefPtr<nsHttpActivityDistributor> self = this; 88 auto task = [args{std::move(args)}, aActivityType, aActivitySubtype, 89 aTimestamp, aExtraSizeData, 90 extraStringData{std::move(extraStringData)}, 91 self{std::move(self)}]() { 92 if (args.type() == HttpActivityArgs::Tuint64_t) { 93 nsWeakPtr weakPtr = gHttpHandler->GetWeakHttpChannel(args.get_uint64_t()); 94 if (nsCOMPtr<nsIHttpChannel> channel = do_QueryReferent(weakPtr)) { 95 (void)self->ObserveActivity(channel, aActivityType, aActivitySubtype, 96 aTimestamp, aExtraSizeData, 97 extraStringData); 98 } 99 } else if (args.type() == HttpActivityArgs::THttpActivity) { 100 nsCOMPtr<nsIURI> uri; 101 nsAutoCString portStr(""_ns); 102 int32_t port = args.get_HttpActivity().port(); 103 bool endToEndSSL = args.get_HttpActivity().endToEndSSL(); 104 if (port != -1 && 105 ((endToEndSSL && port != 443) || (!endToEndSSL && port != 80))) { 106 portStr.AppendInt(port); 107 } 108 109 nsresult rv = 110 NS_NewURI(getter_AddRefs(uri), 111 (endToEndSSL ? "https://"_ns : "http://"_ns) + 112 args.get_HttpActivity().host() + ":"_ns + portStr); 113 if (NS_FAILED(rv)) { 114 return; 115 } 116 117 RefPtr<NullHttpChannel> channel = new NullHttpChannel(); 118 rv = channel->Init(uri, 0, nullptr, 0, nullptr); 119 MOZ_ASSERT(NS_SUCCEEDED(rv)); 120 121 (void)self->ObserveActivity(static_cast<nsIChannel*>(channel), 122 aActivityType, aActivitySubtype, aTimestamp, 123 aExtraSizeData, extraStringData); 124 } else if (args.type() == HttpActivityArgs::THttpConnectionActivity) { 125 const HttpConnectionActivity& activity = 126 args.get_HttpConnectionActivity(); 127 (void)self->ObserveConnectionActivity( 128 activity.host(), activity.port(), activity.ssl(), activity.hasECH(), 129 activity.isHttp3(), aActivityType, aActivitySubtype, aTimestamp, 130 activity.connInfoKey()); 131 } 132 }; 133 134 if (!NS_IsMainThread()) { 135 return NS_DispatchToMainThread(NS_NewRunnableFunction( 136 "net::nsHttpActivityDistributor::ObserveActivityWithArgs", task)); 137 } 138 139 task(); 140 return NS_OK; 141 } 142 143 bool nsHttpActivityDistributor::Activated() { return mActivated; } 144 145 bool nsHttpActivityDistributor::ObserveProxyResponseEnabled() { 146 return mObserveProxyResponse; 147 } 148 149 bool nsHttpActivityDistributor::ObserveConnectionEnabled() { 150 return mObserveConnection; 151 } 152 153 NS_IMETHODIMP 154 nsHttpActivityDistributor::GetIsActive(bool* isActive) { 155 NS_ENSURE_ARG_POINTER(isActive); 156 if (XRE_IsSocketProcess()) { 157 *isActive = mActivated; 158 return NS_OK; 159 } 160 161 MutexAutoLock lock(mLock); 162 *isActive = mActivated = !!mObservers.Length(); 163 return NS_OK; 164 } 165 166 NS_IMETHODIMP nsHttpActivityDistributor::SetIsActive(bool aActived) { 167 MOZ_RELEASE_ASSERT(XRE_IsSocketProcess()); 168 169 mActivated = aActived; 170 return NS_OK; 171 } 172 173 NS_IMETHODIMP 174 nsHttpActivityDistributor::AddObserver(nsIHttpActivityObserver* aObserver) { 175 MOZ_ASSERT(XRE_IsParentProcess()); 176 if (!NS_IsMainThread()) { 177 // We only support calling this from the main thread. 178 return NS_ERROR_FAILURE; 179 } 180 181 ObserverHandle observer( 182 new ObserverHolder("nsIHttpActivityObserver", aObserver)); 183 184 bool wasEmpty = false; 185 { 186 MutexAutoLock lock(mLock); 187 wasEmpty = mObservers.IsEmpty(); 188 // XXX(Bug 1631371) Check if this should use a fallible operation as it 189 // pretended earlier. 190 mObservers.AppendElement(observer); 191 } 192 193 if (wasEmpty) { 194 mActivated = true; 195 if (nsIOService::UseSocketProcess()) { 196 auto task = []() { 197 RefPtr<SocketProcessParent> parent = 198 SocketProcessParent::GetSingleton(); 199 if (parent && parent->CanSend()) { 200 (void)parent->SendOnHttpActivityDistributorActivated(true); 201 } 202 }; 203 gIOService->CallOrWaitForSocketProcess(task); 204 } 205 } 206 return NS_OK; 207 } 208 209 NS_IMETHODIMP 210 nsHttpActivityDistributor::RemoveObserver(nsIHttpActivityObserver* aObserver) { 211 MOZ_ASSERT(XRE_IsParentProcess()); 212 if (!NS_IsMainThread()) { 213 // We only support calling this from the main thread. 214 return NS_ERROR_FAILURE; 215 } 216 217 ObserverHandle observer( 218 new ObserverHolder("nsIHttpActivityObserver", aObserver)); 219 220 { 221 MutexAutoLock lock(mLock); 222 if (!mObservers.RemoveElement(observer)) { 223 return NS_ERROR_FAILURE; 224 } 225 mActivated = mObservers.IsEmpty(); 226 } 227 228 if (nsIOService::UseSocketProcess() && !mActivated) { 229 auto task = []() { 230 RefPtr<SocketProcessParent> parent = SocketProcessParent::GetSingleton(); 231 if (parent && parent->CanSend()) { 232 (void)parent->SendOnHttpActivityDistributorActivated(false); 233 } 234 }; 235 gIOService->CallOrWaitForSocketProcess(task); 236 } 237 return NS_OK; 238 } 239 240 NS_IMETHODIMP 241 nsHttpActivityDistributor::GetObserveProxyResponse( 242 bool* aObserveProxyResponse) { 243 NS_ENSURE_ARG_POINTER(aObserveProxyResponse); 244 bool result = mObserveProxyResponse; 245 *aObserveProxyResponse = result; 246 return NS_OK; 247 } 248 249 NS_IMETHODIMP 250 nsHttpActivityDistributor::SetObserveProxyResponse(bool aObserveProxyResponse) { 251 if (!NS_IsMainThread()) { 252 // We only support calling this from the main thread. 253 return NS_ERROR_FAILURE; 254 } 255 256 mObserveProxyResponse = aObserveProxyResponse; 257 if (nsIOService::UseSocketProcess()) { 258 auto task = [aObserveProxyResponse]() { 259 RefPtr<SocketProcessParent> parent = SocketProcessParent::GetSingleton(); 260 if (parent && parent->CanSend()) { 261 (void)parent->SendOnHttpActivityDistributorObserveProxyResponse( 262 aObserveProxyResponse); 263 } 264 }; 265 gIOService->CallOrWaitForSocketProcess(task); 266 } 267 return NS_OK; 268 } 269 270 NS_IMETHODIMP 271 nsHttpActivityDistributor::GetObserveConnection(bool* aObserveConnection) { 272 NS_ENSURE_ARG_POINTER(aObserveConnection); 273 274 *aObserveConnection = mObserveConnection; 275 return NS_OK; 276 } 277 278 NS_IMETHODIMP 279 nsHttpActivityDistributor::SetObserveConnection(bool aObserveConnection) { 280 if (!NS_IsMainThread()) { 281 // We only support calling this from the main thread. 282 return NS_ERROR_FAILURE; 283 } 284 285 mObserveConnection = aObserveConnection; 286 if (nsIOService::UseSocketProcess()) { 287 auto task = [aObserveConnection]() { 288 RefPtr<SocketProcessParent> parent = SocketProcessParent::GetSingleton(); 289 if (parent && parent->CanSend()) { 290 (void)parent->SendOnHttpActivityDistributorObserveConnection( 291 aObserveConnection); 292 } 293 }; 294 gIOService->CallOrWaitForSocketProcess(task); 295 } 296 return NS_OK; 297 } 298 299 } // namespace net 300 } // namespace mozilla