Bug 840612 - Part 1: Don't close Marionette and debugger server socket when going offline. r=mdas,past,mcmanus f=jduell

This commit is contained in:
Hubert Figuière 2013-03-26 21:22:40 -04:00
parent 2050fda669
commit 123473187f
8 changed files with 84 additions and 15 deletions

View File

@ -71,6 +71,15 @@ public:
//
virtual void IsLocal(bool *aIsLocal) = 0;
//
// called to determine if this socket should not be terminated when Gecko
// is turned offline. This is mostly useful for the debugging server
// socket.
//
virtual void KeepWhenOffline(bool *aKeepWhenOffline)
{
*aKeepWhenOffline = false;
}
//
// returns the number of bytes sent/transmitted over the socket

View File

@ -11,14 +11,31 @@ interface nsISocketTransport;
native PRNetAddr(union PRNetAddr);
[ptr] native PRNetAddrPtr(union PRNetAddr);
typedef unsigned long nsServerSocketFlag;
/**
* nsIServerSocket
*
* An interface to a server socket that can accept incoming connections.
*/
[scriptable, uuid(a5b64be0-d563-46bb-ae95-132e46fcd42f)]
[scriptable, uuid(0df6a0e2-a6b1-4d4c-b30d-f2cb093444e3)]
interface nsIServerSocket : nsISupports
{
/**
* @name Server Socket Flags
* These flags define various socket options.
* @{
*/
/// The server socket will only respond to connections on the
/// local loopback interface. Otherwise, it will accept connections
/// from any interface. To specify a particular network interface,
/// use initWithAddress.
const nsServerSocketFlag LoopbackOnly = 0x00000001;
/// The server socket will not be closed when Gecko is set
/// offline.
const nsServerSocketFlag KeepWhenOffline = 0x00000002;
/** @} */
/**
* init
*
@ -37,7 +54,30 @@ interface nsIServerSocket : nsISupports
* This parameter may be silently limited by the operating system.
* Pass -1 to use the default value.
*/
void init(in long aPort, in boolean aLoopbackOnly, in long aBackLog);
void init(in long aPort,
in boolean aLoopbackOnly,
in long aBackLog);
/**
* initSpecialConnection
*
* This method initializes a server socket and offers the ability to have
* that socket not get terminated if Gecko is set offline.
*
* @param aPort
* The port of the server socket. Pass -1 to indicate no preference,
* and a port will be selected automatically.
* @param aFlags
* Flags for the socket.
* @param aBackLog
* The maximum length the queue of pending connections may grow to.
* This parameter may be silently limited by the operating system.
* Pass -1 to use the default value.
*/
void initSpecialConnection(in long aPort,
in nsServerSocketFlag aFlags,
in long aBackLog);
/**
* initWithAddress

View File

@ -45,6 +45,7 @@ nsServerSocket::nsServerSocket()
: mLock("nsServerSocket.mLock")
, mFD(nullptr)
, mAttached(false)
, mKeepWhenOffline(false)
{
// we want to be able to access the STS directly, and it may not have been
// constructed yet. the STS constructor sets gSocketTransportService.
@ -233,6 +234,12 @@ nsServerSocket::IsLocal(bool *aIsLocal)
*aIsLocal = PR_IsNetAddrType(&mAddr, PR_IpAddrLoopback);
}
void
nsServerSocket::KeepWhenOffline(bool *aKeepWhenOffline)
{
*aKeepWhenOffline = mKeepWhenOffline;
}
//-----------------------------------------------------------------------------
// nsServerSocket::nsISupports
//-----------------------------------------------------------------------------
@ -246,18 +253,26 @@ NS_IMPL_THREADSAFE_ISUPPORTS1(nsServerSocket, nsIServerSocket)
NS_IMETHODIMP
nsServerSocket::Init(int32_t aPort, bool aLoopbackOnly, int32_t aBackLog)
{
return InitSpecialConnection(aPort, aLoopbackOnly ? LoopbackOnly : 0, aBackLog);
}
NS_IMETHODIMP
nsServerSocket::InitSpecialConnection(int32_t aPort, nsServerSocketFlag aFlags,
int32_t aBackLog)
{
PRNetAddrValue val;
PRNetAddr addr;
if (aPort < 0)
aPort = 0;
if (aLoopbackOnly)
if (aFlags & nsIServerSocket::LoopbackOnly)
val = PR_IpAddrLoopback;
else
val = PR_IpAddrAny;
PR_SetNetAddr(val, PR_AF_INET, aPort, &addr);
mKeepWhenOffline = ((aFlags & nsIServerSocket::KeepWhenOffline) != 0);
return InitWithAddress(&addr, aBackLog);
}

View File

@ -23,6 +23,7 @@ public:
virtual void OnSocketReady(PRFileDesc *fd, int16_t outFlags);
virtual void OnSocketDetached(PRFileDesc *fd);
virtual void IsLocal(bool *aIsLocal);
virtual void KeepWhenOffline(bool *aKeepWhenOffline);
virtual uint64_t ByteCountSent() { return 0; }
virtual uint64_t ByteCountReceived() { return 0; }
@ -45,6 +46,7 @@ private:
nsCOMPtr<nsIServerSocketListener> mListener;
nsCOMPtr<nsIEventTarget> mListenerTarget;
bool mAttached;
bool mKeepWhenOffline;
};
//-----------------------------------------------------------------------------

View File

@ -693,15 +693,21 @@ nsSocketTransportService::Reset(bool aGuardLocals)
bool isGuarded;
for (i = mActiveCount - 1; i >= 0; --i) {
isGuarded = false;
if (aGuardLocals)
if (aGuardLocals) {
mActiveList[i].mHandler->IsLocal(&isGuarded);
if (!isGuarded)
mActiveList[i].mHandler->KeepWhenOffline(&isGuarded);
}
if (!isGuarded)
DetachSocket(mActiveList, &mActiveList[i]);
}
for (i = mIdleCount - 1; i >= 0; --i) {
isGuarded = false;
if (aGuardLocals)
if (aGuardLocals) {
mIdleList[i].mHandler->IsLocal(&isGuarded);
if (!isGuarded)
mIdleList[i].mHandler->KeepWhenOffline(&isGuarded);
}
if (!isGuarded)
DetachSocket(mIdleList, &mIdleList[i]);
}

View File

@ -13,7 +13,7 @@ const MARIONETTE_FORCELOCAL_PREF = 'marionette.force-local';
const ServerSocket = CC("@mozilla.org/network/server-socket;1",
"nsIServerSocket",
"init");
"initSpecialConnection");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
@ -89,9 +89,10 @@ MarionetteComponent.prototype = {
if (!marionette_forcelocal) {
// See bug 800138. Because the first socket that opens with
// force-local=false fails, we open a dummy socket that will fail.
// keepWhenOffline=true so that it still work when offline (local).
// This allows the following attempt by Marionette to open a socket
// to succeed.
let insaneSacrificialGoat = new ServerSocket(666, false, 4);
let insaneSacrificialGoat = new ServerSocket(666, Ci.nsIServerSocket.KeepWhenOffline, 4);
insaneSacrificialGoat.asyncListen(this);
}

View File

@ -41,10 +41,6 @@ Cu.import("resource://gre/modules/services-common/log4moz.js");
let logger = Log4Moz.repository.getLogger("Marionette");
logger.info('marionette-actors.js loaded');
Services.prefs.setBoolPref("network.gonk.manage-offline-status", false);
Services.io.manageOfflineStatus = false;
Services.io.offline = false;
// This is used to prevent newSession from returning before the telephony
// API's are ready; see bug 792647. This assumes that marionette-actors.js
// will be loaded before the 'system-message-listener-ready' message

View File

@ -55,7 +55,7 @@ loadSubScript.call(this, "chrome://global/content/devtools/dbg-transport.js");
// XPCOM constructors
const ServerSocket = CC("@mozilla.org/network/server-socket;1",
"nsIServerSocket",
"init");
"initSpecialConnection");
/***
* Public API
@ -212,14 +212,14 @@ var DebuggerServer = {
return true;
}
let localOnly = false;
let flags = Ci.nsIServerSocket.KeepWhenOffline;
// A preference setting can force binding on the loopback interface.
if (Services.prefs.getBoolPref("devtools.debugger.force-local")) {
localOnly = true;
flags |= Ci.nsIServerSocket.LoopbackOnly;
}
try {
let socket = new ServerSocket(aPort, localOnly, 4);
let socket = new ServerSocket(aPort, flags, 4);
socket.asyncListen(this);
this._listener = socket;
} catch (e) {