зеркало из https://github.com/mozilla/pjs.git
Bug 696085: WebSocket connection opening across page loads r=smaug
This commit is contained in:
Родитель
cde59a53a2
Коммит
80872a0825
|
@ -84,6 +84,7 @@
|
|||
#include "nsDOMFile.h"
|
||||
#include "nsWrapperCacheInlines.h"
|
||||
#include "nsDOMEventTargetHelper.h"
|
||||
#include "nsIObserverService.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
|
@ -92,7 +93,7 @@ using namespace mozilla;
|
|||
#define TRUE_OR_FAIL_WEBSOCKET(x, ret) \
|
||||
PR_BEGIN_MACRO \
|
||||
if (NS_UNLIKELY(!(x))) { \
|
||||
NS_WARNING("ENSURE_TRUE_AND_FAIL_IF_FAILED(" #x ") failed"); \
|
||||
NS_WARNING("TRUE_OR_FAIL_WEBSOCKET(" #x ") failed"); \
|
||||
FailConnection(nsIWebSocketChannel::CLOSE_INTERNAL_ERROR); \
|
||||
return ret; \
|
||||
} \
|
||||
|
@ -227,10 +228,9 @@ nsWebSocket::FailConnection(PRUint16 aReasonCode,
|
|||
NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
|
||||
ConsoleError();
|
||||
|
||||
nsresult rv = CloseConnection(aReasonCode, aReasonString);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
CloseConnection(aReasonCode, aReasonString);
|
||||
|
||||
rv = CreateAndDispatchSimpleEvent(NS_LITERAL_STRING("error"));
|
||||
nsresult rv = CreateAndDispatchSimpleEvent(NS_LITERAL_STRING("error"));
|
||||
if (NS_FAILED(rv))
|
||||
NS_WARNING("Failed to dispatch the error event");
|
||||
|
||||
|
@ -250,6 +250,12 @@ nsWebSocket::Disconnect()
|
|||
if (loadGroup)
|
||||
loadGroup->RemoveRequest(this, nsnull, NS_OK);
|
||||
|
||||
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
|
||||
if (os) {
|
||||
os->RemoveObserver(this, DOM_WINDOW_DESTROYED_TOPIC);
|
||||
os->RemoveObserver(this, DOM_WINDOW_FROZEN_TOPIC);
|
||||
}
|
||||
|
||||
// DontKeepAliveAnyMore() can release the object. So hold a reference to this
|
||||
// until the end of the method.
|
||||
nsRefPtr<nsWebSocket> kungfuDeathGrip = this;
|
||||
|
@ -307,6 +313,13 @@ nsWebSocket::OnStart(nsISupports *aContext)
|
|||
if (mDisconnected)
|
||||
return NS_OK;
|
||||
|
||||
// Attempt to kill "ghost" websocket: but usually too early for check to fail
|
||||
nsresult rv = CheckInnerWindowCorrectness();
|
||||
if (NS_FAILED(rv)) {
|
||||
FailConnectionQuietly();
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!mRequestedProtocolList.IsEmpty()) {
|
||||
mChannel->GetProtocol(mEstablishedProtocol);
|
||||
}
|
||||
|
@ -405,7 +418,7 @@ nsWebSocket::GetInterface(const nsIID &aIID, void **aResult)
|
|||
return wwatch->GetPrompt(outerWindow, aIID, aResult);
|
||||
}
|
||||
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
return QueryInterface(aIID, aResult);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -499,6 +512,8 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsWebSocket)
|
|||
NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIWebSocketListener)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIObserver)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIRequest)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebSocket)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
|
||||
|
@ -1085,6 +1100,14 @@ nsWebSocket::DontKeepAliveAnyMore()
|
|||
mCheckMustKeepAlive = false;
|
||||
}
|
||||
|
||||
void
|
||||
nsWebSocket::FailConnectionQuietly()
|
||||
{
|
||||
// Fail without console error or JS onerror message: onmessage/onclose will
|
||||
// also be blocked so long as CheckInnerWindowCorrectness is failing.
|
||||
CloseConnection(nsIWebSocketChannel::CLOSE_GOING_AWAY);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsWebSocket::UpdateURI()
|
||||
{
|
||||
|
@ -1496,6 +1519,19 @@ nsWebSocket::Init(nsIPrincipal* aPrincipal,
|
|||
mOwner = nsnull;
|
||||
}
|
||||
|
||||
// Attempt to kill "ghost" websocket: but usually too early for check to fail
|
||||
rv = CheckInnerWindowCorrectness();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Shut down websocket if window is frozen or destroyed (only needed for
|
||||
// "ghost" websockets--see bug 696085)
|
||||
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
|
||||
NS_ENSURE_STATE(os);
|
||||
rv = os->AddObserver(this, DOM_WINDOW_DESTROYED_TOPIC, true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = os->AddObserver(this, DOM_WINDOW_FROZEN_TOPIC, true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIJSContextStack> stack =
|
||||
do_GetService("@mozilla.org/js/xpc/ContextStack;1");
|
||||
JSContext* cx = nsnull;
|
||||
|
@ -1571,6 +1607,35 @@ nsWebSocket::Init(nsIPrincipal* aPrincipal,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsWebSocket::nsIObserver
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWebSocket::Observe(nsISupports* aSubject,
|
||||
const char* aTopic,
|
||||
const PRUnichar* aData)
|
||||
{
|
||||
if ((mReadyState == nsIWebSocket::CLOSING) ||
|
||||
(mReadyState == nsIWebSocket::CLOSED)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aSubject);
|
||||
if (!mOwner || window != mOwner) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if ((strcmp(aTopic, DOM_WINDOW_FROZEN_TOPIC) == 0) ||
|
||||
(strcmp(aTopic, DOM_WINDOW_DESTROYED_TOPIC) == 0))
|
||||
{
|
||||
FailConnectionQuietly();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsWebSocket::nsIRequest
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -54,7 +54,9 @@
|
|||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIWebSocketChannel.h"
|
||||
#include "nsIWebSocketListener.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIRequest.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
#define DEFAULT_WS_SCHEME_PORT 80
|
||||
#define DEFAULT_WSS_SCHEME_PORT 443
|
||||
|
@ -74,6 +76,8 @@ class nsWebSocket: public nsDOMEventTargetHelper,
|
|||
public nsIJSNativeInitializer,
|
||||
public nsIInterfaceRequestor,
|
||||
public nsIWebSocketListener,
|
||||
public nsIObserver,
|
||||
public nsSupportsWeakReference,
|
||||
public nsIRequest
|
||||
{
|
||||
friend class nsWSCloseEvent;
|
||||
|
@ -88,6 +92,7 @@ public:
|
|||
NS_DECL_NSIWEBSOCKET
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
NS_DECL_NSIWEBSOCKETLISTENER
|
||||
NS_DECL_NSIOBSERVER
|
||||
NS_DECL_NSIREQUEST
|
||||
|
||||
// nsIJSNativeInitializer
|
||||
|
@ -114,6 +119,7 @@ protected:
|
|||
// These methods when called can release the WebSocket object
|
||||
nsresult FailConnection(PRUint16 reasonCode,
|
||||
const nsACString& aReasonString = EmptyCString());
|
||||
void FailConnectionQuietly();
|
||||
nsresult CloseConnection(PRUint16 reasonCode,
|
||||
const nsACString& aReasonString = EmptyCString());
|
||||
nsresult Disconnect();
|
||||
|
|
|
@ -2319,17 +2319,16 @@ WebSocketChannel::Close(PRUint16 code, const nsACString & reason)
|
|||
LOG(("WebSocketChannel::Close() %p\n", this));
|
||||
NS_ABORT_IF_FALSE(NS_IsMainThread(), "not main thread");
|
||||
|
||||
if (mRequestedClose) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!mTransport) {
|
||||
LOG(("WebSocketChannel::Close() without transport - aborting."));
|
||||
AbortSession(NS_ERROR_NOT_CONNECTED);
|
||||
return NS_ERROR_NOT_CONNECTED;
|
||||
}
|
||||
|
||||
if (mRequestedClose) {
|
||||
LOG(("WebSocketChannel:: Double close error\n"));
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// The API requires the UTF-8 string to be 123 or less bytes
|
||||
if (reason.Length() > 123)
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
|
Загрузка…
Ссылка в новой задаче