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
Родитель e2c91f7727
Коммит 4e75963b27
8 изменённых файлов: 226 добавлений и 979 удалений

Просмотреть файл

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

Просмотреть файл

@ -5,22 +5,13 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/ipc/Ril.h" #include "mozilla/ipc/Ril.h"
#include <fcntl.h> #include <fcntl.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/un.h> #include <sys/un.h>
#include "jsfriendapi.h" #include <netdb.h> // For gethostbyname.
#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"
#ifdef CHROMIUM_LOG
#undef CHROMIUM_LOG #undef CHROMIUM_LOG
#endif
#if defined(MOZ_WIDGET_GONK) #if defined(MOZ_WIDGET_GONK)
#include <android/log.h> #include <android/log.h>
#define CHROMIUM_LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk", args) #define CHROMIUM_LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk", args)
@ -28,95 +19,189 @@
#define CHROMIUM_LOG(args...) printf(args); #define CHROMIUM_LOG(args...) printf(args);
#endif #endif
namespace mozilla { #include "jsfriendapi.h"
namespace ipc { #include "mozilla/ArrayUtils.h"
#include "nsTArray.h"
#include "nsThreadUtils.h" // For NS_IsMainThread.
#include "RilConnector.h"
USING_WORKERS_NAMESPACE; USING_WORKERS_NAMESPACE
using namespace JS; using namespace mozilla::ipc;
class RilConsumer; namespace {
static const char RIL_SOCKET_NAME[] = "/dev/socket/rilproxy"; static const char RIL_SOCKET_NAME[] = "/dev/socket/rilproxy";
static nsTArray<nsAutoPtr<RilConsumer>> sRilConsumers; static nsTArray<nsAutoPtr<mozilla::ipc::RilConsumer>> sRilConsumers;
// class ConnectWorkerToRIL final : public WorkerTask
// RilConsumer
//
class RilConsumer final : public RilSocketConsumer
{ {
public: public:
RilConsumer(); bool RunTask(JSContext* aCx) override;
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;
}; };
RilConsumer::RilConsumer() class SendRilSocketDataTask final : public nsRunnable
: mShutdown(false) {
{ } public:
SendRilSocketDataTask(unsigned long aClientId,
UnixSocketRawData* aRawData)
: mRawData(aRawData)
, mClientId(aClientId)
{ }
nsresult NS_IMETHOD Run() override
RilConsumer::ConnectWorkerToRIL(JSContext* aCx) {
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 // Set up the postRILMessage on the function for worker -> RIL thread
// communication. // communication.
NS_ASSERTION(!NS_IsMainThread(), "Expecting to be on the worker thread");
NS_ASSERTION(!JS_IsRunning(aCx), "Are we being called somehow?"); 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 // Check whether |postRILMessage| has been defined. No one but this class
// should ever define |postRILMessage| in a RIL worker. // 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)) { if (!JS_GetProperty(aCx, workerGlobal, "postRILMessage", &val)) {
JS_ReportPendingException(aCx); JS_ReportPendingException(aCx);
return NS_ERROR_FAILURE; return false;
} }
// Make sure that |postRILMessage| is a function. // Make sure that |postRILMessage| is a function.
if (JSTYPE_FUNCTION == JS_TypeOfValue(aCx, val)) { if (JSTYPE_FUNCTION == JS_TypeOfValue(aCx, val)) {
return NS_OK; return true;
} }
JSFunction* postRILMessage = JS_DefineFunction(aCx, workerGlobal, return !!JS_DefineFunction(aCx, workerGlobal, "postRILMessage",
"postRILMessage", PostToRIL, 2, 0);
PostRILMessage, 2, 0);
if (NS_WARN_IF(!postRILMessage)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
} }
nsresult class DispatchRILEvent final : public WorkerTask
RilConsumer::Register(unsigned long aClientId, {
WorkerCrossThreadDispatcher* aDispatcher) 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 // Only append client id after RIL_SOCKET_NAME when it's not connected to
// the first(0) rilproxy for compatibility. // the first(0) rilproxy for compatibility.
@ -129,131 +214,60 @@ RilConsumer::Register(unsigned long aClientId,
mAddress = addr_un.sun_path; 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)); nsresult
if (NS_FAILED(rv)) { RilConsumer::Register(unsigned int aClientId,
return rv; 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; return NS_OK;
} }
void void
RilConsumer::Unregister() RilConsumer::Shutdown()
{ {
mShutdown = true; MOZ_ASSERT(NS_IsMainThread());
Close();
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 void
RilConsumer::PostRILMessage(JSContext* aCx, unsigned aArgc, Value* aVp) RilConsumer::Send(UnixSocketRawData* aRawData)
{ {
CallArgs args = CallArgsFromVp(aArgc, aVp); if (!mSocket || mSocket->GetConnectionStatus() != SOCKET_CONNECTED) {
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]) {
// Probably shutting down. // Probably shutting down.
return true; delete aRawData;
return;
} }
mSocket->SendSocketData(aRawData);
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;
} }
void void
@ -265,14 +279,16 @@ RilConsumer::Close()
} }
} }
// |RilSocketConnector| // |StreamSocketConnector|
void void
RilConsumer::ReceiveSocketData(JSContext* aCx, RilConsumer::ReceiveSocketData(int aIndex,
int aIndex,
nsAutoPtr<UnixSocketBuffer>& aBuffer) 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 void
@ -300,140 +316,5 @@ RilConsumer::OnDisconnect(int aIndex)
mSocket->GetSuggestedConnectDelayMs()); 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 ipc
} // namespace mozilla } // namespace mozilla

Просмотреть файл

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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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()
{ }
}
}

Просмотреть файл

@ -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

Просмотреть файл

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