mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:18:48 +00:00
c2bcdec5c9
- Bug 1261009 - Remove the Data Store API, r=fabrice (b22e580107) - Bug 1268393 - Some compilation issues in ServiceWorker code, r=ehsan (d9c2f2554b) - Bug 1209095 - Accept opaqueredirection fetch results if the request redirection type is manual. r=bkelly (6fe92d1368) - Bug 1267733 P2 Pass ServiceWorkerRegistrationInfo down to CancelChannelRunnable. r=jdm (0ec51f09ef) - Bug 1267733 P3 Trigger service worker update after failed interception. r=jdm (f89a7998d4) - Bug 1267733 P4 Add a wpt test that verifies a service worker update can recover from a broken navigation interception. r=jdm (9dc0ce97bd) - Bug 1267691: Assert on failed attempts to shutdown a thread from itself r=froyd (0cbd1e458c) - Bug 1180533 - Disable BackgroundHangMonitor on gonk (a2d666e741) - Bug 1121216 - disable BackgroundHangMonitor for TSan builds; r=jchen (ef15d1016f) - Bug 1265621 - Use StaticRefPtr in Omnijar.cpp; r=froydnj (81bc32836e) - Bug 1265621 - Expose outer zip readers in Omnijar::GetReader; r=froydnj (ce3f82929e) - Bug 1267021 - Use fallible allocation and move semantics for Push events. r=wchen (3a1ae23d8d) - Bug 1222899 - Handle geolocation-device-events callback. r=kchen (a33bcf4297) - Bug 1237831 - Update GonkGPSGeolocationProvider.cpp to use B2G-style. r=jst (d389eedf47) - Bug 1245033 - Build break in dom/system/gonk/GonkGPSGeolocationProvider.cpp:541:126: error: format '%d' expects argument of type 'int', but argument 5 has type 'nsresult'. r=fabrice (ecde789edf) - Bug 1264287: Convert Wifi to use |UniquePtr|, r=nfroyd (9bad7792bf) - Bug 1267577 - Move nsRunnable to mozilla::Runnable. r=gsvelto (f58e2161f2) - Bug 1210370 - Close wpa_supplicant before we shutdown nsIWifiProxyService. r=mrbkap (5cd4dce58f) - Bug 1218629 - Save audio volume for each device to setting db r=alwu (2f1847dd6f) - Bug 1249437 - Remove workaround of volume control r=alwu (13cd144a89) - Bug 1268432: Replace |Task| with |Runnable| in B2G code r=fabrice (bcc768e9cb) - Bug 1226483 - Add ASSERT check to AudioManager::SelectDeviceFromDevices() r=alwu (446e8f634e) - Bug 1229234 - Enable audio_is_output_device() on ICS r=alwu (84aae07f23) - Bug 1267369 - Only generate typelib data for scriptable interfaces; r=khuey (e49b44c9ce) - Bug 1155969 - Make runtests.py flake8 compliant. r=ted (1de456b206) - Bug 1266569 - Avoid including the ChromeUtils binding in Base64.h. r=froydnj (7ba39a7687)
375 lines
9.5 KiB
C++
375 lines
9.5 KiB
C++
/* 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 "nsWhitespaceTokenizer.h"
|
|
#include "nsXULAppAPI.h"
|
|
#include "nsAutoPtr.h"
|
|
#include "nsString.h"
|
|
#include "nsThreadUtils.h"
|
|
#include "mozilla/RefPtr.h"
|
|
#include "mozilla/Snprintf.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()
|
|
{
|
|
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];
|
|
}
|
|
|
|
snprintf_literal(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
|