GIOChannelParent.cpp (9730B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=4 sw=2 sts=2 et tw=80: */ 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 "GIOChannelParent.h" 8 #include "nsGIOProtocolHandler.h" 9 #include "mozilla/Assertions.h" 10 #include "mozilla/dom/ContentParent.h" 11 #include "mozilla/dom/BrowserParent.h" 12 #include "mozilla/net/NeckoParent.h" 13 #include "nsNetUtil.h" 14 #include "nsIChannel.h" 15 #include "mozilla/net/NeckoChannelParams.h" 16 #include "nsIAuthPrompt.h" 17 #include "nsIAuthPromptProvider.h" 18 #include "nsISecureBrowserUI.h" 19 #include "nsQueryObject.h" 20 #include "mozilla/Logging.h" 21 #include "mozilla/net/ChannelEventQueue.h" 22 #include "mozilla/ipc/URIUtils.h" 23 24 using namespace mozilla::dom; 25 using namespace mozilla::ipc; 26 27 namespace mozilla { 28 #undef LOG 29 #define LOG(args) MOZ_LOG(gGIOLog, mozilla::LogLevel::Debug, args) 30 namespace net { 31 32 GIOChannelParent::GIOChannelParent(dom::BrowserParent* aIframeEmbedding, 33 nsILoadContext* aLoadContext, 34 PBOverrideStatus aOverrideStatus) 35 : mLoadContext(aLoadContext), 36 mPBOverride(aOverrideStatus), 37 mBrowserParent(aIframeEmbedding) { 38 mEventQ = new ChannelEventQueue(static_cast<nsIParentChannel*>(this)); 39 } 40 41 void GIOChannelParent::ActorDestroy(ActorDestroyReason why) { 42 // We may still have refcount>0 if the channel hasn't called OnStopRequest 43 // yet, but we must not send any more msgs to child. 44 mIPCClosed = true; 45 } 46 47 //----------------------------------------------------------------------------- 48 // GIOChannelParent::nsISupports 49 //----------------------------------------------------------------------------- 50 NS_IMPL_ISUPPORTS(GIOChannelParent, nsIStreamListener, nsIParentChannel, 51 nsIInterfaceRequestor, nsIRequestObserver) 52 53 //----------------------------------------------------------------------------- 54 // GIOChannelParent methods 55 //----------------------------------------------------------------------------- 56 57 bool GIOChannelParent::Init(const GIOChannelCreationArgs& aOpenArgs) { 58 switch (aOpenArgs.type()) { 59 case GIOChannelCreationArgs::TGIOChannelOpenArgs: { 60 const GIOChannelOpenArgs& a = aOpenArgs.get_GIOChannelOpenArgs(); 61 return DoAsyncOpen(a.uri(), a.startPos(), a.entityID(), a.uploadStream(), 62 a.loadInfo(), a.loadFlags()); 63 } 64 case GIOChannelCreationArgs::TGIOChannelConnectArgs: { 65 const GIOChannelConnectArgs& cArgs = 66 aOpenArgs.get_GIOChannelConnectArgs(); 67 return ConnectChannel(cArgs.channelId()); 68 } 69 default: 70 MOZ_ASSERT_UNREACHABLE("unknown open type"); 71 return false; 72 } 73 } 74 75 bool GIOChannelParent::DoAsyncOpen(const URIParams& aURI, 76 const uint64_t& aStartPos, 77 const nsCString& aEntityID, 78 const Maybe<IPCStream>& aUploadStream, 79 const LoadInfoArgs& aLoadInfoArgs, 80 const uint32_t& aLoadFlags) { 81 nsresult rv; 82 83 nsCOMPtr<nsIURI> uri = DeserializeURI(aURI); 84 if (!uri) { 85 return false; 86 } 87 88 #ifdef DEBUG 89 LOG(("GIOChannelParent DoAsyncOpen [this=%p uri=%s]\n", this, 90 uri->GetSpecOrDefault().get())); 91 #endif 92 93 nsCOMPtr<nsIIOService> ios(do_GetIOService(&rv)); 94 if (NS_FAILED(rv)) { 95 return SendFailedAsyncOpen(rv); 96 } 97 98 nsAutoCString remoteType; 99 rv = GetRemoteType(remoteType); 100 if (NS_FAILED(rv)) { 101 return SendFailedAsyncOpen(rv); 102 } 103 104 nsCOMPtr<nsILoadInfo> loadInfo; 105 rv = mozilla::ipc::LoadInfoArgsToLoadInfo(aLoadInfoArgs, remoteType, 106 getter_AddRefs(loadInfo)); 107 if (NS_FAILED(rv)) { 108 return SendFailedAsyncOpen(rv); 109 } 110 111 OriginAttributes attrs; 112 rv = loadInfo->GetOriginAttributes(&attrs); 113 if (NS_FAILED(rv)) { 114 return SendFailedAsyncOpen(rv); 115 } 116 117 nsCOMPtr<nsIChannel> chan; 118 rv = NS_NewChannelInternal(getter_AddRefs(chan), uri, loadInfo, nullptr, 119 nullptr, nullptr, aLoadFlags, ios); 120 121 if (NS_FAILED(rv)) { 122 return SendFailedAsyncOpen(rv); 123 } 124 125 mChannel = chan; 126 127 nsIChannel* gioChan = static_cast<nsIChannel*>(mChannel.get()); 128 129 rv = gioChan->AsyncOpen(this); 130 if (NS_FAILED(rv)) { 131 return SendFailedAsyncOpen(rv); 132 } 133 134 return true; 135 } 136 137 bool GIOChannelParent::ConnectChannel(const uint64_t& channelId) { 138 nsresult rv; 139 140 LOG(("Looking for a registered channel [this=%p, id=%" PRIx64 "]", this, 141 channelId)); 142 143 nsCOMPtr<nsIChannel> channel; 144 rv = NS_LinkRedirectChannels(channelId, this, getter_AddRefs(channel)); 145 if (NS_SUCCEEDED(rv)) { 146 mChannel = channel; 147 } 148 149 LOG((" found channel %p, rv=%08" PRIx32, mChannel.get(), 150 static_cast<uint32_t>(rv))); 151 152 return true; 153 } 154 155 mozilla::ipc::IPCResult GIOChannelParent::RecvCancel(const nsresult& status) { 156 if (mChannel) { 157 mChannel->Cancel(status); 158 } 159 160 return IPC_OK(); 161 } 162 163 mozilla::ipc::IPCResult GIOChannelParent::RecvSuspend() { 164 if (mChannel) { 165 mChannel->Suspend(); 166 } 167 return IPC_OK(); 168 } 169 170 mozilla::ipc::IPCResult GIOChannelParent::RecvResume() { 171 if (mChannel) { 172 mChannel->Resume(); 173 } 174 return IPC_OK(); 175 } 176 177 //----------------------------------------------------------------------------- 178 // GIOChannelParent::nsIRequestObserver 179 //----------------------------------------------------------------------------- 180 181 NS_IMETHODIMP 182 GIOChannelParent::OnStartRequest(nsIRequest* aRequest) { 183 LOG(("GIOChannelParent::OnStartRequest [this=%p]\n", this)); 184 nsCOMPtr<nsIChannel> chan = do_QueryInterface(aRequest); 185 MOZ_ASSERT(chan); 186 NS_ENSURE_TRUE(chan, NS_ERROR_UNEXPECTED); 187 188 int64_t contentLength; 189 chan->GetContentLength(&contentLength); 190 nsCString contentType; 191 chan->GetContentType(contentType); 192 nsresult channelStatus = NS_OK; 193 chan->GetStatus(&channelStatus); 194 195 nsCString entityID; 196 URIParams uriparam; 197 nsCOMPtr<nsIURI> uri; 198 chan->GetURI(getter_AddRefs(uri)); 199 SerializeURI(uri, uriparam); 200 201 if (mIPCClosed || !SendOnStartRequest(channelStatus, contentLength, 202 contentType, entityID, uriparam)) { 203 return NS_ERROR_UNEXPECTED; 204 } 205 206 return NS_OK; 207 } 208 209 NS_IMETHODIMP 210 GIOChannelParent::OnStopRequest(nsIRequest* aRequest, nsresult aStatusCode) { 211 LOG(("GIOChannelParent::OnStopRequest: [this=%p status=%" PRIu32 "]\n", this, 212 static_cast<uint32_t>(aStatusCode))); 213 214 if (mIPCClosed || !SendOnStopRequest(aStatusCode)) { 215 return NS_ERROR_UNEXPECTED; 216 } 217 218 return NS_OK; 219 } 220 221 //----------------------------------------------------------------------------- 222 // GIOChannelParent::nsIStreamListener 223 //----------------------------------------------------------------------------- 224 225 NS_IMETHODIMP 226 GIOChannelParent::OnDataAvailable(nsIRequest* aRequest, 227 nsIInputStream* aInputStream, 228 uint64_t aOffset, uint32_t aCount) { 229 LOG(("GIOChannelParent::OnDataAvailable [this=%p]\n", this)); 230 231 nsCString data; 232 nsresult rv = NS_ReadInputStreamToString(aInputStream, data, aCount); 233 if (NS_FAILED(rv)) { 234 return rv; 235 } 236 237 nsresult channelStatus = NS_OK; 238 mChannel->GetStatus(&channelStatus); 239 240 if (mIPCClosed || 241 !SendOnDataAvailable(channelStatus, data, aOffset, aCount)) { 242 return NS_ERROR_UNEXPECTED; 243 } 244 return NS_OK; 245 } 246 247 //----------------------------------------------------------------------------- 248 // GIOChannelParent::nsIParentChannel 249 //----------------------------------------------------------------------------- 250 251 NS_IMETHODIMP 252 GIOChannelParent::SetParentListener(ParentChannelListener* aListener) { 253 // Do not need ptr to ParentChannelListener. 254 return NS_OK; 255 } 256 257 NS_IMETHODIMP 258 GIOChannelParent::NotifyClassificationFlags(uint32_t aClassificationFlags, 259 bool aIsThirdParty) { 260 // Nothing to do. 261 return NS_OK; 262 } 263 264 NS_IMETHODIMP 265 GIOChannelParent::SetClassifierMatchedInfo(const nsACString& aList, 266 const nsACString& aProvider, 267 const nsACString& aFullHash) { 268 // nothing to do 269 return NS_OK; 270 } 271 272 NS_IMETHODIMP 273 GIOChannelParent::SetClassifierMatchedTrackingInfo( 274 const nsACString& aLists, const nsACString& aFullHashes) { 275 // nothing to do 276 return NS_OK; 277 } 278 279 NS_IMETHODIMP 280 GIOChannelParent::Delete() { 281 if (mIPCClosed || !SendDeleteSelf()) { 282 return NS_ERROR_UNEXPECTED; 283 } 284 285 return NS_OK; 286 } 287 288 NS_IMETHODIMP 289 GIOChannelParent::GetRemoteType(nsACString& aRemoteType) { 290 if (!CanSend()) { 291 return NS_ERROR_UNEXPECTED; 292 } 293 294 dom::PContentParent* pcp = Manager()->Manager(); 295 aRemoteType = static_cast<dom::ContentParent*>(pcp)->GetRemoteType(); 296 return NS_OK; 297 } 298 299 //----------------------------------------------------------------------------- 300 // GIOChannelParent::nsIInterfaceRequestor 301 //----------------------------------------------------------------------------- 302 303 NS_IMETHODIMP 304 GIOChannelParent::GetInterface(const nsIID& uuid, void** result) { 305 if (uuid.Equals(NS_GET_IID(nsIAuthPromptProvider)) || 306 uuid.Equals(NS_GET_IID(nsISecureBrowserUI))) { 307 if (mBrowserParent) { 308 return mBrowserParent->QueryInterface(uuid, result); 309 } 310 } 311 312 // Only support nsILoadContext if child channel's callbacks did too 313 if (uuid.Equals(NS_GET_IID(nsILoadContext)) && mLoadContext) { 314 nsCOMPtr<nsILoadContext> copy = mLoadContext; 315 copy.forget(result); 316 return NS_OK; 317 } 318 319 return QueryInterface(uuid, result); 320 } 321 322 //--------------------- 323 } // namespace net 324 } // namespace mozilla