1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/protocol/websocket/WebSocketChannelParent.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,263 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set sw=2 ts=8 et tw=80 : */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "WebSocketLog.h" 1.11 +#include "WebSocketChannelParent.h" 1.12 +#include "nsIAuthPromptProvider.h" 1.13 +#include "mozilla/ipc/InputStreamUtils.h" 1.14 +#include "mozilla/ipc/URIUtils.h" 1.15 +#include "SerializedLoadContext.h" 1.16 + 1.17 +using namespace mozilla::ipc; 1.18 + 1.19 +namespace mozilla { 1.20 +namespace net { 1.21 + 1.22 +NS_IMPL_ISUPPORTS(WebSocketChannelParent, 1.23 + nsIWebSocketListener, 1.24 + nsIInterfaceRequestor) 1.25 + 1.26 +WebSocketChannelParent::WebSocketChannelParent(nsIAuthPromptProvider* aAuthProvider, 1.27 + nsILoadContext* aLoadContext, 1.28 + PBOverrideStatus aOverrideStatus) 1.29 + : mAuthProvider(aAuthProvider) 1.30 + , mLoadContext(aLoadContext) 1.31 + , mIPCOpen(true) 1.32 +{ 1.33 + // Websocket channels can't have a private browsing override 1.34 + MOZ_ASSERT_IF(!aLoadContext, aOverrideStatus == kPBOverride_Unset); 1.35 +#if defined(PR_LOGGING) 1.36 + if (!webSocketLog) 1.37 + webSocketLog = PR_NewLogModule("nsWebSocket"); 1.38 +#endif 1.39 +} 1.40 + 1.41 +//----------------------------------------------------------------------------- 1.42 +// WebSocketChannelParent::PWebSocketChannelParent 1.43 +//----------------------------------------------------------------------------- 1.44 + 1.45 +bool 1.46 +WebSocketChannelParent::RecvDeleteSelf() 1.47 +{ 1.48 + LOG(("WebSocketChannelParent::RecvDeleteSelf() %p\n", this)); 1.49 + mChannel = nullptr; 1.50 + mAuthProvider = nullptr; 1.51 + return mIPCOpen ? Send__delete__(this) : true; 1.52 +} 1.53 + 1.54 +bool 1.55 +WebSocketChannelParent::RecvAsyncOpen(const URIParams& aURI, 1.56 + const nsCString& aOrigin, 1.57 + const nsCString& aProtocol, 1.58 + const bool& aSecure, 1.59 + const uint32_t& aPingInterval, 1.60 + const bool& aClientSetPingInterval, 1.61 + const uint32_t& aPingTimeout, 1.62 + const bool& aClientSetPingTimeout) 1.63 +{ 1.64 + LOG(("WebSocketChannelParent::RecvAsyncOpen() %p\n", this)); 1.65 + 1.66 + nsresult rv; 1.67 + nsCOMPtr<nsIURI> uri; 1.68 + 1.69 + if (aSecure) { 1.70 + mChannel = 1.71 + do_CreateInstance("@mozilla.org/network/protocol;1?name=wss", &rv); 1.72 + } else { 1.73 + mChannel = 1.74 + do_CreateInstance("@mozilla.org/network/protocol;1?name=ws", &rv); 1.75 + } 1.76 + if (NS_FAILED(rv)) 1.77 + goto fail; 1.78 + 1.79 + rv = mChannel->SetNotificationCallbacks(this); 1.80 + if (NS_FAILED(rv)) 1.81 + goto fail; 1.82 + 1.83 + rv = mChannel->SetProtocol(aProtocol); 1.84 + if (NS_FAILED(rv)) 1.85 + goto fail; 1.86 + 1.87 + uri = DeserializeURI(aURI); 1.88 + if (!uri) { 1.89 + rv = NS_ERROR_FAILURE; 1.90 + goto fail; 1.91 + } 1.92 + 1.93 + // only use ping values from child if they were overridden by client code. 1.94 + if (aClientSetPingInterval) { 1.95 + // IDL allows setting in seconds, so must be multiple of 1000 ms 1.96 + MOZ_ASSERT(aPingInterval >= 1000 && !(aPingInterval % 1000)); 1.97 + mChannel->SetPingInterval(aPingInterval / 1000); 1.98 + } 1.99 + if (aClientSetPingTimeout) { 1.100 + MOZ_ASSERT(aPingTimeout >= 1000 && !(aPingTimeout % 1000)); 1.101 + mChannel->SetPingTimeout(aPingTimeout / 1000); 1.102 + } 1.103 + 1.104 + rv = mChannel->AsyncOpen(uri, aOrigin, this, nullptr); 1.105 + if (NS_FAILED(rv)) 1.106 + goto fail; 1.107 + 1.108 + return true; 1.109 + 1.110 +fail: 1.111 + mChannel = nullptr; 1.112 + return SendOnStop(rv); 1.113 +} 1.114 + 1.115 +bool 1.116 +WebSocketChannelParent::RecvClose(const uint16_t& code, const nsCString& reason) 1.117 +{ 1.118 + LOG(("WebSocketChannelParent::RecvClose() %p\n", this)); 1.119 + if (mChannel) { 1.120 + nsresult rv = mChannel->Close(code, reason); 1.121 + NS_ENSURE_SUCCESS(rv, true); 1.122 + } 1.123 + return true; 1.124 +} 1.125 + 1.126 +bool 1.127 +WebSocketChannelParent::RecvSendMsg(const nsCString& aMsg) 1.128 +{ 1.129 + LOG(("WebSocketChannelParent::RecvSendMsg() %p\n", this)); 1.130 + if (mChannel) { 1.131 + nsresult rv = mChannel->SendMsg(aMsg); 1.132 + NS_ENSURE_SUCCESS(rv, true); 1.133 + } 1.134 + return true; 1.135 +} 1.136 + 1.137 +bool 1.138 +WebSocketChannelParent::RecvSendBinaryMsg(const nsCString& aMsg) 1.139 +{ 1.140 + LOG(("WebSocketChannelParent::RecvSendBinaryMsg() %p\n", this)); 1.141 + if (mChannel) { 1.142 + nsresult rv = mChannel->SendBinaryMsg(aMsg); 1.143 + NS_ENSURE_SUCCESS(rv, true); 1.144 + } 1.145 + return true; 1.146 +} 1.147 + 1.148 +bool 1.149 +WebSocketChannelParent::RecvSendBinaryStream(const InputStreamParams& aStream, 1.150 + const uint32_t& aLength) 1.151 +{ 1.152 + LOG(("WebSocketChannelParent::RecvSendBinaryStream() %p\n", this)); 1.153 + if (mChannel) { 1.154 + nsTArray<mozilla::ipc::FileDescriptor> fds; 1.155 + nsCOMPtr<nsIInputStream> stream = DeserializeInputStream(aStream, fds); 1.156 + if (!stream) { 1.157 + return false; 1.158 + } 1.159 + nsresult rv = mChannel->SendBinaryStream(stream, aLength); 1.160 + NS_ENSURE_SUCCESS(rv, true); 1.161 + } 1.162 + return true; 1.163 +} 1.164 + 1.165 +//----------------------------------------------------------------------------- 1.166 +// WebSocketChannelParent::nsIRequestObserver 1.167 +//----------------------------------------------------------------------------- 1.168 + 1.169 +NS_IMETHODIMP 1.170 +WebSocketChannelParent::OnStart(nsISupports *aContext) 1.171 +{ 1.172 + LOG(("WebSocketChannelParent::OnStart() %p\n", this)); 1.173 + nsAutoCString protocol, extensions; 1.174 + if (mChannel) { 1.175 + mChannel->GetProtocol(protocol); 1.176 + mChannel->GetExtensions(extensions); 1.177 + } 1.178 + if (!mIPCOpen || !SendOnStart(protocol, extensions)) { 1.179 + return NS_ERROR_FAILURE; 1.180 + } 1.181 + return NS_OK; 1.182 +} 1.183 + 1.184 +NS_IMETHODIMP 1.185 +WebSocketChannelParent::OnStop(nsISupports *aContext, nsresult aStatusCode) 1.186 +{ 1.187 + LOG(("WebSocketChannelParent::OnStop() %p\n", this)); 1.188 + if (!mIPCOpen || !SendOnStop(aStatusCode)) { 1.189 + return NS_ERROR_FAILURE; 1.190 + } 1.191 + return NS_OK; 1.192 +} 1.193 + 1.194 +NS_IMETHODIMP 1.195 +WebSocketChannelParent::OnMessageAvailable(nsISupports *aContext, const nsACString& aMsg) 1.196 +{ 1.197 + LOG(("WebSocketChannelParent::OnMessageAvailable() %p\n", this)); 1.198 + if (!mIPCOpen || !SendOnMessageAvailable(nsCString(aMsg))) { 1.199 + return NS_ERROR_FAILURE; 1.200 + } 1.201 + return NS_OK; 1.202 +} 1.203 + 1.204 +NS_IMETHODIMP 1.205 +WebSocketChannelParent::OnBinaryMessageAvailable(nsISupports *aContext, const nsACString& aMsg) 1.206 +{ 1.207 + LOG(("WebSocketChannelParent::OnBinaryMessageAvailable() %p\n", this)); 1.208 + if (!mIPCOpen || !SendOnBinaryMessageAvailable(nsCString(aMsg))) { 1.209 + return NS_ERROR_FAILURE; 1.210 + } 1.211 + return NS_OK; 1.212 +} 1.213 + 1.214 +NS_IMETHODIMP 1.215 +WebSocketChannelParent::OnAcknowledge(nsISupports *aContext, uint32_t aSize) 1.216 +{ 1.217 + LOG(("WebSocketChannelParent::OnAcknowledge() %p\n", this)); 1.218 + if (!mIPCOpen || !SendOnAcknowledge(aSize)) { 1.219 + return NS_ERROR_FAILURE; 1.220 + } 1.221 + return NS_OK; 1.222 +} 1.223 + 1.224 +NS_IMETHODIMP 1.225 +WebSocketChannelParent::OnServerClose(nsISupports *aContext, 1.226 + uint16_t code, const nsACString & reason) 1.227 +{ 1.228 + LOG(("WebSocketChannelParent::OnServerClose() %p\n", this)); 1.229 + if (!mIPCOpen || !SendOnServerClose(code, nsCString(reason))) { 1.230 + return NS_ERROR_FAILURE; 1.231 + } 1.232 + return NS_OK; 1.233 +} 1.234 + 1.235 +void 1.236 +WebSocketChannelParent::ActorDestroy(ActorDestroyReason why) 1.237 +{ 1.238 + LOG(("WebSocketChannelParent::ActorDestroy() %p\n", this)); 1.239 + mIPCOpen = false; 1.240 +} 1.241 + 1.242 +//----------------------------------------------------------------------------- 1.243 +// WebSocketChannelParent::nsIInterfaceRequestor 1.244 +//----------------------------------------------------------------------------- 1.245 + 1.246 +NS_IMETHODIMP 1.247 +WebSocketChannelParent::GetInterface(const nsIID & iid, void **result) 1.248 +{ 1.249 + LOG(("WebSocketChannelParent::GetInterface() %p\n", this)); 1.250 + if (mAuthProvider && iid.Equals(NS_GET_IID(nsIAuthPromptProvider))) 1.251 + return mAuthProvider->GetAuthPrompt(nsIAuthPromptProvider::PROMPT_NORMAL, 1.252 + iid, result); 1.253 + 1.254 + // Only support nsILoadContext if child channel's callbacks did too 1.255 + if (iid.Equals(NS_GET_IID(nsILoadContext)) && mLoadContext) { 1.256 + NS_ADDREF(mLoadContext); 1.257 + *result = static_cast<nsILoadContext*>(mLoadContext); 1.258 + return NS_OK; 1.259 + } 1.260 + 1.261 + return QueryInterface(iid, result); 1.262 +} 1.263 + 1.264 + 1.265 +} // namespace net 1.266 +} // namespace mozilla