Backed out 6 changesets (bug 1171994) for causing smoketest bustage. a=me

Backed out changeset 46061230e77a (bug 1171994)
Backed out changeset ea00769b70df (bug 1171994)
Backed out changeset 2dc847e4650c (bug 1171994)
Backed out changeset 14ec8c87f973 (bug 1171994)
Backed out changeset 31cdbef9fe22 (bug 1171994)
Backed out changeset 463528fcee4d (bug 1171994)
This commit is contained in:
Ryan VanderMeulen 2015-07-15 12:53:28 -04:00
parent e2c91f7727
commit 4e75963b27
8 changed files with 226 additions and 979 deletions

View File

@ -119,7 +119,7 @@ SystemWorkerManager::Shutdown()
ShutdownAutoMounter();
#ifdef MOZ_B2G_RIL
RilWorker::Shutdown();
RilConsumer::Shutdown();
#endif
nsCOMPtr<nsIWifi> wifi(do_QueryInterface(mWifiWorker));
@ -201,7 +201,7 @@ SystemWorkerManager::RegisterRilWorker(unsigned int aClientId,
return NS_ERROR_FAILURE;
}
return RilWorker::Register(aClientId, wctd);
return RilConsumer::Register(aClientId, wctd);
#endif // MOZ_B2G_RIL
}

View File

@ -5,22 +5,13 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/ipc/Ril.h"
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/un.h>
#include "jsfriendapi.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/workers/Workers.h"
#include "mozilla/ipc/RilSocket.h"
#include "mozilla/ipc/RilSocketConsumer.h"
#include "nsThreadUtils.h" // For NS_IsMainThread.
#include "RilConnector.h"
#include <netdb.h> // For gethostbyname.
#ifdef CHROMIUM_LOG
#undef CHROMIUM_LOG
#endif
#if defined(MOZ_WIDGET_GONK)
#include <android/log.h>
#define CHROMIUM_LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk", args)
@ -28,95 +19,189 @@
#define CHROMIUM_LOG(args...) printf(args);
#endif
namespace mozilla {
namespace ipc {
#include "jsfriendapi.h"
#include "mozilla/ArrayUtils.h"
#include "nsTArray.h"
#include "nsThreadUtils.h" // For NS_IsMainThread.
#include "RilConnector.h"
USING_WORKERS_NAMESPACE;
using namespace JS;
USING_WORKERS_NAMESPACE
using namespace mozilla::ipc;
class RilConsumer;
namespace {
static const char RIL_SOCKET_NAME[] = "/dev/socket/rilproxy";
static nsTArray<nsAutoPtr<RilConsumer>> sRilConsumers;
static nsTArray<nsAutoPtr<mozilla::ipc::RilConsumer>> sRilConsumers;
//
// RilConsumer
//
class RilConsumer final : public RilSocketConsumer
class ConnectWorkerToRIL final : public WorkerTask
{
public:
RilConsumer();
nsresult ConnectWorkerToRIL(JSContext* aCx);
nsresult Register(unsigned long aClientId,
WorkerCrossThreadDispatcher* aDispatcher);
void Unregister();
// Methods for |RilSocketConsumer|
//
void ReceiveSocketData(JSContext* aCx,
int aIndex,
nsAutoPtr<UnixSocketBuffer>& aBuffer) override;
void OnConnectSuccess(int aIndex) override;
void OnConnectError(int aIndex) override;
void OnDisconnect(int aIndex) override;
protected:
static bool PostRILMessage(JSContext* aCx, unsigned aArgc, Value* aVp);
nsresult Send(JSContext* aCx, const CallArgs& aArgs);
nsresult Receive(JSContext* aCx,
uint32_t aClientId,
const UnixSocketBuffer* aBuffer);
void Close();
private:
nsRefPtr<RilSocket> mSocket;
nsCString mAddress;
bool mShutdown;
bool RunTask(JSContext* aCx) override;
};
RilConsumer::RilConsumer()
: mShutdown(false)
{ }
class SendRilSocketDataTask final : public nsRunnable
{
public:
SendRilSocketDataTask(unsigned long aClientId,
UnixSocketRawData* aRawData)
: mRawData(aRawData)
, mClientId(aClientId)
{ }
nsresult
RilConsumer::ConnectWorkerToRIL(JSContext* aCx)
NS_IMETHOD Run() override
{
MOZ_ASSERT(NS_IsMainThread());
if (sRilConsumers.Length() <= mClientId || !sRilConsumers[mClientId]) {
// Probably shutting down.
delete mRawData;
return NS_OK;
}
sRilConsumers[mClientId]->Send(mRawData);
return NS_OK;
}
private:
UnixSocketRawData* mRawData;
unsigned long mClientId;
};
static bool
PostToRIL(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
{
JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
NS_ASSERTION(!NS_IsMainThread(), "Expecting to be on the worker thread");
if (args.length() != 2) {
JS_ReportError(aCx, "Expecting two arguments with the RIL message");
return false;
}
int clientId = args[0].toInt32();
JS::Value v = args[1];
UnixSocketRawData* raw = nullptr;
if (v.isString()) {
JSAutoByteString abs;
JS::Rooted<JSString*> str(aCx, v.toString());
if (!abs.encodeUtf8(aCx, str)) {
return false;
}
raw = new UnixSocketRawData(abs.ptr(), abs.length());
} else if (!v.isPrimitive()) {
JSObject* obj = v.toObjectOrNull();
if (!JS_IsTypedArrayObject(obj)) {
JS_ReportError(aCx, "Object passed in wasn't a typed array");
return false;
}
uint32_t type = JS_GetArrayBufferViewType(obj);
if (type != js::Scalar::Int8 &&
type != js::Scalar::Uint8 &&
type != js::Scalar::Uint8Clamped) {
JS_ReportError(aCx, "Typed array data is not octets");
return false;
}
JS::AutoCheckCannotGC nogc;
size_t size = JS_GetTypedArrayByteLength(obj);
void* data = JS_GetArrayBufferViewData(obj, nogc);
raw = new UnixSocketRawData(data, size);
} else {
JS_ReportError(
aCx, "Incorrect argument. Expecting a string or a typed array");
return false;
}
if (!raw) {
JS_ReportError(aCx, "Unable to post to RIL");
return false;
}
nsRefPtr<SendRilSocketDataTask> task = new SendRilSocketDataTask(clientId,
raw);
NS_DispatchToMainThread(task);
return true;
}
bool
ConnectWorkerToRIL::RunTask(JSContext* aCx)
{
// Set up the postRILMessage on the function for worker -> RIL thread
// communication.
NS_ASSERTION(!NS_IsMainThread(), "Expecting to be on the worker thread");
NS_ASSERTION(!JS_IsRunning(aCx), "Are we being called somehow?");
Rooted<JSObject*> workerGlobal(aCx, CurrentGlobalOrNull(aCx));
JS::Rooted<JSObject*> workerGlobal(aCx, JS::CurrentGlobalOrNull(aCx));
// Check whether |postRILMessage| has been defined. No one but this class
// should ever define |postRILMessage| in a RIL worker.
Rooted<Value> val(aCx);
JS::Rooted<JS::Value> val(aCx);
if (!JS_GetProperty(aCx, workerGlobal, "postRILMessage", &val)) {
JS_ReportPendingException(aCx);
return NS_ERROR_FAILURE;
return false;
}
// Make sure that |postRILMessage| is a function.
if (JSTYPE_FUNCTION == JS_TypeOfValue(aCx, val)) {
return NS_OK;
return true;
}
JSFunction* postRILMessage = JS_DefineFunction(aCx, workerGlobal,
"postRILMessage",
PostRILMessage, 2, 0);
if (NS_WARN_IF(!postRILMessage)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
return !!JS_DefineFunction(aCx, workerGlobal, "postRILMessage",
PostToRIL, 2, 0);
}
nsresult
RilConsumer::Register(unsigned long aClientId,
WorkerCrossThreadDispatcher* aDispatcher)
class DispatchRILEvent final : public WorkerTask
{
public:
DispatchRILEvent(unsigned long aClient, UnixSocketBuffer* aBuffer)
: mClientId(aClient)
, mBuffer(aBuffer)
{ }
bool RunTask(JSContext* aCx) override;
private:
unsigned long mClientId;
nsAutoPtr<UnixSocketBuffer> mBuffer;
};
bool
DispatchRILEvent::RunTask(JSContext* aCx)
{
JS::Rooted<JSObject*> obj(aCx, JS::CurrentGlobalOrNull(aCx));
JS::Rooted<JSObject*> array(aCx,
JS_NewUint8Array(aCx, mBuffer->GetSize()));
if (!array) {
return false;
}
{
JS::AutoCheckCannotGC nogc;
memcpy(JS_GetArrayBufferViewData(array, nogc),
mBuffer->GetData(), mBuffer->GetSize());
}
JS::AutoValueArray<2> args(aCx);
args[0].setNumber((uint32_t)mClientId);
args[1].setObject(*array);
JS::Rooted<JS::Value> rval(aCx);
return JS_CallFunctionName(aCx, obj, "onRILMessage", args, &rval);
}
} // namespace
namespace mozilla {
namespace ipc {
RilConsumer::RilConsumer(unsigned long aClientId,
WorkerCrossThreadDispatcher* aDispatcher)
: mDispatcher(aDispatcher)
, mShutdown(false)
{
// Only append client id after RIL_SOCKET_NAME when it's not connected to
// the first(0) rilproxy for compatibility.
@ -129,131 +214,60 @@ RilConsumer::Register(unsigned long aClientId,
mAddress = addr_un.sun_path;
}
mSocket = new RilSocket(aDispatcher, this, aClientId);
mSocket = new StreamSocket(this, aClientId);
mSocket->Connect(new RilConnector(mAddress, aClientId));
}
nsresult rv = mSocket->Connect(new RilConnector(mAddress, aClientId));
if (NS_FAILED(rv)) {
return rv;
nsresult
RilConsumer::Register(unsigned int aClientId,
WorkerCrossThreadDispatcher* aDispatcher)
{
MOZ_ASSERT(NS_IsMainThread());
sRilConsumers.EnsureLengthAtLeast(aClientId + 1);
if (sRilConsumers[aClientId]) {
NS_WARNING("RilConsumer already registered");
return NS_ERROR_FAILURE;
}
nsRefPtr<ConnectWorkerToRIL> connection = new ConnectWorkerToRIL();
if (!aDispatcher->PostTask(connection)) {
NS_WARNING("Failed to connect worker to ril");
return NS_ERROR_UNEXPECTED;
}
// Now that we're set up, connect ourselves to the RIL thread.
sRilConsumers[aClientId] = new RilConsumer(aClientId, aDispatcher);
return NS_OK;
}
void
RilConsumer::Unregister()
RilConsumer::Shutdown()
{
mShutdown = true;
Close();
MOZ_ASSERT(NS_IsMainThread());
for (unsigned long i = 0; i < sRilConsumers.Length(); i++) {
nsAutoPtr<RilConsumer> instance(sRilConsumers[i]);
if (!instance) {
continue;
}
instance->mShutdown = true;
instance->Close();
instance = nullptr;
}
}
bool
RilConsumer::PostRILMessage(JSContext* aCx, unsigned aArgc, Value* aVp)
void
RilConsumer::Send(UnixSocketRawData* aRawData)
{
CallArgs args = CallArgsFromVp(aArgc, aVp);
if (args.length() != 2) {
JS_ReportError(aCx, "Expecting two arguments with the RIL message");
return false;
}
int clientId = args[0].toInt32();
if ((ssize_t)sRilConsumers.Length() <= clientId || !sRilConsumers[clientId]) {
if (!mSocket || mSocket->GetConnectionStatus() != SOCKET_CONNECTED) {
// Probably shutting down.
return true;
delete aRawData;
return;
}
nsresult rv = sRilConsumers[clientId]->Send(aCx, args);
if (NS_FAILED(rv)) {
return false;
}
return true;
}
nsresult
RilConsumer::Send(JSContext* aCx, const CallArgs& aArgs)
{
if (NS_WARN_IF(!mSocket) ||
NS_WARN_IF(mSocket->GetConnectionStatus() != SOCKET_CONNECTED)) {
// Probably shutting down.
return NS_OK;
}
nsAutoPtr<UnixSocketRawData> raw;
Value v = aArgs[1];
if (v.isString()) {
JSAutoByteString abs;
Rooted<JSString*> str(aCx, v.toString());
if (!abs.encodeUtf8(aCx, str)) {
return NS_ERROR_FAILURE;
}
raw = new UnixSocketRawData(abs.ptr(), abs.length());
} else if (!v.isPrimitive()) {
JSObject* obj = v.toObjectOrNull();
if (!JS_IsTypedArrayObject(obj)) {
JS_ReportError(aCx, "Object passed in wasn't a typed array");
return NS_ERROR_FAILURE;
}
uint32_t type = JS_GetArrayBufferViewType(obj);
if (type != js::Scalar::Int8 &&
type != js::Scalar::Uint8 &&
type != js::Scalar::Uint8Clamped) {
JS_ReportError(aCx, "Typed array data is not octets");
return NS_ERROR_FAILURE;
}
AutoCheckCannotGC nogc;
size_t size = JS_GetTypedArrayByteLength(obj);
void* data = JS_GetArrayBufferViewData(obj, nogc);
raw = new UnixSocketRawData(data, size);
} else {
JS_ReportError(
aCx, "Incorrect argument. Expecting a string or a typed array");
return NS_ERROR_FAILURE;
}
if (!raw) {
JS_ReportError(aCx, "Unable to post to RIL");
return NS_ERROR_FAILURE;
}
mSocket->SendSocketData(raw.forget());
return NS_OK;
}
nsresult
RilConsumer::Receive(JSContext* aCx,
uint32_t aClientId,
const UnixSocketBuffer* aBuffer)
{
MOZ_ASSERT(aBuffer);
Rooted<JSObject*> obj(aCx, CurrentGlobalOrNull(aCx));
Rooted<JSObject*> array(aCx, JS_NewUint8Array(aCx, aBuffer->GetSize()));
if (NS_WARN_IF(!array)) {
return NS_ERROR_FAILURE;
}
{
AutoCheckCannotGC nogc;
memcpy(JS_GetArrayBufferViewData(array, nogc),
aBuffer->GetData(), aBuffer->GetSize());
}
AutoValueArray<2> args(aCx);
args[0].setNumber(aClientId);
args[1].setObject(*array);
Rooted<Value> rval(aCx);
JS_CallFunctionName(aCx, obj, "onRILMessage", args, &rval);
return NS_OK;
mSocket->SendSocketData(aRawData);
}
void
@ -265,14 +279,16 @@ RilConsumer::Close()
}
}
// |RilSocketConnector|
// |StreamSocketConnector|
void
RilConsumer::ReceiveSocketData(JSContext* aCx,
int aIndex,
RilConsumer::ReceiveSocketData(int aIndex,
nsAutoPtr<UnixSocketBuffer>& aBuffer)
{
Receive(aCx, (uint32_t)aIndex, aBuffer);
MOZ_ASSERT(NS_IsMainThread());
nsRefPtr<DispatchRILEvent> dre(new DispatchRILEvent(aIndex, aBuffer.forget()));
mDispatcher->PostTask(dre);
}
void
@ -300,140 +316,5 @@ RilConsumer::OnDisconnect(int aIndex)
mSocket->GetSuggestedConnectDelayMs());
}
//
// RilWorker
//
nsTArray<nsAutoPtr<RilWorker>> RilWorker::sRilWorkers;
nsresult
RilWorker::Register(unsigned int aClientId,
WorkerCrossThreadDispatcher* aDispatcher)
{
MOZ_ASSERT(NS_IsMainThread());
sRilWorkers.EnsureLengthAtLeast(aClientId + 1);
if (sRilWorkers[aClientId]) {
NS_WARNING("RilWorkers already registered");
return NS_ERROR_FAILURE;
}
// Now that we're set up, connect ourselves to the RIL thread.
sRilWorkers[aClientId] = new RilWorker(aDispatcher);
nsresult rv = sRilWorkers[aClientId]->RegisterConsumer(aClientId);
if (NS_FAILED(rv)) {
return rv;
}
return NS_OK;
}
void
RilWorker::Shutdown()
{
MOZ_ASSERT(NS_IsMainThread());
for (size_t i = 0; i < sRilWorkers.Length(); ++i) {
if (!sRilWorkers[i]) {
continue;
}
sRilWorkers[i]->UnregisterConsumer(i);
sRilWorkers[i] = nullptr;
}
}
RilWorker::RilWorker(WorkerCrossThreadDispatcher* aDispatcher)
: mDispatcher(aDispatcher)
{
MOZ_ASSERT(mDispatcher);
}
class RilWorker::RegisterConsumerTask : public WorkerTask
{
public:
RegisterConsumerTask(unsigned int aClientId,
WorkerCrossThreadDispatcher* aDispatcher)
: mClientId(aClientId)
, mDispatcher(aDispatcher)
{
MOZ_ASSERT(mDispatcher);
}
bool RunTask(JSContext* aCx) override
{
sRilConsumers.EnsureLengthAtLeast(mClientId + 1);
MOZ_ASSERT(!sRilConsumers[mClientId]);
nsAutoPtr<RilConsumer> rilConsumer(new RilConsumer());
nsresult rv = rilConsumer->ConnectWorkerToRIL(aCx);
if (NS_FAILED(rv)) {
return false;
}
rv = rilConsumer->Register(mClientId, mDispatcher);
if (NS_FAILED(rv)) {
return false;
}
sRilConsumers[mClientId] = rilConsumer;
return true;
}
private:
unsigned int mClientId;
nsRefPtr<WorkerCrossThreadDispatcher> mDispatcher;
};
nsresult
RilWorker::RegisterConsumer(unsigned int aClientId)
{
nsRefPtr<RegisterConsumerTask> task = new RegisterConsumerTask(aClientId,
mDispatcher);
if (!mDispatcher->PostTask(task)) {
NS_WARNING("Failed to post register-consumer task.");
return NS_ERROR_UNEXPECTED;
}
return NS_OK;
}
class RilWorker::UnregisterConsumerTask : public WorkerTask
{
public:
UnregisterConsumerTask(unsigned int aClientId)
: mClientId(aClientId)
{ }
bool RunTask(JSContext* aCx) override
{
MOZ_ASSERT(mClientId < sRilConsumers.Length());
MOZ_ASSERT(sRilConsumers[mClientId]);
sRilConsumers[mClientId]->Unregister();
sRilConsumers[mClientId] = nullptr;
return true;
}
private:
unsigned int mClientId;
};
void
RilWorker::UnregisterConsumer(unsigned int aClientId)
{
nsRefPtr<UnregisterConsumerTask> task =
new UnregisterConsumerTask(aClientId);
if (!mDispatcher->PostTask(task)) {
NS_WARNING("Failed to post unregister-consumer task.");
return;
}
}
} // namespace ipc
} // namespace mozilla

View File

@ -7,45 +7,42 @@
#ifndef mozilla_ipc_Ril_h
#define mozilla_ipc_Ril_h 1
#include "nsAutoPtr.h"
#include "nsError.h"
#include "nsTArray.h"
#include <mozilla/dom/workers/Workers.h>
#include <mozilla/ipc/StreamSocket.h>
#include <mozilla/ipc/StreamSocketConsumer.h>
namespace mozilla {
namespace dom {
namespace workers {
class WorkerCrossThreadDispatcher;
} // namespace workers
} // namespace dom
namespace ipc {
class RilConsumer;
class RilWorker final
class RilConsumer final : public StreamSocketConsumer
{
public:
static nsresult Register(
unsigned int aClientId,
mozilla::dom::workers::WorkerCrossThreadDispatcher* aDispatcher);
static void Shutdown();
void Send(UnixSocketRawData* aRawData);
private:
class RegisterConsumerTask;
class UnregisterConsumerTask;
RilConsumer(unsigned long aClientId,
mozilla::dom::workers::WorkerCrossThreadDispatcher* aDispatcher);
RilWorker(mozilla::dom::workers::WorkerCrossThreadDispatcher* aDispatcher);
void Close();
nsresult RegisterConsumer(unsigned int aClientId);
void UnregisterConsumer(unsigned int aClientId);
// Methods for |StreamSocketConsumer|
//
static nsTArray<nsAutoPtr<RilWorker>> sRilWorkers;
void ReceiveSocketData(int aIndex,
nsAutoPtr<UnixSocketBuffer>& aBuffer) override;
void OnConnectSuccess(int aIndex) override;
void OnConnectError(int aIndex) override;
void OnDisconnect(int aIndex) override;
nsRefPtr<StreamSocket> mSocket;
nsRefPtr<mozilla::dom::workers::WorkerCrossThreadDispatcher> mDispatcher;
nsCString mAddress;
bool mShutdown;
};
} // namespace ipc

View File

@ -1,433 +0,0 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "RilSocket.h"
#include <fcntl.h>
#include "mozilla/dom/workers/Workers.h"
#include "mozilla/ipc/UnixSocketConnector.h"
#include "mozilla/RefPtr.h"
#include "nsXULAppAPI.h"
#include "RilSocketConsumer.h"
static const size_t MAX_READ_SIZE = 1 << 16;
namespace mozilla {
namespace ipc {
USING_WORKERS_NAMESPACE
//
// RilSocketIO
//
class RilSocketIO final : public ConnectionOrientedSocketIO
{
public:
class ConnectTask;
class DelayedConnectTask;
class ReceiveTask;
RilSocketIO(WorkerCrossThreadDispatcher* aDispatcher,
MessageLoop* aConsumerLoop,
MessageLoop* aIOLoop,
RilSocket* aRilSocket,
UnixSocketConnector* aConnector);
~RilSocketIO();
RilSocket* GetRilSocket();
DataSocket* GetDataSocket();
// Delayed-task handling
//
void SetDelayedConnectTask(CancelableTask* aTask);
void ClearDelayedConnectTask();
void CancelDelayedConnectTask();
// Methods for |DataSocket|
//
nsresult QueryReceiveBuffer(UnixSocketIOBuffer** aBuffer) override;
void ConsumeBuffer() override;
void DiscardBuffer() override;
// Methods for |SocketIOBase|
//
SocketBase* GetSocketBase() override;
bool IsShutdownOnConsumerThread() const override;
bool IsShutdownOnIOThread() const override;
void ShutdownOnConsumerThread() override;
void ShutdownOnIOThread() override;
private:
/**
* Cross-thread dispatcher for the RIL worker
*/
nsRefPtr<WorkerCrossThreadDispatcher> mDispatcher;
/**
* Consumer pointer. Non-thread safe RefPtr, so should only be manipulated
* directly from consumer thread. All non-consumer-thread accesses should
* happen with mIO as container.
*/
RefPtr<RilSocket> mRilSocket;
/**
* If true, do not requeue whatever task we're running
*/
bool mShuttingDownOnIOThread;
/**
* Task member for delayed connect task. Should only be access on consumer
* thread.
*/
CancelableTask* mDelayedConnectTask;
/**
* I/O buffer for received data
*/
nsAutoPtr<UnixSocketRawData> mBuffer;
};
RilSocketIO::RilSocketIO(WorkerCrossThreadDispatcher* aDispatcher,
MessageLoop* aConsumerLoop,
MessageLoop* aIOLoop,
RilSocket* aRilSocket,
UnixSocketConnector* aConnector)
: ConnectionOrientedSocketIO(aConsumerLoop, aIOLoop, aConnector)
, mDispatcher(aDispatcher)
, mRilSocket(aRilSocket)
, mShuttingDownOnIOThread(false)
, mDelayedConnectTask(nullptr)
{
MOZ_ASSERT(mDispatcher);
MOZ_ASSERT(mRilSocket);
}
RilSocketIO::~RilSocketIO()
{
MOZ_ASSERT(IsConsumerThread());
MOZ_ASSERT(IsShutdownOnConsumerThread());
}
RilSocket*
RilSocketIO::GetRilSocket()
{
return mRilSocket.get();
}
DataSocket*
RilSocketIO::GetDataSocket()
{
return mRilSocket.get();
}
void
RilSocketIO::SetDelayedConnectTask(CancelableTask* aTask)
{
MOZ_ASSERT(IsConsumerThread());
mDelayedConnectTask = aTask;
}
void
RilSocketIO::ClearDelayedConnectTask()
{
MOZ_ASSERT(IsConsumerThread());
mDelayedConnectTask = nullptr;
}
void
RilSocketIO::CancelDelayedConnectTask()
{
MOZ_ASSERT(IsConsumerThread());
if (!mDelayedConnectTask) {
return;
}
mDelayedConnectTask->Cancel();
ClearDelayedConnectTask();
}
// |DataSocketIO|
nsresult
RilSocketIO::QueryReceiveBuffer(UnixSocketIOBuffer** aBuffer)
{
MOZ_ASSERT(aBuffer);
if (!mBuffer) {
mBuffer = new UnixSocketRawData(MAX_READ_SIZE);
}
*aBuffer = mBuffer.get();
return NS_OK;
}
/**
* |ReceiveTask| transfers data received on the I/O thread
* to an instance of |RilSocket| on the consumer thread.
*/
class RilSocketIO::ReceiveTask final : public WorkerTask
{
public:
ReceiveTask(RilSocketIO* aIO, UnixSocketBuffer* aBuffer)
: mIO(aIO)
, mBuffer(aBuffer)
{
MOZ_ASSERT(mIO);
}
bool RunTask(JSContext* aCx) override
{
// Dispatched via WCTD, but still needs to run on the consumer thread
MOZ_ASSERT(mIO->IsConsumerThread());
if (NS_WARN_IF(mIO->IsShutdownOnConsumerThread())) {
// Since we've already explicitly closed and the close
// happened before this, this isn't really an error.
return true;
}
RilSocket* rilSocket = mIO->GetRilSocket();
MOZ_ASSERT(rilSocket);
rilSocket->ReceiveSocketData(aCx, mBuffer);
return true;
}
private:
RilSocketIO* mIO;
nsAutoPtr<UnixSocketBuffer> mBuffer;
};
void
RilSocketIO::ConsumeBuffer()
{
nsRefPtr<ReceiveTask> task = new ReceiveTask(this, mBuffer.forget());
NS_WARN_IF(!mDispatcher->PostTask(task));
}
void
RilSocketIO::DiscardBuffer()
{
// Nothing to do.
}
// |SocketIOBase|
SocketBase*
RilSocketIO::GetSocketBase()
{
return GetDataSocket();
}
bool
RilSocketIO::IsShutdownOnConsumerThread() const
{
MOZ_ASSERT(IsConsumerThread());
return mRilSocket == nullptr;
}
bool
RilSocketIO::IsShutdownOnIOThread() const
{
return mShuttingDownOnIOThread;
}
void
RilSocketIO::ShutdownOnConsumerThread()
{
MOZ_ASSERT(IsConsumerThread());
MOZ_ASSERT(!IsShutdownOnConsumerThread());
mRilSocket = nullptr;
}
void
RilSocketIO::ShutdownOnIOThread()
{
MOZ_ASSERT(!IsConsumerThread());
MOZ_ASSERT(!mShuttingDownOnIOThread);
Close(); // will also remove fd from I/O loop
mShuttingDownOnIOThread = true;
}
//
// Socket tasks
//
class RilSocketIO::ConnectTask final
: public SocketIOTask<RilSocketIO>
{
public:
ConnectTask(RilSocketIO* aIO)
: SocketIOTask<RilSocketIO>(aIO)
{ }
void Run() override
{
MOZ_ASSERT(!GetIO()->IsConsumerThread());
MOZ_ASSERT(!IsCanceled());
GetIO()->Connect();
}
};
class RilSocketIO::DelayedConnectTask final
: public SocketIOTask<RilSocketIO>
{
public:
DelayedConnectTask(RilSocketIO* aIO)
: SocketIOTask<RilSocketIO>(aIO)
{ }
void Run() override
{
MOZ_ASSERT(GetIO()->IsConsumerThread());
if (IsCanceled()) {
return;
}
RilSocketIO* io = GetIO();
if (io->IsShutdownOnConsumerThread()) {
return;
}
io->ClearDelayedConnectTask();
io->GetIOLoop()->PostTask(FROM_HERE, new ConnectTask(io));
}
};
//
// RilSocket
//
RilSocket::RilSocket(WorkerCrossThreadDispatcher* aDispatcher,
RilSocketConsumer* aConsumer, int aIndex)
: mIO(nullptr)
, mDispatcher(aDispatcher)
, mConsumer(aConsumer)
, mIndex(aIndex)
{
MOZ_ASSERT(mDispatcher);
MOZ_ASSERT(mConsumer);
}
RilSocket::~RilSocket()
{
MOZ_ASSERT(!mIO);
}
void
RilSocket::ReceiveSocketData(JSContext* aCx,
nsAutoPtr<UnixSocketBuffer>& aBuffer)
{
mConsumer->ReceiveSocketData(aCx, mIndex, aBuffer);
}
nsresult
RilSocket::Connect(UnixSocketConnector* aConnector, int aDelayMs,
MessageLoop* aConsumerLoop, MessageLoop* aIOLoop)
{
MOZ_ASSERT(!mIO);
mIO = new RilSocketIO(mDispatcher, aConsumerLoop, aIOLoop, this, aConnector);
SetConnectionStatus(SOCKET_CONNECTING);
if (aDelayMs > 0) {
RilSocketIO::DelayedConnectTask* connectTask =
new RilSocketIO::DelayedConnectTask(mIO);
mIO->SetDelayedConnectTask(connectTask);
MessageLoop::current()->PostDelayedTask(FROM_HERE, connectTask, aDelayMs);
} else {
aIOLoop->PostTask(FROM_HERE, new RilSocketIO::ConnectTask(mIO));
}
return NS_OK;
}
nsresult
RilSocket::Connect(UnixSocketConnector* aConnector, int aDelayMs)
{
return Connect(aConnector, aDelayMs,
MessageLoop::current(), XRE_GetIOMessageLoop());
}
// |ConnectionOrientedSocket|
nsresult
RilSocket::PrepareAccept(UnixSocketConnector* aConnector,
MessageLoop* aConsumerLoop,
MessageLoop* aIOLoop,
ConnectionOrientedSocketIO*& aIO)
{
MOZ_CRASH("|RilSocket| does not support accepting connections.");
}
// |DataSocket|
void
RilSocket::SendSocketData(UnixSocketIOBuffer* aBuffer)
{
MOZ_ASSERT(mIO);
MOZ_ASSERT(mIO->IsConsumerThread());
MOZ_ASSERT(!mIO->IsShutdownOnConsumerThread());
mIO->GetIOLoop()->PostTask(
FROM_HERE,
new SocketIOSendTask<RilSocketIO, UnixSocketIOBuffer>(mIO, aBuffer));
}
// |SocketBase|
void
RilSocket::Close()
{
MOZ_ASSERT(mIO);
MOZ_ASSERT(mIO->IsConsumerThread());
mIO->CancelDelayedConnectTask();
// From this point on, we consider |mIO| as being deleted. We sever
// the relationship here so any future calls to |Connect| will create
// a new I/O object.
mIO->ShutdownOnConsumerThread();
mIO->GetIOLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mIO));
mIO = nullptr;
NotifyDisconnect();
}
void
RilSocket::OnConnectSuccess()
{
mConsumer->OnConnectSuccess(mIndex);
}
void
RilSocket::OnConnectError()
{
mConsumer->OnConnectError(mIndex);
}
void
RilSocket::OnDisconnect()
{
mConsumer->OnDisconnect(mIndex);
}
} // namespace ipc
} // namespace mozilla

View File

@ -1,110 +0,0 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_ipc_RilSocket_h
#define mozilla_ipc_RilSocket_h
#include "mozilla/ipc/ConnectionOrientedSocket.h"
class JSContext;
class MessageLoop;
namespace mozilla {
namespace dom {
namespace workers {
class WorkerCrossThreadDispatcher;
} // namespace workers
} // namespace dom
} // namespace mozilla
namespace mozilla {
namespace ipc {
class RilSocketConsumer;
class RilSocketIO;
class UnixSocketConnector;
class RilSocket final : public ConnectionOrientedSocket
{
public:
/**
* Constructs an instance of |RilSocket|.
*
* @param aDispatcher The dispatcher class for the received messages.
* @param aConsumer The consumer for the socket.
* @param aIndex An arbitrary index.
*/
RilSocket(mozilla::dom::workers::WorkerCrossThreadDispatcher* aDispatcher,
RilSocketConsumer* aConsumer, int aIndex);
/**
* Method to be called whenever data is received. RIL-worker only.
*
* @param aCx The RIL worker's JS context.
* @param aBuffer Data received from the socket.
*/
void ReceiveSocketData(JSContext* aCx, nsAutoPtr<UnixSocketBuffer>& aBuffer);
/**
* Starts a task on the socket that will try to connect to a socket in a
* non-blocking manner.
*
* @param aConnector Connector object for socket type specific functions
* @param aDelayMs Time delay in milliseconds.
* @param aConsumerLoop The socket's consumer thread.
* @param aIOLoop The socket's I/O thread.
* @return NS_OK on success, or an XPCOM error code otherwise.
*/
nsresult Connect(UnixSocketConnector* aConnector, int aDelayMs,
MessageLoop* aConsumerLoop, MessageLoop* aIOLoop);
/**
* Starts a task on the socket that will try to connect to a socket in a
* non-blocking manner.
*
* @param aConnector Connector object for socket type specific functions
* @param aDelayMs Time delay in milliseconds.
* @return NS_OK on success, or an XPCOM error code otherwise.
*/
nsresult Connect(UnixSocketConnector* aConnector, int aDelayMs = 0);
// Methods for |ConnectionOrientedSocket|
//
nsresult PrepareAccept(UnixSocketConnector* aConnector,
MessageLoop* aConsumerLoop,
MessageLoop* aIOLoop,
ConnectionOrientedSocketIO*& aIO) override;
// Methods for |DataSocket|
//
void SendSocketData(UnixSocketIOBuffer* aBuffer) override;
// Methods for |SocketBase|
//
void Close() override;
void OnConnectSuccess() override;
void OnConnectError() override;
void OnDisconnect() override;
protected:
virtual ~RilSocket();
private:
RilSocketIO* mIO;
nsRefPtr<mozilla::dom::workers::WorkerCrossThreadDispatcher> mDispatcher;
RilSocketConsumer* mConsumer;
int mIndex;
};
} // namespace ipc
} // namepsace mozilla
#endif // mozilla_ipc_RilSocket_h

View File

@ -1,20 +0,0 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "RilSocketConsumer.h"
namespace mozilla {
namespace ipc {
//
// RilSocketConsumer
//
RilSocketConsumer::~RilSocketConsumer()
{ }
}
}

View File

@ -1,64 +0,0 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_ipc_RilSocketConsumer_h
#define mozilla_ipc_RilSocketConsumer_h
#include "nsAutoPtr.h"
class JSContext;
namespace mozilla {
namespace ipc {
class UnixSocketBuffer;
/**
* |RilSocketConsumer| handles socket events and received data.
*/
class RilSocketConsumer
{
public:
/**
* Method to be called whenever data is received. RIL-worker only.
*
* @param aCx The RIL worker's JS context.
* @param aIndex The index that has been given to the stream socket.
* @param aBuffer Data received from the socket.
*/
virtual void ReceiveSocketData(JSContext* aCx,
int aIndex,
nsAutoPtr<UnixSocketBuffer>& aBuffer) = 0;
/**
* Callback for socket success. Consumer-thread only.
*
* @param aIndex The index that has been given to the stream socket.
*/
virtual void OnConnectSuccess(int aIndex) = 0;
/**
* Callback for socket errors. Consumer-thread only.
*
* @param aIndex The index that has been given to the stream socket.
*/
virtual void OnConnectError(int aIndex) = 0;
/**
* Callback for socket disconnect. Consumer-thread only.
*
* @param aIndex The index that has been given to the stream socket.
*/
virtual void OnDisconnect(int aIndex) = 0;
protected:
virtual ~RilSocketConsumer();
};
}
}
#endif

View File

@ -6,15 +6,11 @@
EXPORTS.mozilla.ipc += [
'Ril.h',
'RilSocket.h',
'RilSocketConsumer.h'
]
SOURCES += [
'Ril.cpp',
'RilConnector.cpp',
'RilSocket.cpp',
'RilSocketConsumer.cpp'
'RilConnector.cpp'
]
include('/ipc/chromium/chromium-config.mozbuild')