import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo

This commit is contained in:
Roy Tam 2018-01-19 03:59:58 +08:00
commit dcd9973243
150858 changed files with 23884658 additions and 0 deletions

374
ipc/netd/Netd.cpp Normal file
View file

@ -0,0 +1,374 @@
/* 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 "Netd.h"
#include <android/log.h>
#include <cutils/sockets.h>
#include <fcntl.h>
#include <sys/socket.h>
#include "android/log.h"
#include "base/task.h"
#include "nsWhitespaceTokenizer.h"
#include "nsXULAppAPI.h"
#include "nsString.h"
#include "nsThreadUtils.h"
#include "mozilla/RefPtr.h"
#include "mozilla/Sprintf.h"
#include "SystemProperty.h"
#define NETD_LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk", args)
#define ICS_SYS_USB_RNDIS_MAC "/sys/class/android_usb/android0/f_rndis/ethaddr"
#define INVALID_SOCKET -1
#define MAX_RECONNECT_TIMES 10
using mozilla::system::Property;
namespace {
RefPtr<mozilla::ipc::NetdClient> gNetdClient;
RefPtr<mozilla::ipc::NetdConsumer> gNetdConsumer;
class StopNetdConsumer : public mozilla::Runnable {
public:
NS_IMETHOD Run() override
{
MOZ_ASSERT(NS_IsMainThread());
gNetdConsumer = nullptr;
return NS_OK;
}
};
bool
InitRndisAddress()
{
char mac[20];
char serialno[] = "1234567890ABCDEF";
static const int kEthernetAddressLength = 6;
char address[kEthernetAddressLength];
int i = 0;
int ret = 0;
int length = 0;
mozilla::ScopedClose fd;
fd.rwget() = open(ICS_SYS_USB_RNDIS_MAC, O_WRONLY);
if (fd.rwget() == -1) {
NETD_LOG("Unable to open file %s.", ICS_SYS_USB_RNDIS_MAC);
return false;
}
Property::Get("ro.serialno", serialno, "1234567890ABCDEF");
memset(address, 0, sizeof(address));
// First byte is 0x02 to signify a locally administered address.
address[0] = 0x02;
length = strlen(serialno);
for (i = 0; i < length; i++) {
address[i % (kEthernetAddressLength - 1) + 1] ^= serialno[i];
}
SprintfLiteral(mac, "%02x:%02x:%02x:%02x:%02x:%02x",
address[0], address[1], address[2],
address[3], address[4], address[5]);
length = strlen(mac);
ret = write(fd.get(), mac, length);
if (ret != length) {
NETD_LOG("Fail to write file %s.", ICS_SYS_USB_RNDIS_MAC);
return false;
}
return true;
}
} // namespace
namespace mozilla {
namespace ipc {
NetdClient::NetdClient()
: LineWatcher('\0', MAX_COMMAND_SIZE)
, mIOLoop(MessageLoopForIO::current())
, mSocket(INVALID_SOCKET)
, mCurrentWriteOffset(0)
, mReConnectTimes(0)
{
MOZ_COUNT_CTOR(NetdClient);
}
NetdClient::~NetdClient()
{
MOZ_COUNT_DTOR(NetdClient);
}
bool
NetdClient::OpenSocket()
{
mSocket.rwget() = socket_local_client("netd",
ANDROID_SOCKET_NAMESPACE_RESERVED,
SOCK_STREAM);
if (mSocket.rwget() < 0) {
NETD_LOG("Error connecting to : netd (%s) - will retry", strerror(errno));
return false;
}
// Add FD_CLOEXEC flag.
int flags = fcntl(mSocket.get(), F_GETFD);
if (flags == -1) {
NETD_LOG("Error doing fcntl with F_GETFD command(%s)", strerror(errno));
return false;
}
flags |= FD_CLOEXEC;
if (fcntl(mSocket.get(), F_SETFD, flags) == -1) {
NETD_LOG("Error doing fcntl with F_SETFD command(%s)", strerror(errno));
return false;
}
// Set non-blocking.
if (fcntl(mSocket.get(), F_SETFL, O_NONBLOCK) == -1) {
NETD_LOG("Error set non-blocking socket(%s)", strerror(errno));
return false;
}
if (!MessageLoopForIO::current()->
WatchFileDescriptor(mSocket.get(),
true,
MessageLoopForIO::WATCH_READ,
&mReadWatcher,
this)) {
NETD_LOG("Error set socket read watcher(%s)", strerror(errno));
return false;
}
if (!mOutgoingQ.empty()) {
MessageLoopForIO::current()->
WatchFileDescriptor(mSocket.get(),
false,
MessageLoopForIO::WATCH_WRITE,
&mWriteWatcher,
this);
}
NETD_LOG("Connected to netd");
return true;
}
void NetdClient::OnLineRead(int aFd, nsDependentCSubstring& aMessage)
{
// Set errno to 0 first. For preventing to use the stale version of errno.
errno = 0;
// We found a line terminator. Each line is formatted as an
// integer response code followed by the rest of the line.
// Fish out the response code.
int responseCode = strtol(aMessage.Data(), nullptr, 10);
if (!errno) {
NetdCommand* response = new NetdCommand();
// Passing all the response message, including the line terminator.
response->mSize = aMessage.Length();
memcpy(response->mData, aMessage.Data(), aMessage.Length());
gNetdConsumer->MessageReceived(response);
}
if (!responseCode) {
NETD_LOG("Can't parse netd's response");
}
}
void
NetdClient::OnFileCanWriteWithoutBlocking(int aFd)
{
MOZ_ASSERT(aFd == mSocket.get());
WriteNetdCommand();
}
void
NetdClient::OnError()
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
mReadWatcher.StopWatchingFileDescriptor();
mWriteWatcher.StopWatchingFileDescriptor();
mSocket.dispose();
mCurrentWriteOffset = 0;
mCurrentNetdCommand = nullptr;
while (!mOutgoingQ.empty()) {
delete mOutgoingQ.front();
mOutgoingQ.pop();
}
Start();
}
// static
void
NetdClient::Start()
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
if (!gNetdClient) {
NETD_LOG("Netd Client is not initialized");
return;
}
if (!gNetdClient->OpenSocket()) {
// Socket open failed, try again in a second.
NETD_LOG("Fail to connect to Netd");
if (++gNetdClient->mReConnectTimes > MAX_RECONNECT_TIMES) {
NETD_LOG("Fail to connect to Netd after retry %d times", MAX_RECONNECT_TIMES);
return;
}
MessageLoopForIO::current()->
PostDelayedTask(NewRunnableFunction(NetdClient::Start),
1000);
return;
}
gNetdClient->mReConnectTimes = 0;
}
// static
void
NetdClient::SendNetdCommandIOThread(NetdCommand* aMessage)
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
MOZ_ASSERT(aMessage);
if (!gNetdClient) {
NETD_LOG("Netd Client is not initialized");
return;
}
gNetdClient->mOutgoingQ.push(aMessage);
if (gNetdClient->mSocket.get() == INVALID_SOCKET) {
NETD_LOG("Netd connection is not established, push the message to queue");
return;
}
gNetdClient->WriteNetdCommand();
}
void
NetdClient::WriteNetdCommand()
{
if (!mCurrentNetdCommand) {
mCurrentWriteOffset = 0;
mCurrentNetdCommand = mOutgoingQ.front();
mOutgoingQ.pop();
}
while (mCurrentWriteOffset < mCurrentNetdCommand->mSize) {
ssize_t write_amount = mCurrentNetdCommand->mSize - mCurrentWriteOffset;
ssize_t written = write(mSocket.get(),
mCurrentNetdCommand->mData + mCurrentWriteOffset,
write_amount);
if (written < 0) {
NETD_LOG("Cannot write to network, error %d\n", (int) written);
OnError();
return;
}
if (written > 0) {
mCurrentWriteOffset += written;
}
if (written != write_amount) {
NETD_LOG("WriteNetdCommand fail !!! Write is not completed");
break;
}
}
if (mCurrentWriteOffset != mCurrentNetdCommand->mSize) {
MessageLoopForIO::current()->
WatchFileDescriptor(mSocket.get(),
false,
MessageLoopForIO::WATCH_WRITE,
&mWriteWatcher,
this);
return;
}
mCurrentNetdCommand = nullptr;
}
static void
InitNetdIOThread()
{
bool result;
char propValue[Property::VALUE_MAX_LENGTH];
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
MOZ_ASSERT(!gNetdClient);
Property::Get("ro.build.version.sdk", propValue, "0");
// Assign rndis address for usb tethering in ICS.
if (atoi(propValue) >= 15) {
result = InitRndisAddress();
// We don't return here because InitRnsisAddress() function is related to
// usb tethering only. Others service such as wifi tethering still need
// to use ipc to communicate with netd.
if (!result) {
NETD_LOG("fail to give rndis interface an address");
}
}
gNetdClient = new NetdClient();
gNetdClient->Start();
}
static void
ShutdownNetdIOThread()
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
nsCOMPtr<nsIRunnable> shutdownEvent = new StopNetdConsumer();
gNetdClient = nullptr;
NS_DispatchToMainThread(shutdownEvent);
}
void
StartNetd(NetdConsumer* aNetdConsumer)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aNetdConsumer);
MOZ_ASSERT(gNetdConsumer == nullptr);
gNetdConsumer = aNetdConsumer;
XRE_GetIOMessageLoop()->PostTask(
NewRunnableFunction(InitNetdIOThread));
}
void
StopNetd()
{
MOZ_ASSERT(NS_IsMainThread());
nsIThread* currentThread = NS_GetCurrentThread();
NS_ASSERTION(currentThread, "This should never be null!");
XRE_GetIOMessageLoop()->PostTask(
NewRunnableFunction(ShutdownNetdIOThread));
while (gNetdConsumer) {
if (!NS_ProcessNextEvent(currentThread)) {
NS_WARNING("Something bad happened!");
break;
}
}
}
/**************************************************************************
*
* This function runs in net worker Thread context. The net worker thread
* is created in dom/system/gonk/NetworkManager.js
*
**************************************************************************/
void
SendNetdCommand(NetdCommand* aMessage)
{
MOZ_ASSERT(aMessage);
XRE_GetIOMessageLoop()->PostTask(
NewRunnableFunction(NetdClient::SendNetdCommandIOThread, aMessage));
}
} // namespace ipc
} // namespace mozilla

81
ipc/netd/Netd.h Normal file
View file

@ -0,0 +1,81 @@
/* 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_system_netd_h__
#define mozilla_system_netd_h__
#include "nsISupportsImpl.h"
#include "nsAutoPtr.h"
#include "base/message_loop.h"
#include "mozilla/FileUtils.h"
#define MAX_COMMAND_SIZE 4096
namespace mozilla {
namespace ipc {
/*
* Represents raw data going to or coming from the Netd socket.
*/
struct NetdCommand
{
uint8_t mData[MAX_COMMAND_SIZE];
// Number of octets in mData.
size_t mSize;
};
class NetdConsumer
{
protected:
virtual ~NetdConsumer() { }
public:
NS_INLINE_DECL_REFCOUNTING(NetdConsumer)
virtual void MessageReceived(NetdCommand* aMessage) = 0;
};
class NetdWriteTask : public Runnable
{
NS_IMETHOD Run();
};
class NetdClient : public MessageLoopForIO::LineWatcher
{
virtual ~NetdClient();
public:
NS_INLINE_DECL_REFCOUNTING(NetdClient)
typedef std::queue<NetdCommand*> NetdCommandQueue;
NetdClient();
static void Start();
static void SendNetdCommandIOThread(NetdCommand* aMessage);
private:
void WriteNetdCommand();
virtual void OnError();
virtual void OnLineRead(int aFd, nsDependentCSubstring& aMessage);
virtual void OnFileCanWriteWithoutBlocking(int aFd);
bool OpenSocket();
MessageLoopForIO *mIOLoop;
MessageLoopForIO::FileDescriptorWatcher mReadWatcher;
MessageLoopForIO::FileDescriptorWatcher mWriteWatcher;
ScopedClose mSocket;
NetdCommandQueue mOutgoingQ;
nsAutoPtr<NetdCommand> mCurrentNetdCommand;
size_t mCurrentWriteOffset;
size_t mReConnectTimes;
};
void StartNetd(NetdConsumer *);
void StopNetd();
void SendNetdCommand(NetdCommand *);
} // namespace ipc
} // namespace mozilla
#endif // mozilla_system_netd_h__

17
ipc/netd/moz.build Normal file
View file

@ -0,0 +1,17 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
EXPORTS.mozilla.ipc += [
'Netd.h',
]
SOURCES += [
'Netd.cpp',
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'