mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-01 22:55:23 +00:00
Merge m-c to fx-team. a=merge
This commit is contained in:
commit
1241218f33
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e5c1905b0144a855537fd857d62ec7a3393bb334"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="6e35b0948c42a4398b8a5916015de167121683a1"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e5c1905b0144a855537fd857d62ec7a3393bb334"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="6e35b0948c42a4398b8a5916015de167121683a1"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9a9797062c6001d6346504161c51187a2968466b"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e5c1905b0144a855537fd857d62ec7a3393bb334"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="6e35b0948c42a4398b8a5916015de167121683a1"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="bdd03caf084e1b9279155bd232bc718a38c47cbc"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e5c1905b0144a855537fd857d62ec7a3393bb334"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="6e35b0948c42a4398b8a5916015de167121683a1"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e5c1905b0144a855537fd857d62ec7a3393bb334"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="6e35b0948c42a4398b8a5916015de167121683a1"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e5c1905b0144a855537fd857d62ec7a3393bb334"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="6e35b0948c42a4398b8a5916015de167121683a1"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9a9797062c6001d6346504161c51187a2968466b"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e5c1905b0144a855537fd857d62ec7a3393bb334"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="6e35b0948c42a4398b8a5916015de167121683a1"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e5c1905b0144a855537fd857d62ec7a3393bb334"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="6e35b0948c42a4398b8a5916015de167121683a1"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="bdd03caf084e1b9279155bd232bc718a38c47cbc"/>
|
||||
|
@ -1,9 +1,9 @@
|
||||
{
|
||||
"git": {
|
||||
"git_revision": "e5c1905b0144a855537fd857d62ec7a3393bb334",
|
||||
"git_revision": "6e35b0948c42a4398b8a5916015de167121683a1",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "97f0671809608b83775857fce9a7f7eba056d5d3",
|
||||
"revision": "14e42674734ab45c745a6b431cac067fab6f7a77",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e5c1905b0144a855537fd857d62ec7a3393bb334"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="6e35b0948c42a4398b8a5916015de167121683a1"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="bdd03caf084e1b9279155bd232bc718a38c47cbc"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="e5c1905b0144a855537fd857d62ec7a3393bb334"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="6e35b0948c42a4398b8a5916015de167121683a1"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -734,7 +734,6 @@ BrowserGlue.prototype = {
|
||||
LightweightThemeManager.addBuiltInTheme({
|
||||
id: "firefox-devedition@mozilla.org",
|
||||
name: themeName,
|
||||
accentcolor: "transparent",
|
||||
headerURL: "resource:///chrome/browser/content/browser/defaultthemes/devedition.header.png",
|
||||
iconURL: "resource:///chrome/browser/content/browser/defaultthemes/devedition.icon.png",
|
||||
author: vendorShortName,
|
||||
|
@ -1415,6 +1415,8 @@ WebConsoleFrame.prototype = {
|
||||
let severity = 'error';
|
||||
if (aScriptError.warning || aScriptError.strict) {
|
||||
severity = 'warning';
|
||||
} else if (aScriptError.info) {
|
||||
severity = 'log';
|
||||
}
|
||||
|
||||
let category = 'js';
|
||||
|
@ -8954,11 +8954,8 @@ dnl ========================================================
|
||||
# builds. Bugs to enable:
|
||||
#
|
||||
# Android: bug 864843
|
||||
# B2G: bug 866301
|
||||
|
||||
if test "$MOZ_WIDGET_TOOLKIT" = "android" ||
|
||||
test "$MOZ_BUILD_APP" = "b2g" ||
|
||||
test "$MOZ_BUILD_APP" = "b2g/dev"; then
|
||||
if test "$MOZ_WIDGET_TOOLKIT" = "android"; then
|
||||
_INTL_API=no
|
||||
else
|
||||
_INTL_API=yes
|
||||
|
@ -497,7 +497,21 @@ enum BluetoothHandsfreeWbsConfig {
|
||||
};
|
||||
|
||||
class BluetoothSignal;
|
||||
typedef mozilla::Observer<BluetoothSignal> BluetoothSignalObserver;
|
||||
|
||||
class BluetoothSignalObserver : public mozilla::Observer<BluetoothSignal>
|
||||
{
|
||||
public:
|
||||
BluetoothSignalObserver() : mSignalRegistered(false)
|
||||
{ }
|
||||
|
||||
void SetSignalRegistered(bool aSignalRegistered)
|
||||
{
|
||||
mSignalRegistered = aSignalRegistered;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool mSignalRegistered;
|
||||
};
|
||||
|
||||
// Enums for object types, currently used for shared function lookups
|
||||
// (get/setproperty, etc...). Possibly discernable via dbus paths, but this
|
||||
|
@ -96,6 +96,34 @@ GeneratePathFromGattId(const BluetoothGattId& aId,
|
||||
GeneratePathFromGattId(aId, aPath, uuidStr);
|
||||
}
|
||||
|
||||
void
|
||||
RegisterBluetoothSignalHandler(const nsAString& aPath,
|
||||
BluetoothSignalObserver* aHandler)
|
||||
{
|
||||
MOZ_ASSERT(!aPath.IsEmpty());
|
||||
MOZ_ASSERT(aHandler);
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
|
||||
bs->RegisterBluetoothSignalHandler(aPath, aHandler);
|
||||
aHandler->SetSignalRegistered(true);
|
||||
}
|
||||
|
||||
void
|
||||
UnregisterBluetoothSignalHandler(const nsAString& aPath,
|
||||
BluetoothSignalObserver* aHandler)
|
||||
{
|
||||
MOZ_ASSERT(!aPath.IsEmpty());
|
||||
MOZ_ASSERT(aHandler);
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
|
||||
bs->UnregisterBluetoothSignalHandler(aPath, aHandler);
|
||||
aHandler->SetSignalRegistered(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* |SetJsObject| is an internal function used by |BroadcastSystemMessage| only
|
||||
*/
|
||||
|
@ -77,6 +77,32 @@ void
|
||||
GeneratePathFromGattId(const BluetoothGattId& aId,
|
||||
nsAString& aPath);
|
||||
|
||||
//
|
||||
// Register/Unregister bluetooth signal handlers
|
||||
//
|
||||
|
||||
/**
|
||||
* Register the bluetooth signal handler.
|
||||
*
|
||||
* @param aPath Path of the signal to be registered.
|
||||
* @param aHandler The message handler object to be added into the observer
|
||||
* list. Note that this function doesn't take references to it.
|
||||
*/
|
||||
void
|
||||
RegisterBluetoothSignalHandler(const nsAString& aPath,
|
||||
BluetoothSignalObserver* aHandler);
|
||||
|
||||
/**
|
||||
* Unregister the bluetooth signal handler.
|
||||
*
|
||||
* @param aPath Path of the signal to be unregistered.
|
||||
* @param aHandler The message handler object to be removed from the observer
|
||||
* list. Note that this function doesn't take references to it.
|
||||
*/
|
||||
void
|
||||
UnregisterBluetoothSignalHandler(const nsAString& aPath,
|
||||
BluetoothSignalObserver* aHandler);
|
||||
|
||||
//
|
||||
// Broadcast system message
|
||||
//
|
||||
|
@ -43,7 +43,7 @@ EnsureBluetoothSocketHalLoad()
|
||||
}
|
||||
|
||||
class mozilla::dom::bluetooth::DroidSocketImpl : public ipc::UnixFdWatcher
|
||||
, protected SocketIOBase
|
||||
, protected DataSocketIO
|
||||
{
|
||||
public:
|
||||
/* The connection status in DroidSocketImpl indicates the current
|
||||
@ -75,7 +75,6 @@ public:
|
||||
|
||||
DroidSocketImpl(MessageLoop* aIOLoop, BluetoothSocket* aConsumer)
|
||||
: ipc::UnixFdWatcher(aIOLoop)
|
||||
, SocketIOBase(MAX_READ_SIZE)
|
||||
, mConsumer(aConsumer)
|
||||
, mShuttingDownOnIOThread(false)
|
||||
, mConnectionStatus(SOCKET_IS_DISCONNECTED)
|
||||
@ -135,16 +134,28 @@ public:
|
||||
AddWatchers(WRITE_WATCHER, false);
|
||||
}
|
||||
|
||||
SocketConsumerBase* GetConsumer()
|
||||
BluetoothSocket* GetBluetoothSocket()
|
||||
{
|
||||
return mConsumer.get();
|
||||
}
|
||||
|
||||
DataSocket* GetDataSocket()
|
||||
{
|
||||
return GetBluetoothSocket();
|
||||
}
|
||||
|
||||
SocketBase* GetSocketBase()
|
||||
{
|
||||
return GetConsumer();
|
||||
return GetDataSocket();
|
||||
}
|
||||
|
||||
// Methods for |DataSocket|
|
||||
//
|
||||
|
||||
nsresult QueryReceiveBuffer(UnixSocketIOBuffer** aBuffer);
|
||||
void ConsumeBuffer();
|
||||
void DiscardBuffer();
|
||||
|
||||
/**
|
||||
* Consumer pointer. Non-thread safe RefPtr, so should only be manipulated
|
||||
* directly from main thread. All non-main-thread accesses should happen with
|
||||
@ -153,6 +164,8 @@ public:
|
||||
RefPtr<BluetoothSocket> mConsumer;
|
||||
|
||||
private:
|
||||
class ReceiveRunnable;
|
||||
|
||||
/**
|
||||
* libevent triggered functions that reads data from socket when available and
|
||||
* guarenteed non-blocking. Only to be called on IO thread.
|
||||
@ -180,6 +193,11 @@ private:
|
||||
bool mShuttingDownOnIOThread;
|
||||
|
||||
ConnectionStatus mConnectionStatus;
|
||||
|
||||
/**
|
||||
* I/O buffer for received data
|
||||
*/
|
||||
nsAutoPtr<UnixSocketRawData> mBuffer;
|
||||
};
|
||||
|
||||
class SocketConnectTask final : public SocketIOTask<DroidSocketImpl>
|
||||
@ -492,6 +510,69 @@ DroidSocketImpl::OnSocketCanConnectWithoutBlocking(int aFd)
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
DroidSocketImpl::QueryReceiveBuffer(
|
||||
UnixSocketIOBuffer** aBuffer)
|
||||
{
|
||||
MOZ_ASSERT(aBuffer);
|
||||
|
||||
if (!mBuffer) {
|
||||
mBuffer = new UnixSocketRawData(MAX_READ_SIZE);
|
||||
}
|
||||
*aBuffer = mBuffer.get();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* |ReceiveRunnable| transfers data received on the I/O thread
|
||||
* to an instance of |BluetoothSocket| on the main thread.
|
||||
*/
|
||||
class DroidSocketImpl::ReceiveRunnable final
|
||||
: public SocketIORunnable<DroidSocketImpl>
|
||||
{
|
||||
public:
|
||||
ReceiveRunnable(DroidSocketImpl* aIO, UnixSocketBuffer* aBuffer)
|
||||
: SocketIORunnable<DroidSocketImpl>(aIO)
|
||||
, mBuffer(aBuffer)
|
||||
{ }
|
||||
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
DroidSocketImpl* io = SocketIORunnable<DroidSocketImpl>::GetIO();
|
||||
|
||||
if (NS_WARN_IF(io->IsShutdownOnMainThread())) {
|
||||
// Since we've already explicitly closed and the close
|
||||
// happened before this, this isn't really an error.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
BluetoothSocket* bluetoothSocket = io->GetBluetoothSocket();
|
||||
MOZ_ASSERT(bluetoothSocket);
|
||||
|
||||
bluetoothSocket->ReceiveSocketData(mBuffer);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsAutoPtr<UnixSocketBuffer> mBuffer;
|
||||
};
|
||||
|
||||
void
|
||||
DroidSocketImpl::ConsumeBuffer()
|
||||
{
|
||||
NS_DispatchToMainThread(new ReceiveRunnable(this, mBuffer.forget()));
|
||||
}
|
||||
|
||||
void
|
||||
DroidSocketImpl::DiscardBuffer()
|
||||
{
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
BluetoothSocket::BluetoothSocket(BluetoothSocketObserver* aObserver,
|
||||
BluetoothSocketType aType,
|
||||
bool aAuth,
|
||||
|
@ -8,7 +8,7 @@
|
||||
#define mozilla_dom_bluetooth_BluetoothSocket_h
|
||||
|
||||
#include "BluetoothCommon.h"
|
||||
#include "mozilla/ipc/SocketBase.h"
|
||||
#include "mozilla/ipc/DataSocket.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
@ -16,7 +16,7 @@ class BluetoothSocketObserver;
|
||||
class BluetoothSocketResultHandler;
|
||||
class DroidSocketImpl;
|
||||
|
||||
class BluetoothSocket : public mozilla::ipc::SocketConsumerBase
|
||||
class BluetoothSocket : public mozilla::ipc::DataSocket
|
||||
{
|
||||
public:
|
||||
BluetoothSocket(BluetoothSocketObserver* aObserver,
|
||||
@ -34,13 +34,19 @@ public:
|
||||
|
||||
void CloseSocket() override;
|
||||
|
||||
/**
|
||||
* Method to be called whenever data is received. This is only called on the
|
||||
* main thread.
|
||||
*
|
||||
* @param aBuffer Data received from the socket.
|
||||
*/
|
||||
void ReceiveSocketData(nsAutoPtr<mozilla::ipc::UnixSocketBuffer>& aBuffer);
|
||||
|
||||
void SendSocketData(mozilla::ipc::UnixSocketIOBuffer* aBuffer) override;
|
||||
|
||||
virtual void OnConnectSuccess() override;
|
||||
virtual void OnConnectError() override;
|
||||
virtual void OnDisconnect() override;
|
||||
virtual void ReceiveSocketData(
|
||||
nsAutoPtr<mozilla::ipc::UnixSocketBuffer>& aBuffer) override;
|
||||
|
||||
inline void GetAddress(nsAString& aDeviceAddress)
|
||||
{
|
||||
|
@ -37,8 +37,8 @@ class BluetoothService;
|
||||
* BluetoothParent
|
||||
******************************************************************************/
|
||||
|
||||
class BluetoothParent : public PBluetoothParent,
|
||||
public mozilla::Observer<BluetoothSignal>
|
||||
class BluetoothParent : public PBluetoothParent
|
||||
, public BluetoothSignalObserver
|
||||
{
|
||||
friend class mozilla::dom::ContentParent;
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "BluetoothReplyRunnable.h"
|
||||
#include "BluetoothService.h"
|
||||
#include "BluetoothUtils.h"
|
||||
#include "DOMRequest.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIPrincipal.h"
|
||||
@ -29,9 +30,30 @@ using namespace mozilla::dom;
|
||||
|
||||
USING_BLUETOOTH_NAMESPACE
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(BluetoothAdapter, DOMEventTargetHelper,
|
||||
mDevices, mDiscoveryHandleInUse,
|
||||
mPairingReqs)
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothAdapter)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothAdapter,
|
||||
DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDevices)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDiscoveryHandleInUse)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPairingReqs)
|
||||
|
||||
/**
|
||||
* Unregister the bluetooth signal handler after unlinked.
|
||||
*
|
||||
* This is needed to avoid ending up with exposing a deleted object to JS or
|
||||
* accessing deleted objects while receiving signals from parent process
|
||||
* after unlinked. Please see Bug 1138267 for detail informations.
|
||||
*/
|
||||
UnregisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_ADAPTER), tmp);
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothAdapter,
|
||||
DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDevices)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDiscoveryHandleInUse)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPairingReqs)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
// QueryInterface implementation for BluetoothAdapter
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothAdapter)
|
||||
@ -210,17 +232,12 @@ BluetoothAdapter::BluetoothAdapter(nsPIDOMWindow* aWindow,
|
||||
SetPropertyByValue(values[i]);
|
||||
}
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
bs->RegisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_ADAPTER), this);
|
||||
RegisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_ADAPTER), this);
|
||||
}
|
||||
|
||||
BluetoothAdapter::~BluetoothAdapter()
|
||||
{
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
// We can be null on shutdown, where this might happen
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
bs->UnregisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_ADAPTER), this);
|
||||
UnregisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_ADAPTER), this);
|
||||
}
|
||||
|
||||
void
|
||||
@ -228,9 +245,7 @@ BluetoothAdapter::DisconnectFromOwner()
|
||||
{
|
||||
DOMEventTargetHelper::DisconnectFromOwner();
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
bs->UnregisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_ADAPTER), this);
|
||||
UnregisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_ADAPTER), this);
|
||||
}
|
||||
|
||||
void
|
||||
@ -321,9 +336,8 @@ BluetoothAdapter::Create(nsPIDOMWindow* aWindow, const BluetoothValue& aValue)
|
||||
void
|
||||
BluetoothAdapter::Notify(const BluetoothSignal& aData)
|
||||
{
|
||||
InfallibleTArray<BluetoothNamedValue> arr;
|
||||
|
||||
BT_LOGD("[A] %s", NS_ConvertUTF16toUTF8(aData.name()).get());
|
||||
NS_ENSURE_TRUE_VOID(mSignalRegistered);
|
||||
|
||||
BluetoothValue v = aData.value();
|
||||
if (aData.name().EqualsLiteral("PropertyChanged")) {
|
||||
|
@ -184,7 +184,7 @@ private:
|
||||
~BluetoothAdapter();
|
||||
|
||||
/**
|
||||
* Set adapter properties according to properties array
|
||||
* Set adapter properties according to properties array.
|
||||
*
|
||||
* @param aValue [in] Properties array to set with
|
||||
*/
|
||||
|
@ -21,10 +21,29 @@ using namespace mozilla::dom;
|
||||
|
||||
USING_BLUETOOTH_NAMESPACE
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(BluetoothDevice,
|
||||
DOMEventTargetHelper,
|
||||
mCod,
|
||||
mGatt)
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothDevice)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothDevice,
|
||||
DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCod)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mGatt)
|
||||
|
||||
/**
|
||||
* Unregister the bluetooth signal handler after unlinked.
|
||||
*
|
||||
* This is needed to avoid ending up with exposing a deleted object to JS or
|
||||
* accessing deleted objects while receiving signals from parent process
|
||||
* after unlinked. Please see Bug 1138267 for detail informations.
|
||||
*/
|
||||
UnregisterBluetoothSignalHandler(tmp->mAddress, tmp);
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothDevice,
|
||||
DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCod)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGatt)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothDevice)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
@ -91,27 +110,19 @@ BluetoothDevice::BluetoothDevice(nsPIDOMWindow* aWindow,
|
||||
SetPropertyByValue(values[i]);
|
||||
}
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
bs->RegisterBluetoothSignalHandler(mAddress, this);
|
||||
RegisterBluetoothSignalHandler(mAddress, this);
|
||||
}
|
||||
|
||||
BluetoothDevice::~BluetoothDevice()
|
||||
{
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
// bs can be null on shutdown, where destruction might happen.
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
bs->UnregisterBluetoothSignalHandler(mAddress, this);
|
||||
UnregisterBluetoothSignalHandler(mAddress, this);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDevice::DisconnectFromOwner()
|
||||
{
|
||||
DOMEventTargetHelper::DisconnectFromOwner();
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
bs->UnregisterBluetoothSignalHandler(mAddress, this);
|
||||
UnregisterBluetoothSignalHandler(mAddress, this);
|
||||
}
|
||||
|
||||
BluetoothDeviceType
|
||||
@ -199,6 +210,7 @@ void
|
||||
BluetoothDevice::Notify(const BluetoothSignal& aData)
|
||||
{
|
||||
BT_LOGD("[D] %s", NS_ConvertUTF16toUTF8(aData.name()).get());
|
||||
NS_ENSURE_TRUE_VOID(mSignalRegistered);
|
||||
|
||||
BluetoothValue v = aData.value();
|
||||
if (aData.name().EqualsLiteral("PropertyChanged")) {
|
||||
|
@ -21,9 +21,26 @@ using namespace mozilla::dom;
|
||||
|
||||
USING_BLUETOOTH_NAMESPACE
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(BluetoothGatt,
|
||||
DOMEventTargetHelper,
|
||||
mServices)
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothGatt)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothGatt,
|
||||
DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mServices)
|
||||
|
||||
/**
|
||||
* Unregister the bluetooth signal handler after unlinked.
|
||||
*
|
||||
* This is needed to avoid ending up with exposing a deleted object to JS or
|
||||
* accessing deleted objects while receiving signals from parent process
|
||||
* after unlinked. Please see Bug 1138267 for detail informations.
|
||||
*/
|
||||
UnregisterBluetoothSignalHandler(tmp->mAppUuid, tmp);
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothGatt,
|
||||
DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServices)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothGatt)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
@ -56,7 +73,7 @@ BluetoothGatt::~BluetoothGatt()
|
||||
bs->UnregisterGattClientInternal(mClientIf, result);
|
||||
}
|
||||
|
||||
bs->UnregisterBluetoothSignalHandler(mAppUuid, this);
|
||||
UnregisterBluetoothSignalHandler(mAppUuid, this);
|
||||
}
|
||||
|
||||
void
|
||||
@ -94,7 +111,7 @@ BluetoothGatt::DisconnectFromOwner()
|
||||
bs->UnregisterGattClientInternal(mClientIf, result);
|
||||
}
|
||||
|
||||
bs->UnregisterBluetoothSignalHandler(mAppUuid, this);
|
||||
UnregisterBluetoothSignalHandler(mAppUuid, this);
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
@ -122,7 +139,7 @@ BluetoothGatt::Connect(ErrorResult& aRv)
|
||||
BT_ENSURE_TRUE_REJECT(!mAppUuid.IsEmpty(),
|
||||
promise,
|
||||
NS_ERROR_DOM_OPERATION_ERR);
|
||||
bs->RegisterBluetoothSignalHandler(mAppUuid, this);
|
||||
RegisterBluetoothSignalHandler(mAppUuid, this);
|
||||
}
|
||||
|
||||
UpdateConnectionState(BluetoothConnectionState::Connecting);
|
||||
@ -323,6 +340,7 @@ void
|
||||
BluetoothGatt::Notify(const BluetoothSignal& aData)
|
||||
{
|
||||
BT_LOGD("[D] %s", NS_ConvertUTF16toUTF8(aData.name()).get());
|
||||
NS_ENSURE_TRUE_VOID(mSignalRegistered);
|
||||
|
||||
BluetoothValue v = aData.value();
|
||||
if (aData.name().EqualsLiteral("ClientRegistered")) {
|
||||
|
@ -20,8 +20,34 @@ using namespace mozilla::dom;
|
||||
|
||||
USING_BLUETOOTH_NAMESPACE
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(
|
||||
BluetoothGattCharacteristic, mOwner, mService, mDescriptors)
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothGattCharacteristic)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(BluetoothGattCharacteristic)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mService)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDescriptors)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
||||
|
||||
/**
|
||||
* Unregister the bluetooth signal handler after unlinked.
|
||||
*
|
||||
* This is needed to avoid ending up with exposing a deleted object to JS or
|
||||
* accessing deleted objects while receiving signals from parent process
|
||||
* after unlinked. Please see Bug 1138267 for detail informations.
|
||||
*/
|
||||
nsString path;
|
||||
GeneratePathFromGattId(tmp->mCharId, path);
|
||||
UnregisterBluetoothSignalHandler(path, tmp);
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(BluetoothGattCharacteristic)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mService)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDescriptors)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(BluetoothGattCharacteristic)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(BluetoothGattCharacteristic)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(BluetoothGattCharacteristic)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BluetoothGattCharacteristic)
|
||||
@ -42,24 +68,18 @@ BluetoothGattCharacteristic::BluetoothGattCharacteristic(
|
||||
MOZ_ASSERT(aOwner);
|
||||
MOZ_ASSERT(mService);
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
|
||||
// Generate bluetooth signal path and a string representation to provide uuid
|
||||
// of this characteristic to applications
|
||||
nsString path;
|
||||
GeneratePathFromGattId(mCharId, path, mUuidStr);
|
||||
bs->RegisterBluetoothSignalHandler(path, this);
|
||||
RegisterBluetoothSignalHandler(path, this);
|
||||
}
|
||||
|
||||
BluetoothGattCharacteristic::~BluetoothGattCharacteristic()
|
||||
{
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
|
||||
nsString path;
|
||||
GeneratePathFromGattId(mCharId, path);
|
||||
bs->UnregisterBluetoothSignalHandler(path, this);
|
||||
UnregisterBluetoothSignalHandler(path, this);
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
@ -150,6 +170,7 @@ void
|
||||
BluetoothGattCharacteristic::Notify(const BluetoothSignal& aData)
|
||||
{
|
||||
BT_LOGD("[D] %s", NS_ConvertUTF16toUTF8(aData.name()).get());
|
||||
NS_ENSURE_TRUE_VOID(mSignalRegistered);
|
||||
|
||||
BluetoothValue v = aData.value();
|
||||
if (aData.name().EqualsLiteral("DescriptorsDiscovered")) {
|
||||
|
@ -19,8 +19,32 @@ using namespace mozilla::dom;
|
||||
|
||||
USING_BLUETOOTH_NAMESPACE
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(
|
||||
BluetoothGattDescriptor, mOwner, mCharacteristic)
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothGattDescriptor)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(BluetoothGattDescriptor)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCharacteristic)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
||||
|
||||
/**
|
||||
* Unregister the bluetooth signal handler after unlinked.
|
||||
*
|
||||
* This is needed to avoid ending up with exposing a deleted object to JS or
|
||||
* accessing deleted objects while receiving signals from parent process
|
||||
* after unlinked. Please see Bug 1138267 for detail informations.
|
||||
*/
|
||||
nsString path;
|
||||
GeneratePathFromGattId(tmp->mDescriptorId, path);
|
||||
UnregisterBluetoothSignalHandler(path, tmp);
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(BluetoothGattDescriptor)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCharacteristic)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(BluetoothGattDescriptor)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(BluetoothGattDescriptor)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(BluetoothGattDescriptor)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BluetoothGattDescriptor)
|
||||
@ -39,24 +63,18 @@ BluetoothGattDescriptor::BluetoothGattDescriptor(
|
||||
MOZ_ASSERT(aOwner);
|
||||
MOZ_ASSERT(aCharacteristic);
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
|
||||
// Generate bluetooth signal path and a string representation to provide uuid
|
||||
// of this descriptor to applications
|
||||
nsString path;
|
||||
GeneratePathFromGattId(mDescriptorId, path, mUuidStr);
|
||||
bs->RegisterBluetoothSignalHandler(path, this);
|
||||
RegisterBluetoothSignalHandler(path, this);
|
||||
}
|
||||
|
||||
BluetoothGattDescriptor::~BluetoothGattDescriptor()
|
||||
{
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
|
||||
nsString path;
|
||||
GeneratePathFromGattId(mDescriptorId, path);
|
||||
bs->UnregisterBluetoothSignalHandler(path, this);
|
||||
UnregisterBluetoothSignalHandler(path, this);
|
||||
}
|
||||
|
||||
void
|
||||
@ -72,6 +90,7 @@ void
|
||||
BluetoothGattDescriptor::Notify(const BluetoothSignal& aData)
|
||||
{
|
||||
BT_LOGD("[D] %s", NS_ConvertUTF16toUTF8(aData.name()).get());
|
||||
NS_ENSURE_TRUE_VOID(mSignalRegistered);
|
||||
|
||||
BluetoothValue v = aData.value();
|
||||
if (aData.name().EqualsLiteral("DescriptorValueUpdated")) {
|
||||
|
@ -17,8 +17,34 @@ using namespace mozilla::dom;
|
||||
|
||||
USING_BLUETOOTH_NAMESPACE
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(
|
||||
BluetoothGattService, mOwner, mIncludedServices, mCharacteristics)
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothGattService)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(BluetoothGattService)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIncludedServices)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCharacteristics)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
||||
|
||||
/**
|
||||
* Unregister the bluetooth signal handler after unlinked.
|
||||
*
|
||||
* This is needed to avoid ending up with exposing a deleted object to JS or
|
||||
* accessing deleted objects while receiving signals from parent process
|
||||
* after unlinked. Please see Bug 1138267 for detail informations.
|
||||
*/
|
||||
nsString path;
|
||||
GeneratePathFromGattId(tmp->mServiceId.mId, path);
|
||||
UnregisterBluetoothSignalHandler(path, tmp);
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(BluetoothGattService)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIncludedServices)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCharacteristics)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(BluetoothGattService)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(BluetoothGattService)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(BluetoothGattService)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BluetoothGattService)
|
||||
@ -36,24 +62,18 @@ BluetoothGattService::BluetoothGattService(
|
||||
MOZ_ASSERT(aOwner);
|
||||
MOZ_ASSERT(!mAppUuid.IsEmpty());
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
|
||||
// Generate bluetooth signal path and a string representation to provide
|
||||
// uuid of this service to applications
|
||||
nsString path;
|
||||
GeneratePathFromGattId(mServiceId.mId, path, mUuidStr);
|
||||
bs->RegisterBluetoothSignalHandler(path, this);
|
||||
RegisterBluetoothSignalHandler(path, this);
|
||||
}
|
||||
|
||||
BluetoothGattService::~BluetoothGattService()
|
||||
{
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
|
||||
nsString path;
|
||||
GeneratePathFromGattId(mServiceId.mId, path);
|
||||
bs->UnregisterBluetoothSignalHandler(path, this);
|
||||
UnregisterBluetoothSignalHandler(path, this);
|
||||
}
|
||||
|
||||
void
|
||||
@ -95,6 +115,7 @@ void
|
||||
BluetoothGattService::Notify(const BluetoothSignal& aData)
|
||||
{
|
||||
BT_LOGD("[D] %s", NS_ConvertUTF16toUTF8(aData.name()).get());
|
||||
NS_ENSURE_TRUE_VOID(mSignalRegistered);
|
||||
|
||||
BluetoothValue v = aData.value();
|
||||
if (aData.name().EqualsLiteral("IncludedServicesDiscovered")) {
|
||||
|
@ -5,11 +5,12 @@
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "BluetoothManager.h"
|
||||
#include "BluetoothAdapter.h"
|
||||
#include "BluetoothService.h"
|
||||
#include "BluetoothReplyRunnable.h"
|
||||
#include "BluetoothService.h"
|
||||
#include "BluetoothUtils.h"
|
||||
|
||||
#include "mozilla/dom/bluetooth/BluetoothAdapter.h"
|
||||
#include "mozilla/dom/bluetooth/BluetoothManager.h"
|
||||
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
|
||||
#include "mozilla/dom/BluetoothManager2Binding.h"
|
||||
#include "mozilla/Services.h"
|
||||
@ -22,7 +23,27 @@ using namespace mozilla;
|
||||
|
||||
USING_BLUETOOTH_NAMESPACE
|
||||
|
||||
// QueryInterface implementation for BluetoothManager
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothManager)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothManager,
|
||||
DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mAdapters)
|
||||
|
||||
/**
|
||||
* Unregister the bluetooth signal handler after unlinked.
|
||||
*
|
||||
* This is needed to avoid ending up with exposing a deleted object to JS or
|
||||
* accessing deleted objects while receiving signals from parent process
|
||||
* after unlinked. Please see Bug 1138267 for detail informations.
|
||||
*/
|
||||
UnregisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_MANAGER), tmp);
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothManager,
|
||||
DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAdapters)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothManager)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
@ -92,7 +113,7 @@ BluetoothManager::BluetoothManager(nsPIDOMWindow *aWindow)
|
||||
{
|
||||
MOZ_ASSERT(aWindow);
|
||||
|
||||
ListenToBluetoothSignal(true);
|
||||
RegisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_MANAGER), this);
|
||||
BT_API2_LOGR("aWindow %p", aWindow);
|
||||
|
||||
// Query adapters list from bluetooth backend
|
||||
@ -105,27 +126,14 @@ BluetoothManager::BluetoothManager(nsPIDOMWindow *aWindow)
|
||||
|
||||
BluetoothManager::~BluetoothManager()
|
||||
{
|
||||
ListenToBluetoothSignal(false);
|
||||
UnregisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_MANAGER), this);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothManager::DisconnectFromOwner()
|
||||
{
|
||||
DOMEventTargetHelper::DisconnectFromOwner();
|
||||
ListenToBluetoothSignal(false);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothManager::ListenToBluetoothSignal(bool aStart)
|
||||
{
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
|
||||
if (aStart) {
|
||||
bs->RegisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_MANAGER), this);
|
||||
} else {
|
||||
bs->UnregisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_MANAGER), this);
|
||||
}
|
||||
UnregisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_MANAGER), this);
|
||||
}
|
||||
|
||||
BluetoothAdapter*
|
||||
@ -265,6 +273,7 @@ void
|
||||
BluetoothManager::Notify(const BluetoothSignal& aData)
|
||||
{
|
||||
BT_LOGD("[M] %s", NS_ConvertUTF16toUTF8(aData.name()).get());
|
||||
NS_ENSURE_TRUE_VOID(mSignalRegistered);
|
||||
|
||||
if (aData.name().EqualsLiteral("AdapterAdded")) {
|
||||
HandleAdapterAdded(aData.value());
|
||||
|
@ -25,6 +25,8 @@ class BluetoothManager final : public DOMEventTargetHelper
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(BluetoothManager,
|
||||
DOMEventTargetHelper)
|
||||
|
||||
/****************************************************************************
|
||||
* Event Handlers
|
||||
@ -79,13 +81,6 @@ private:
|
||||
BluetoothManager(nsPIDOMWindow* aWindow);
|
||||
~BluetoothManager();
|
||||
|
||||
/**
|
||||
* Start/Stop listening to bluetooth signal.
|
||||
*
|
||||
* @param aStart [in] Whether to start or stop listening to bluetooth signal
|
||||
*/
|
||||
void ListenToBluetoothSignal(bool aStart);
|
||||
|
||||
/**
|
||||
* Check whether default adapter exists.
|
||||
*/
|
||||
|
@ -4,12 +4,13 @@
|
||||
* 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 "BluetoothService.h"
|
||||
#include "BluetoothUtils.h"
|
||||
#include "mozilla/dom/bluetooth/BluetoothPairingListener.h"
|
||||
#include "mozilla/dom/bluetooth/BluetoothPairingHandle.h"
|
||||
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
|
||||
#include "mozilla/dom/BluetoothPairingEvent.h"
|
||||
#include "mozilla/dom/BluetoothPairingListenerBinding.h"
|
||||
#include "BluetoothService.h"
|
||||
|
||||
USING_BLUETOOTH_NAMESPACE
|
||||
|
||||
@ -42,11 +43,8 @@ BluetoothPairingListener::Create(nsPIDOMWindow* aWindow)
|
||||
|
||||
BluetoothPairingListener::~BluetoothPairingListener()
|
||||
{
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
// It can be nullptr on shutdown.
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
bs->UnregisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_PAIRING_LISTENER),
|
||||
this);
|
||||
UnregisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_PAIRING_LISTENER),
|
||||
this);
|
||||
}
|
||||
|
||||
void
|
||||
@ -118,11 +116,8 @@ void
|
||||
BluetoothPairingListener::DisconnectFromOwner()
|
||||
{
|
||||
DOMEventTargetHelper::DisconnectFromOwner();
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
bs->UnregisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_PAIRING_LISTENER),
|
||||
this);
|
||||
UnregisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_PAIRING_LISTENER),
|
||||
this);
|
||||
}
|
||||
|
||||
void
|
||||
@ -153,10 +148,8 @@ BluetoothPairingListener::TryListeningToBluetoothSignal()
|
||||
}
|
||||
|
||||
// Start listening to bluetooth signal to handle pairing requests
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
NS_ENSURE_TRUE_VOID(bs);
|
||||
bs->RegisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_PAIRING_LISTENER),
|
||||
this);
|
||||
RegisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_PAIRING_LISTENER),
|
||||
this);
|
||||
|
||||
mHasListenedToSignal = true;
|
||||
}
|
||||
|
@ -37,8 +37,8 @@ class BluetoothService;
|
||||
* BluetoothParent
|
||||
******************************************************************************/
|
||||
|
||||
class BluetoothParent : public PBluetoothParent,
|
||||
public mozilla::Observer<BluetoothSignal>
|
||||
class BluetoothParent : public PBluetoothParent
|
||||
, public BluetoothSignalObserver
|
||||
{
|
||||
friend class mozilla::dom::ContentParent;
|
||||
|
||||
|
@ -25,7 +25,7 @@ static const size_t MAX_READ_SIZE = 1 << 16;
|
||||
|
||||
class BluetoothSocket::BluetoothSocketIO final
|
||||
: public UnixSocketWatcher
|
||||
, protected SocketIOBase
|
||||
, protected DataSocketIO
|
||||
{
|
||||
public:
|
||||
BluetoothSocketIO(MessageLoop* mIOLoop,
|
||||
@ -34,9 +34,11 @@ public:
|
||||
const nsACString& aAddress);
|
||||
~BluetoothSocketIO();
|
||||
|
||||
void GetSocketAddr(nsAString& aAddrStr) const;
|
||||
SocketConsumerBase* GetConsumer();
|
||||
SocketBase* GetSocketBase();
|
||||
void GetSocketAddr(nsAString& aAddrStr) const;
|
||||
|
||||
BluetoothSocket* GetBluetoothSocket();
|
||||
DataSocket* GetDataSocket();
|
||||
SocketBase* GetSocketBase();
|
||||
|
||||
// Shutdown state
|
||||
//
|
||||
@ -80,7 +82,16 @@ public:
|
||||
void OnSocketCanReceiveWithoutBlocking() override;
|
||||
void OnSocketCanSendWithoutBlocking() override;
|
||||
|
||||
// Methods for |DataSocket|
|
||||
//
|
||||
|
||||
nsresult QueryReceiveBuffer(UnixSocketIOBuffer** aBuffer);
|
||||
void ConsumeBuffer();
|
||||
void DiscardBuffer();
|
||||
|
||||
private:
|
||||
class ReceiveRunnable;
|
||||
|
||||
void FireSocketError();
|
||||
|
||||
// Set up flags on file descriptor.
|
||||
@ -122,6 +133,11 @@ private:
|
||||
* Task member for delayed connect task. Should only be access on main thread.
|
||||
*/
|
||||
CancelableTask* mDelayedConnectTask;
|
||||
|
||||
/**
|
||||
* I/O buffer for received data
|
||||
*/
|
||||
nsAutoPtr<UnixSocketRawData> mBuffer;
|
||||
};
|
||||
|
||||
BluetoothSocket::BluetoothSocketIO::BluetoothSocketIO(
|
||||
@ -130,7 +146,6 @@ BluetoothSocket::BluetoothSocketIO::BluetoothSocketIO(
|
||||
UnixSocketConnector* aConnector,
|
||||
const nsACString& aAddress)
|
||||
: UnixSocketWatcher(mIOLoop)
|
||||
, SocketIOBase(MAX_READ_SIZE)
|
||||
, mConsumer(aConsumer)
|
||||
, mConnector(aConnector)
|
||||
, mShuttingDownOnIOThread(false)
|
||||
@ -158,16 +173,22 @@ BluetoothSocket::BluetoothSocketIO::GetSocketAddr(nsAString& aAddrStr) const
|
||||
mConnector->GetSocketAddr(mAddr, aAddrStr);
|
||||
}
|
||||
|
||||
SocketConsumerBase*
|
||||
BluetoothSocket::BluetoothSocketIO::GetConsumer()
|
||||
BluetoothSocket*
|
||||
BluetoothSocket::BluetoothSocketIO::GetBluetoothSocket()
|
||||
{
|
||||
return mConsumer.get();
|
||||
}
|
||||
|
||||
DataSocket*
|
||||
BluetoothSocket::BluetoothSocketIO::GetDataSocket()
|
||||
{
|
||||
return GetBluetoothSocket();
|
||||
}
|
||||
|
||||
SocketBase*
|
||||
BluetoothSocket::BluetoothSocketIO::GetSocketBase()
|
||||
{
|
||||
return GetConsumer();
|
||||
return GetDataSocket();
|
||||
}
|
||||
|
||||
bool
|
||||
@ -475,6 +496,69 @@ BluetoothSocket::BluetoothSocketIO::SetSocketFlags(int aFd)
|
||||
return true;
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothSocket::BluetoothSocketIO::QueryReceiveBuffer(
|
||||
UnixSocketIOBuffer** aBuffer)
|
||||
{
|
||||
MOZ_ASSERT(aBuffer);
|
||||
|
||||
if (!mBuffer) {
|
||||
mBuffer = new UnixSocketRawData(MAX_READ_SIZE);
|
||||
}
|
||||
*aBuffer = mBuffer.get();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* |ReceiveRunnable| transfers data received on the I/O thread
|
||||
* to an instance of |BluetoothSocket| on the main thread.
|
||||
*/
|
||||
class BluetoothSocket::BluetoothSocketIO::ReceiveRunnable final
|
||||
: public SocketIORunnable<BluetoothSocketIO>
|
||||
{
|
||||
public:
|
||||
ReceiveRunnable(BluetoothSocketIO* aIO, UnixSocketBuffer* aBuffer)
|
||||
: SocketIORunnable<BluetoothSocketIO>(aIO)
|
||||
, mBuffer(aBuffer)
|
||||
{ }
|
||||
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
BluetoothSocketIO* io = SocketIORunnable<BluetoothSocketIO>::GetIO();
|
||||
|
||||
if (NS_WARN_IF(io->IsShutdownOnMainThread())) {
|
||||
// Since we've already explicitly closed and the close
|
||||
// happened before this, this isn't really an error.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
BluetoothSocket* bluetoothSocket = io->GetBluetoothSocket();
|
||||
MOZ_ASSERT(bluetoothSocket);
|
||||
|
||||
bluetoothSocket->ReceiveSocketData(mBuffer);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsAutoPtr<UnixSocketBuffer> mBuffer;
|
||||
};
|
||||
|
||||
void
|
||||
BluetoothSocket::BluetoothSocketIO::ConsumeBuffer()
|
||||
{
|
||||
NS_DispatchToMainThread(new ReceiveRunnable(this, mBuffer.forget()));
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothSocket::BluetoothSocketIO::DiscardBuffer()
|
||||
{
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
//
|
||||
// Socket tasks
|
||||
//
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
#include "BluetoothCommon.h"
|
||||
#include <stdlib.h>
|
||||
#include "mozilla/ipc/SocketBase.h"
|
||||
#include "mozilla/ipc/DataSocket.h"
|
||||
#include "mozilla/ipc/UnixSocketWatcher.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "nsAutoPtr.h"
|
||||
@ -21,7 +21,7 @@ BEGIN_BLUETOOTH_NAMESPACE
|
||||
class BluetoothSocketObserver;
|
||||
class BluetoothUnixSocketConnector;
|
||||
|
||||
class BluetoothSocket final : public mozilla::ipc::SocketConsumerBase
|
||||
class BluetoothSocket final : public mozilla::ipc::DataSocket
|
||||
{
|
||||
public:
|
||||
BluetoothSocket(BluetoothSocketObserver* aObserver,
|
||||
@ -44,14 +44,20 @@ public:
|
||||
virtual void OnConnectSuccess() override;
|
||||
virtual void OnConnectError() override;
|
||||
virtual void OnDisconnect() override;
|
||||
virtual void ReceiveSocketData(
|
||||
nsAutoPtr<mozilla::ipc::UnixSocketBuffer>& aBuffer) override;
|
||||
|
||||
inline void GetAddress(nsAString& aDeviceAddress)
|
||||
{
|
||||
GetSocketAddr(aDeviceAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to be called whenever data is received. This is only called on the
|
||||
* main thread.
|
||||
*
|
||||
* @param aBuffer Data received from the socket.
|
||||
*/
|
||||
void ReceiveSocketData(nsAutoPtr<mozilla::ipc::UnixSocketBuffer>& aBuffer);
|
||||
|
||||
/**
|
||||
* Queue data to be sent to the socket on the IO thread. Can only be called on
|
||||
* originating thread.
|
||||
|
3
dom/cache/TypeUtils.cpp
vendored
3
dom/cache/TypeUtils.cpp
vendored
@ -68,7 +68,8 @@ ProcessURL(nsAString& aUrl, bool* aSchemeValidOut,
|
||||
if (aSchemeValidOut) {
|
||||
nsAutoCString scheme(Substring(flatURL, schemePos, schemeLen));
|
||||
*aSchemeValidOut = scheme.LowerCaseEqualsLiteral("http") ||
|
||||
scheme.LowerCaseEqualsLiteral("https");
|
||||
scheme.LowerCaseEqualsLiteral("https") ||
|
||||
scheme.LowerCaseEqualsLiteral("app");
|
||||
}
|
||||
|
||||
uint32_t queryPos;
|
||||
|
@ -504,7 +504,7 @@ FMRadio::EnableAudioChannelAgent()
|
||||
NS_IMETHODIMP
|
||||
FMRadio::CanPlayChanged(int32_t aCanPlay)
|
||||
{
|
||||
SetCanPlay(aCanPlay == AudioChannelState::AUDIO_CHANNEL_STATE_NORMAL);
|
||||
SetCanPlay(!(aCanPlay == AudioChannelState::AUDIO_CHANNEL_STATE_MUTED));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -13,9 +13,6 @@
|
||||
// Service instantiation
|
||||
#include "ipc/IccIPCService.h"
|
||||
#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL)
|
||||
// TODO: Bug 815526, deprecate RILContentHelper.
|
||||
#include "nsIRadioInterfaceLayer.h"
|
||||
#include "nsRadioInterfaceLayer.h"
|
||||
#include "nsIGonkIccService.h"
|
||||
#endif
|
||||
#include "nsXULAppAPI.h" // For XRE_GetProcessType()
|
||||
@ -148,13 +145,7 @@ NS_CreateIccService()
|
||||
service = new mozilla::dom::icc::IccIPCService();
|
||||
#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL)
|
||||
} else {
|
||||
// TODO: Bug 815526, deprecate RILContentHelper.
|
||||
nsCOMPtr <nsIRadioInterfaceLayer> ril =
|
||||
do_GetService(NS_RADIOINTERFACELAYER_CONTRACTID);
|
||||
nsCOMPtr <nsIRadioInterfaceLayer_new> ril_new(do_QueryInterface(ril));
|
||||
|
||||
service = (ril_new) ? do_GetService(GONK_ICC_SERVICE_CONTRACTID)
|
||||
: do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
|
||||
service = do_GetService(GONK_ICC_SERVICE_CONTRACTID);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,10 @@ XPCOMUtils.defineLazyServiceGetter(this, "gRadioInterfaceLayer",
|
||||
"@mozilla.org/ril;1",
|
||||
"nsIRadioInterfaceLayer");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gMobileConnectionService",
|
||||
"@mozilla.org/mobileconnection/mobileconnectionservice;1",
|
||||
"nsIGonkMobileConnectionService");
|
||||
|
||||
let DEBUG = RIL.DEBUG_RIL;
|
||||
function debug(s) {
|
||||
dump("IccService: " + s);
|
||||
@ -73,7 +77,7 @@ function IccService() {
|
||||
|
||||
let numClients = gRadioInterfaceLayer.numRadioInterfaces;
|
||||
for (let i = 0; i < numClients; i++) {
|
||||
this._iccs.push(new Icc(gRadioInterfaceLayer.getRadioInterface(i)));
|
||||
this._iccs.push(new Icc(i));
|
||||
}
|
||||
|
||||
this._updateDebugFlag();
|
||||
@ -145,7 +149,7 @@ IccService.prototype = {
|
||||
}
|
||||
|
||||
let icc = this.getIccByServiceId(aServiceId);
|
||||
icc._imsi = aImsi;
|
||||
icc.imsi = aImsi || null;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -166,15 +170,16 @@ IccService.prototype = {
|
||||
}
|
||||
};
|
||||
|
||||
function Icc(aRadioInterface) {
|
||||
this._radioInterface = aRadioInterface;
|
||||
function Icc(aClientId) {
|
||||
this._clientId = aClientId;
|
||||
this._radioInterface = gRadioInterfaceLayer.getRadioInterface(aClientId);
|
||||
this._listeners = [];
|
||||
}
|
||||
Icc.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIIcc]),
|
||||
|
||||
_clientId: 0,
|
||||
_radioInterface: null,
|
||||
_imsi: null,
|
||||
_listeners: null,
|
||||
|
||||
_updateCardState: function(aCardState) {
|
||||
@ -192,24 +197,52 @@ Icc.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* A utility function to compare objects. The srcInfo may contain
|
||||
* "rilMessageType", should ignore it.
|
||||
*/
|
||||
_isInfoChanged: function(srcInfo, destInfo) {
|
||||
if (!destInfo) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (let key in srcInfo) {
|
||||
if (key === "rilMessageType") {
|
||||
continue;
|
||||
}
|
||||
if (srcInfo[key] !== destInfo[key]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* We need to consider below cases when update iccInfo:
|
||||
* 1. Should clear iccInfo to null if there is no card detected.
|
||||
* 2. Need to create corresponding object based on iccType.
|
||||
*/
|
||||
_updateIccInfo: function(aIccInfo) {
|
||||
let oldSpn = this.iccInfo ? this.iccInfo.spn : null;
|
||||
|
||||
// Card is not detected, clear iccInfo to null.
|
||||
if (!aIccInfo || !aIccInfo.iccid) {
|
||||
if (this.iccInfo) {
|
||||
if (DEBUG) {
|
||||
debug("Card is not detected, clear iccInfo to null.");
|
||||
}
|
||||
this.imsi = null;
|
||||
this.iccInfo = null;
|
||||
this._deliverListenerEvent("notifyIccInfoChanged");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._isInfoChanged(aIccInfo, this.iccInfo)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If iccInfo is null, new corresponding object based on iccType.
|
||||
if (!this.iccInfo ||
|
||||
this.iccInfo.iccType != aIccInfo.iccType) {
|
||||
@ -233,6 +266,23 @@ Icc.prototype = {
|
||||
aIccInfo.mcc.toString());
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
// Update lastKnownHomeNetwork.
|
||||
if (aIccInfo.mcc && aIccInfo.mnc) {
|
||||
let lastKnownHomeNetwork = aIccInfo.mcc + "-" + aIccInfo.mnc;
|
||||
// Append spn information if available.
|
||||
if (aIccInfo.spn) {
|
||||
lastKnownHomeNetwork += "-" + aIccInfo.spn;
|
||||
}
|
||||
|
||||
gMobileConnectionService.notifyLastHomeNetworkChanged(this._clientId,
|
||||
lastKnownHomeNetwork);
|
||||
}
|
||||
|
||||
// If spn becomes available, we should check roaming again.
|
||||
if (!oldSpn && aIccInfo.spn) {
|
||||
gMobileConnectionService.notifySpnAvailable(this._clientId);
|
||||
}
|
||||
},
|
||||
|
||||
_deliverListenerEvent: function(aName, aArgs) {
|
||||
@ -305,6 +355,7 @@ Icc.prototype = {
|
||||
*/
|
||||
iccInfo: null,
|
||||
cardState: Ci.nsIIcc.CARD_STATE_UNKNOWN,
|
||||
imsi: null,
|
||||
|
||||
registerListener: function(aListener) {
|
||||
if (this._listeners.indexOf(aListener) >= 0) {
|
||||
@ -379,7 +430,7 @@ Icc.prototype = {
|
||||
|
||||
switch (aMvnoType) {
|
||||
case Ci.nsIIcc.CARD_MVNO_TYPE_IMSI:
|
||||
let imsi = this._imsi;
|
||||
let imsi = this.imsi;
|
||||
if (!imsi) {
|
||||
aCallback.notifyError(RIL.GECKO_ERROR_GENERIC_FAILURE);
|
||||
break;
|
||||
|
@ -97,7 +97,7 @@ NS_CreateIccService();
|
||||
/**
|
||||
* XPCOM component that provides the access to the selected ICC.
|
||||
*/
|
||||
[scriptable, uuid(38a5bbe2-add6-11e4-ba9e-e390d1d19195)]
|
||||
[scriptable, uuid(20a99186-e4cb-11e4-a5f9-938abcf7c826)]
|
||||
interface nsIIcc : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -214,6 +214,11 @@ interface nsIIcc : nsISupports
|
||||
*/
|
||||
readonly attribute unsigned long cardState;
|
||||
|
||||
/**
|
||||
* IMSI of this ICC.
|
||||
*/
|
||||
readonly attribute DOMString imsi;
|
||||
|
||||
/**
|
||||
* Get the status of an ICC lock (e.g. the PIN lock).
|
||||
*
|
||||
|
@ -182,6 +182,13 @@ IccChild::GetCardState(uint32_t* aCardState)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
IccChild::GetImsi(nsAString & aImsi)
|
||||
{
|
||||
NS_WARNING("IMSI shall not directly be fetched in child process.");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
IccChild::GetCardLockEnabled(uint32_t aLockType,
|
||||
nsIIccCallback* aRequestReply)
|
||||
|
@ -240,13 +240,12 @@ class MemoryReportRequestChild : public PMemoryReportRequestChild,
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
MemoryReportRequestChild(uint32_t aGeneration, bool aAnonymize,
|
||||
MemoryReportRequestChild(bool aAnonymize,
|
||||
const MaybeFileDesc& aDMDFile);
|
||||
NS_IMETHOD Run() override;
|
||||
private:
|
||||
virtual ~MemoryReportRequestChild();
|
||||
|
||||
uint32_t mGeneration;
|
||||
bool mAnonymize;
|
||||
FileDescriptor mDMDFile;
|
||||
};
|
||||
@ -254,8 +253,8 @@ private:
|
||||
NS_IMPL_ISUPPORTS(MemoryReportRequestChild, nsIRunnable)
|
||||
|
||||
MemoryReportRequestChild::MemoryReportRequestChild(
|
||||
uint32_t aGeneration, bool aAnonymize, const MaybeFileDesc& aDMDFile)
|
||||
: mGeneration(aGeneration), mAnonymize(aAnonymize)
|
||||
bool aAnonymize, const MaybeFileDesc& aDMDFile)
|
||||
: mAnonymize(aAnonymize)
|
||||
{
|
||||
MOZ_COUNT_CTOR(MemoryReportRequestChild);
|
||||
if (aDMDFile.type() == MaybeFileDesc::TFileDescriptor) {
|
||||
@ -867,48 +866,37 @@ ContentChild::AllocPMemoryReportRequestChild(const uint32_t& aGeneration,
|
||||
const MaybeFileDesc& aDMDFile)
|
||||
{
|
||||
MemoryReportRequestChild *actor =
|
||||
new MemoryReportRequestChild(aGeneration, aAnonymize, aDMDFile);
|
||||
new MemoryReportRequestChild(aAnonymize, aDMDFile);
|
||||
actor->AddRef();
|
||||
return actor;
|
||||
}
|
||||
|
||||
// This is just a wrapper for InfallibleTArray<MemoryReport> that implements
|
||||
// nsISupports, so it can be passed to nsIMemoryReporter::CollectReports.
|
||||
class MemoryReportsWrapper final : public nsISupports {
|
||||
~MemoryReportsWrapper() {}
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
explicit MemoryReportsWrapper(InfallibleTArray<MemoryReport>* r) : mReports(r) { }
|
||||
InfallibleTArray<MemoryReport> *mReports;
|
||||
};
|
||||
NS_IMPL_ISUPPORTS0(MemoryReportsWrapper)
|
||||
|
||||
class MemoryReportCallback final : public nsIMemoryReporterCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
explicit MemoryReportCallback(const nsACString& aProcess)
|
||||
: mProcess(aProcess)
|
||||
explicit MemoryReportCallback(MemoryReportRequestChild* aActor,
|
||||
const nsACString& aProcess)
|
||||
: mActor(aActor)
|
||||
, mProcess(aProcess)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Callback(const nsACString& aProcess, const nsACString &aPath,
|
||||
int32_t aKind, int32_t aUnits, int64_t aAmount,
|
||||
const nsACString& aDescription,
|
||||
nsISupports* aiWrappedReports) override
|
||||
nsISupports* aUnused) override
|
||||
{
|
||||
MemoryReportsWrapper *wrappedReports =
|
||||
static_cast<MemoryReportsWrapper *>(aiWrappedReports);
|
||||
|
||||
MemoryReport memreport(mProcess, nsCString(aPath), aKind, aUnits,
|
||||
aAmount, nsCString(aDescription));
|
||||
wrappedReports->mReports->AppendElement(memreport);
|
||||
mActor->SendReport(memreport);
|
||||
return NS_OK;
|
||||
}
|
||||
private:
|
||||
~MemoryReportCallback() {}
|
||||
|
||||
nsRefPtr<MemoryReportRequestChild> mActor;
|
||||
const nsCString mProcess;
|
||||
};
|
||||
NS_IMPL_ISUPPORTS(
|
||||
@ -944,21 +932,18 @@ NS_IMETHODIMP MemoryReportRequestChild::Run()
|
||||
ContentChild *child = static_cast<ContentChild*>(Manager());
|
||||
nsCOMPtr<nsIMemoryReporterManager> mgr = do_GetService("@mozilla.org/memory-reporter-manager;1");
|
||||
|
||||
InfallibleTArray<MemoryReport> reports;
|
||||
|
||||
nsCString process;
|
||||
child->GetProcessName(process);
|
||||
child->AppendProcessId(process);
|
||||
|
||||
// Run the reporters. The callback will turn each measurement into a
|
||||
// MemoryReport.
|
||||
nsRefPtr<MemoryReportsWrapper> wrappedReports =
|
||||
new MemoryReportsWrapper(&reports);
|
||||
nsRefPtr<MemoryReportCallback> cb = new MemoryReportCallback(process);
|
||||
mgr->GetReportsForThisProcessExtended(cb, wrappedReports, mAnonymize,
|
||||
nsRefPtr<MemoryReportCallback> cb =
|
||||
new MemoryReportCallback(this, process);
|
||||
mgr->GetReportsForThisProcessExtended(cb, nullptr, mAnonymize,
|
||||
FileDescriptorToFILE(mDMDFile, "wb"));
|
||||
|
||||
bool sent = Send__delete__(this, mGeneration, reports);
|
||||
bool sent = Send__delete__(this);
|
||||
return sent ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -405,45 +405,65 @@ bool ContentParent::sNuwaReady = false;
|
||||
class MemoryReportRequestParent : public PMemoryReportRequestParent
|
||||
{
|
||||
public:
|
||||
MemoryReportRequestParent();
|
||||
explicit MemoryReportRequestParent(uint32_t aGeneration);
|
||||
|
||||
virtual ~MemoryReportRequestParent();
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
virtual bool Recv__delete__(const uint32_t& aGeneration, InfallibleTArray<MemoryReport>&& aReport) override;
|
||||
virtual bool RecvReport(const MemoryReport& aReport) override;
|
||||
virtual bool Recv__delete__() override;
|
||||
|
||||
private:
|
||||
const uint32_t mGeneration;
|
||||
// Non-null if we haven't yet called EndChildReport() on it.
|
||||
nsRefPtr<nsMemoryReporterManager> mReporterManager;
|
||||
|
||||
ContentParent* Owner()
|
||||
{
|
||||
return static_cast<ContentParent*>(Manager());
|
||||
}
|
||||
};
|
||||
|
||||
MemoryReportRequestParent::MemoryReportRequestParent()
|
||||
MemoryReportRequestParent::MemoryReportRequestParent(uint32_t aGeneration)
|
||||
: mGeneration(aGeneration)
|
||||
{
|
||||
MOZ_COUNT_CTOR(MemoryReportRequestParent);
|
||||
mReporterManager = nsMemoryReporterManager::GetOrCreate();
|
||||
NS_WARN_IF(!mReporterManager);
|
||||
}
|
||||
|
||||
bool
|
||||
MemoryReportRequestParent::RecvReport(const MemoryReport& aReport)
|
||||
{
|
||||
if (mReporterManager) {
|
||||
mReporterManager->HandleChildReport(mGeneration, aReport);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
MemoryReportRequestParent::Recv__delete__()
|
||||
{
|
||||
// Notifying the reporter manager is done in ActorDestroy, because
|
||||
// it needs to happen even if the child process exits mid-report.
|
||||
// (The reporter manager will time out eventually, but let's avoid
|
||||
// that if possible.)
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
MemoryReportRequestParent::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
// Implement me! Bug 1005154
|
||||
}
|
||||
|
||||
bool
|
||||
MemoryReportRequestParent::Recv__delete__(const uint32_t& generation,
|
||||
nsTArray<MemoryReport>&& childReports)
|
||||
{
|
||||
nsRefPtr<nsMemoryReporterManager> mgr =
|
||||
nsMemoryReporterManager::GetOrCreate();
|
||||
if (mgr) {
|
||||
mgr->HandleChildReports(generation, childReports);
|
||||
if (mReporterManager) {
|
||||
mReporterManager->EndChildReport(mGeneration, aWhy == Deletion);
|
||||
mReporterManager = nullptr;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
MemoryReportRequestParent::~MemoryReportRequestParent()
|
||||
{
|
||||
MOZ_ASSERT(!mReporterManager);
|
||||
MOZ_COUNT_DTOR(MemoryReportRequestParent);
|
||||
}
|
||||
|
||||
@ -3549,7 +3569,8 @@ ContentParent::AllocPMemoryReportRequestParent(const uint32_t& aGeneration,
|
||||
const bool &aMinimizeMemoryUsage,
|
||||
const MaybeFileDesc &aDMDFile)
|
||||
{
|
||||
MemoryReportRequestParent* parent = new MemoryReportRequestParent();
|
||||
MemoryReportRequestParent* parent =
|
||||
new MemoryReportRequestParent(aGeneration);
|
||||
return parent;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
@ -20,8 +20,9 @@ struct MemoryReport {
|
||||
protocol PMemoryReportRequest {
|
||||
manager PContent;
|
||||
|
||||
parent:
|
||||
__delete__(uint32_t generation, MemoryReport[] report);
|
||||
parent:
|
||||
Report(MemoryReport aReport);
|
||||
__delete__();
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ PRLogModuleInfo* gAudioOffloadPlayerLog;
|
||||
#endif
|
||||
|
||||
// maximum time in paused state when offloading audio decompression.
|
||||
// When elapsed, the AudioSink is destroyed to allow the audio DSP to power down.
|
||||
// When elapsed, the GonkAudioSink is destroyed to allow the audio DSP to power down.
|
||||
static const uint64_t OFFLOAD_PAUSE_MAX_MSECS = 60000ll;
|
||||
|
||||
AudioOffloadPlayer::AudioOffloadPlayer(MediaOmxCommonDecoder* aObserver) :
|
||||
@ -473,28 +473,28 @@ void AudioOffloadPlayer::NotifyAudioTearDown()
|
||||
}
|
||||
|
||||
// static
|
||||
size_t AudioOffloadPlayer::AudioSinkCallback(AudioSink* aAudioSink,
|
||||
size_t AudioOffloadPlayer::AudioSinkCallback(GonkAudioSink* aAudioSink,
|
||||
void* aBuffer,
|
||||
size_t aSize,
|
||||
void* aCookie,
|
||||
AudioSink::cb_event_t aEvent)
|
||||
GonkAudioSink::cb_event_t aEvent)
|
||||
{
|
||||
AudioOffloadPlayer* me = (AudioOffloadPlayer*) aCookie;
|
||||
|
||||
switch (aEvent) {
|
||||
|
||||
case AudioSink::CB_EVENT_FILL_BUFFER:
|
||||
case GonkAudioSink::CB_EVENT_FILL_BUFFER:
|
||||
AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("Notify Audio position changed"));
|
||||
me->NotifyPositionChanged();
|
||||
return me->FillBuffer(aBuffer, aSize);
|
||||
|
||||
case AudioSink::CB_EVENT_STREAM_END:
|
||||
case GonkAudioSink::CB_EVENT_STREAM_END:
|
||||
AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("Notify Audio EOS"));
|
||||
me->mReachedEOS = true;
|
||||
me->NotifyAudioEOS();
|
||||
break;
|
||||
|
||||
case AudioSink::CB_EVENT_TEAR_DOWN:
|
||||
case GonkAudioSink::CB_EVENT_TEAR_DOWN:
|
||||
AUDIO_OFFLOAD_LOG(PR_LOG_DEBUG, ("Notify Tear down event"));
|
||||
me->NotifyAudioTearDown();
|
||||
break;
|
||||
@ -697,7 +697,7 @@ MediaDecoderOwner::NextFrameStatus AudioOffloadPlayer::GetNextFrameStatus()
|
||||
}
|
||||
}
|
||||
|
||||
void AudioOffloadPlayer::SendMetaDataToHal(sp<AudioSink>& aSink,
|
||||
void AudioOffloadPlayer::SendMetaDataToHal(sp<GonkAudioSink>& aSink,
|
||||
const sp<MetaData>& aMeta)
|
||||
{
|
||||
int32_t sampleRate = 0;
|
||||
|
@ -50,11 +50,11 @@ class WakeLock;
|
||||
* it to the sink
|
||||
*
|
||||
* Also this class passes state changes (play/pause/seek) from
|
||||
* MediaOmxCommonDecoder to AudioSink as well as provide AudioSink status
|
||||
* MediaOmxCommonDecoder to GonkAudioSink as well as provide GonkAudioSink status
|
||||
* (position changed, playback ended, seek complete, audio tear down) back to
|
||||
* MediaOmxCommonDecoder
|
||||
*
|
||||
* It acts as a bridge between MediaOmxCommonDecoder and AudioSink during
|
||||
* It acts as a bridge between MediaOmxCommonDecoder and GonkAudioSink during
|
||||
* offload playback
|
||||
*/
|
||||
|
||||
@ -80,7 +80,7 @@ public:
|
||||
// Caller retains ownership of "aSource".
|
||||
virtual void SetSource(const android::sp<MediaSource> &aSource) override;
|
||||
|
||||
// Start the source if it's not already started and open the AudioSink to
|
||||
// Start the source if it's not already started and open the GonkAudioSink to
|
||||
// create an offloaded audio track
|
||||
virtual status_t Start(bool aSourceAlreadyStarted = false) override;
|
||||
|
||||
@ -106,7 +106,7 @@ public:
|
||||
void Reset();
|
||||
|
||||
private:
|
||||
// Set when audio source is started and audioSink is initialized
|
||||
// Set when audio source is started and GonkAudioSink is initialized
|
||||
// Used only in main thread
|
||||
bool mStarted;
|
||||
|
||||
@ -170,7 +170,7 @@ private:
|
||||
// Audio sink wrapper to access offloaded audio tracks
|
||||
// Used in main thread and offload callback thread
|
||||
// Race conditions are protected in underlying Android::AudioTrack class
|
||||
android::sp<AudioSink> mAudioSink;
|
||||
android::sp<GonkAudioSink> mAudioSink;
|
||||
|
||||
// Buffer used to get date from audio source. Used in offload callback thread
|
||||
MediaBuffer* mInputBuffer;
|
||||
@ -183,7 +183,7 @@ private:
|
||||
// Timer to trigger position changed events
|
||||
nsCOMPtr<nsITimer> mTimeUpdateTimer;
|
||||
|
||||
// Timer to reset AudioSink when audio is paused for OFFLOAD_PAUSE_MAX_USECS.
|
||||
// Timer to reset GonkAudioSink when audio is paused for OFFLOAD_PAUSE_MAX_USECS.
|
||||
// It is triggered in Pause() and canceled when there is a Play() within
|
||||
// OFFLOAD_PAUSE_MAX_USECS. Used only from main thread so no lock is needed.
|
||||
nsCOMPtr<nsITimer> mResetTimer;
|
||||
@ -203,12 +203,12 @@ private:
|
||||
// case of error
|
||||
size_t FillBuffer(void *aData, size_t aSize);
|
||||
|
||||
// Called by AudioSink when it needs data, to notify EOS or tear down event
|
||||
static size_t AudioSinkCallback(AudioSink *aAudioSink,
|
||||
// Called by GonkAudioSink when it needs data, to notify EOS or tear down event
|
||||
static size_t AudioSinkCallback(GonkAudioSink *aAudioSink,
|
||||
void *aData,
|
||||
size_t aSize,
|
||||
void *aMe,
|
||||
AudioSink::cb_event_t aEvent);
|
||||
GonkAudioSink::cb_event_t aEvent);
|
||||
|
||||
bool IsSeeking();
|
||||
|
||||
@ -254,8 +254,8 @@ private:
|
||||
// MediaDecoder to re-evaluate offloading options
|
||||
void NotifyAudioTearDown();
|
||||
|
||||
// Send information from MetaData to the HAL via AudioSink
|
||||
void SendMetaDataToHal(android::sp<AudioSink>& aSink,
|
||||
// Send information from MetaData to the HAL via GonkAudioSink
|
||||
void SendMetaDataToHal(android::sp<GonkAudioSink>& aSink,
|
||||
const android::sp<MetaData>& aMeta);
|
||||
|
||||
AudioOffloadPlayer(const AudioOffloadPlayer &);
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include <utils/Mutex.h>
|
||||
#include <AudioTrack.h>
|
||||
|
||||
#include "AudioSink.h"
|
||||
#include "GonkAudioSink.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -34,7 +34,7 @@ namespace mozilla {
|
||||
* Android::AudioTrack
|
||||
* Similarly to ease handling offloaded tracks, part of AudioOutput is used here
|
||||
*/
|
||||
class AudioOutput : public AudioSink
|
||||
class AudioOutput : public GonkAudioSink
|
||||
{
|
||||
typedef android::Mutex Mutex;
|
||||
typedef android::String8 String8;
|
||||
|
@ -17,8 +17,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_SINK_H_
|
||||
#define AUDIO_SINK_H_
|
||||
#ifndef GONK_AUDIO_SINK_H_
|
||||
#define GONK_AUDIO_SINK_H_
|
||||
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/String8.h>
|
||||
@ -39,7 +39,7 @@ namespace mozilla {
|
||||
* Stripped version of Android KK MediaPlayerBase::AudioSink class
|
||||
*/
|
||||
|
||||
class AudioSink : public android::RefBase
|
||||
class GonkAudioSink : public android::RefBase
|
||||
{
|
||||
typedef android::String8 String8;
|
||||
typedef android::status_t status_t;
|
||||
@ -54,12 +54,12 @@ public:
|
||||
};
|
||||
|
||||
// Callback returns the number of bytes actually written to the buffer.
|
||||
typedef size_t (*AudioCallback)(AudioSink* aAudioSink,
|
||||
typedef size_t (*AudioCallback)(GonkAudioSink* aAudioSink,
|
||||
void* aBuffer,
|
||||
size_t aSize,
|
||||
void* aCookie,
|
||||
cb_event_t aEvent);
|
||||
virtual ~AudioSink() {}
|
||||
virtual ~GonkAudioSink() {}
|
||||
virtual ssize_t FrameSize() const = 0;
|
||||
virtual status_t GetPosition(uint32_t* aPosition) const = 0;
|
||||
virtual status_t SetVolume(float aVolume) const = 0;
|
||||
@ -86,4 +86,4 @@ public:
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // AUDIO_SINK_H_
|
||||
#endif // GONK_AUDIO_SINK_H_
|
@ -26,7 +26,7 @@ if CONFIG['MOZ_AUDIO_OFFLOAD']:
|
||||
EXPORTS += [
|
||||
'AudioOffloadPlayer.h',
|
||||
'AudioOutput.h',
|
||||
'AudioSink.h',
|
||||
'GonkAudioSink.h',
|
||||
]
|
||||
SOURCES += [
|
||||
'AudioOffloadPlayer.cpp',
|
||||
|
@ -56,6 +56,10 @@ XPCOMUtils.defineLazyServiceGetter(this, "gNetworkManager",
|
||||
"@mozilla.org/network/manager;1",
|
||||
"nsINetworkManager");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gIccService",
|
||||
"@mozilla.org/icc/iccservice;1",
|
||||
"nsIIccService");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gRadioInterfaceLayer", function() {
|
||||
let ril = { numRadioInterfaces: 0 };
|
||||
try {
|
||||
@ -387,9 +391,8 @@ MobileConnectionProvider.prototype = {
|
||||
* really the case. See bug 787967
|
||||
*/
|
||||
_checkRoamingBetweenOperators: function(aNetworkInfo) {
|
||||
// TODO: Bug 864489 - B2G RIL: use ipdl as IPC in MozIccManager
|
||||
// Should get iccInfo from GonkIccProvider.
|
||||
let iccInfo = this._radioInterface.rilContext.iccInfo;
|
||||
let icc = gIccService.getIccByServiceId(this._clientId);
|
||||
let iccInfo = icc ? icc.iccInfo : null;
|
||||
let operator = aNetworkInfo.network;
|
||||
let state = aNetworkInfo.state;
|
||||
|
||||
|
@ -134,6 +134,10 @@ XPCOMUtils.defineLazyServiceGetter(this, "gpps",
|
||||
"@mozilla.org/network/protocol-proxy-service;1",
|
||||
"nsIProtocolProxyService");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gIccService",
|
||||
"@mozilla.org/icc/iccservice;1",
|
||||
"nsIIccService");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gUUIDGenerator",
|
||||
"@mozilla.org/uuid-generator;1",
|
||||
"nsIUUIDGenerator");
|
||||
@ -347,7 +351,7 @@ MmsConnection.prototype = {
|
||||
// Get the proper IccInfo based on the current card type.
|
||||
try {
|
||||
let iccInfo = null;
|
||||
let baseIccInfo = this.radioInterface.rilContext.iccInfo;
|
||||
let baseIccInfo = this.getIccInfo();
|
||||
if (baseIccInfo.iccType === 'ruim' || baseIccInfo.iccType === 'csim') {
|
||||
iccInfo = baseIccInfo.QueryInterface(Ci.nsICdmaIccInfo);
|
||||
number = iccInfo.mdn;
|
||||
@ -365,11 +369,27 @@ MmsConnection.prototype = {
|
||||
return number;
|
||||
},
|
||||
|
||||
/**
|
||||
* A utility function to get IccInfo of the SIM card (if installed).
|
||||
*/
|
||||
getIccInfo: function() {
|
||||
let icc = gIccService.getIccByServiceId(this.serviceId);
|
||||
return icc ? icc.iccInfo : null;
|
||||
},
|
||||
|
||||
/**
|
||||
* A utility function to get CardState of the SIM card (if installed).
|
||||
*/
|
||||
getCardState: function() {
|
||||
let icc = gIccService.getIccByServiceId(this.serviceId);
|
||||
return icc ? icc.cardState : Ci.nsIIcc.CARD_STATE_UNKNOWN;
|
||||
},
|
||||
|
||||
/**
|
||||
* A utility function to get the ICC ID of the SIM card (if installed).
|
||||
*/
|
||||
getIccId: function() {
|
||||
let iccInfo = this.radioInterface.rilContext.iccInfo;
|
||||
let iccInfo = this.getIccInfo();
|
||||
|
||||
if (!iccInfo) {
|
||||
return null;
|
||||
@ -404,8 +424,7 @@ MmsConnection.prototype = {
|
||||
if (getRadioDisabledState()) {
|
||||
if (DEBUG) debug("Error! Radio is disabled when sending MMS.");
|
||||
errorStatus = _HTTP_STATUS_RADIO_DISABLED;
|
||||
} else if (this.radioInterface.rilContext.cardState !=
|
||||
Ci.nsIIcc.CARD_STATE_READY) {
|
||||
} else if (this.getCardState() != Ci.nsIIcc.CARD_STATE_READY) {
|
||||
if (DEBUG) debug("Error! SIM card is not ready when sending MMS.");
|
||||
errorStatus = _HTTP_STATUS_NO_SIM_CARD;
|
||||
}
|
||||
|
@ -76,9 +76,13 @@ XPCOMUtils.defineLazyGetter(this, "gWAP", function() {
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gCellBroadcastService",
|
||||
"@mozilla.org/cellbroadcast/gonkservice;1",
|
||||
"@mozilla.org/cellbroadcast/cellbroadcastservice;1",
|
||||
"nsIGonkCellBroadcastService");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gIccService",
|
||||
"@mozilla.org/icc/iccservice;1",
|
||||
"nsIIccService");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gMobileConnectionService",
|
||||
"@mozilla.org/mobileconnection/mobileconnectionservice;1",
|
||||
"nsIMobileConnectionService");
|
||||
@ -158,7 +162,7 @@ SmsService.prototype = {
|
||||
// Get the proper IccInfo based on the current card type.
|
||||
try {
|
||||
let iccInfo = null;
|
||||
let baseIccInfo = gRadioInterfaces[aServiceId].rilContext.iccInfo;
|
||||
let baseIccInfo = this._getIccInfo(aServiceId);
|
||||
if (baseIccInfo.iccType === 'ruim' || baseIccInfo.iccType === 'csim') {
|
||||
iccInfo = baseIccInfo.QueryInterface(Ci.nsICdmaIccInfo);
|
||||
number = iccInfo.mdn;
|
||||
@ -176,8 +180,18 @@ SmsService.prototype = {
|
||||
return number;
|
||||
},
|
||||
|
||||
_getIccInfo: function(aServiceId) {
|
||||
let icc = gIccService.getIccByServiceId(aServiceId);
|
||||
return icc ? icc.iccInfo : null;
|
||||
},
|
||||
|
||||
_getCardState: function(aServiceId) {
|
||||
let icc = gIccService.getIccByServiceId(aServiceId);
|
||||
return icc ? icc.cardState : Ci.nsIIcc.CARD_STATE_UNKNOWN;
|
||||
},
|
||||
|
||||
_getIccId: function(aServiceId) {
|
||||
let iccInfo = gRadioInterfaces[aServiceId].rilContext.iccInfo;
|
||||
let iccInfo = this._getIccInfo(aServiceId);
|
||||
|
||||
if (!iccInfo) {
|
||||
return null;
|
||||
@ -887,8 +901,7 @@ SmsService.prototype = {
|
||||
radioState == Ci.nsIMobileConnection.MOBILE_RADIO_STATE_DISABLED) {
|
||||
if (DEBUG) debug("Error! Radio is disabled when sending SMS.");
|
||||
errorCode = Ci.nsIMobileMessageCallback.RADIO_DISABLED_ERROR;
|
||||
} else if (gRadioInterfaces[aServiceId].rilContext.cardState !=
|
||||
Ci.nsIIcc.CARD_STATE_READY) {
|
||||
} else if (this._getCardState(aServiceId) != Ci.nsIIcc.CARD_STATE_READY) {
|
||||
if (DEBUG) debug("Error! SIM card is not ready when sending SMS.");
|
||||
errorCode = Ci.nsIMobileMessageCallback.NO_SIM_CARD_ERROR;
|
||||
}
|
||||
|
@ -69,6 +69,10 @@ XPCOMUtils.defineLazyServiceGetter(this, "messenger",
|
||||
"@mozilla.org/system-message-internal;1",
|
||||
"nsISystemMessagesInternal");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gIccService",
|
||||
"@mozilla.org/icc/iccservice;1",
|
||||
"nsIIccService");
|
||||
|
||||
this.NetworkStatsService = {
|
||||
init: function() {
|
||||
debug("Service started");
|
||||
@ -253,11 +257,12 @@ this.NetworkStatsService = {
|
||||
let networks = {};
|
||||
let numRadioInterfaces = gRil.numRadioInterfaces;
|
||||
for (let i = 0; i < numRadioInterfaces; i++) {
|
||||
let icc = gIccService.getIccByServiceId(i);
|
||||
let radioInterface = gRil.getRadioInterface(i);
|
||||
if (radioInterface.rilContext.iccInfo) {
|
||||
let netId = this.getNetworkId(radioInterface.rilContext.iccInfo.iccid,
|
||||
if (icc && icc.iccInfo) {
|
||||
let netId = this.getNetworkId(icc.iccInfo.iccid,
|
||||
NET_TYPE_MOBILE);
|
||||
networks[netId] = { id : radioInterface.rilContext.iccInfo.iccid,
|
||||
networks[netId] = { id : icc.iccInfo.iccid,
|
||||
type: NET_TYPE_MOBILE };
|
||||
}
|
||||
}
|
||||
|
@ -371,7 +371,7 @@ DOMSVGLength::SetValueAsString(const nsAString& aValue, ErrorResult& aRv)
|
||||
}
|
||||
|
||||
if (mVal) {
|
||||
mVal->SetBaseValueString(aValue, mSVGElement, true);
|
||||
aRv = mVal->SetBaseValueString(aValue, mSVGElement, true);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=539697
|
||||
-->
|
||||
<head>
|
||||
<title>Test SVGTransform behavior</title>
|
||||
<title>Test valueAsString behavior</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
@ -35,6 +35,7 @@ function run()
|
||||
|
||||
try {
|
||||
c.r.baseVal.valueAsString = 'rubbish';
|
||||
ok(false, 'setting a length to rubbish should fail');
|
||||
} catch (e) {
|
||||
is(e.name, 'SyntaxError', 'syntax error expected');
|
||||
is(e.code, DOMException.SYNTAX_ERR, 'syntax error expected');
|
||||
@ -46,6 +47,7 @@ function run()
|
||||
|
||||
try {
|
||||
m.orientAngle.baseVal.valueAsString = 'rubbish';
|
||||
ok(false, 'setting an angle to rubbish should fail');
|
||||
} catch (e) {
|
||||
is(e.name, 'SyntaxError', 'syntax error expected');
|
||||
is(e.code, DOMException.SYNTAX_ERR, 'syntax error expected');
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "nsIMobileCellInfo.h"
|
||||
#include "nsIMobileNetworkInfo.h"
|
||||
#include "nsIRadioInterfaceLayer.h"
|
||||
#include "nsIIccService.h"
|
||||
#endif
|
||||
|
||||
#ifdef AGPS_TYPE_INVALID
|
||||
@ -476,31 +477,35 @@ GonkGPSGeolocationProvider::RequestSetID(uint32_t flags)
|
||||
|
||||
AGpsSetIDType type = AGPS_SETID_TYPE_NONE;
|
||||
|
||||
nsCOMPtr<nsIRilContext> rilCtx;
|
||||
mRadioInterface->GetRilContext(getter_AddRefs(rilCtx));
|
||||
nsCOMPtr<nsIIccService> iccService =
|
||||
do_GetService(ICC_SERVICE_CONTRACTID);
|
||||
NS_ENSURE_TRUE_VOID(iccService);
|
||||
|
||||
if (rilCtx) {
|
||||
nsAutoString id;
|
||||
if (flags & AGPS_RIL_REQUEST_SETID_IMSI) {
|
||||
type = AGPS_SETID_TYPE_IMSI;
|
||||
rilCtx->GetImsi(id);
|
||||
}
|
||||
nsCOMPtr<nsIIcc> icc;
|
||||
iccService->GetIccByServiceId(mRilDataServiceId, getter_AddRefs(icc));
|
||||
NS_ENSURE_TRUE_VOID(icc);
|
||||
|
||||
if (flags & AGPS_RIL_REQUEST_SETID_MSISDN) {
|
||||
nsCOMPtr<nsIIccInfo> iccInfo;
|
||||
rilCtx->GetIccInfo(getter_AddRefs(iccInfo));
|
||||
if (iccInfo) {
|
||||
nsCOMPtr<nsIGsmIccInfo> gsmIccInfo = do_QueryInterface(iccInfo);
|
||||
if (gsmIccInfo) {
|
||||
type = AGPS_SETID_TYPE_MSISDN;
|
||||
gsmIccInfo->GetMsisdn(id);
|
||||
}
|
||||
nsAutoString id;
|
||||
|
||||
if (flags & AGPS_RIL_REQUEST_SETID_IMSI) {
|
||||
type = AGPS_SETID_TYPE_IMSI;
|
||||
icc->GetImsi(id);
|
||||
}
|
||||
|
||||
if (flags & AGPS_RIL_REQUEST_SETID_MSISDN) {
|
||||
nsCOMPtr<nsIIccInfo> iccInfo;
|
||||
icc->GetIccInfo(getter_AddRefs(iccInfo));
|
||||
if (iccInfo) {
|
||||
nsCOMPtr<nsIGsmIccInfo> gsmIccInfo = do_QueryInterface(iccInfo);
|
||||
if (gsmIccInfo) {
|
||||
type = AGPS_SETID_TYPE_MSISDN;
|
||||
gsmIccInfo->GetMsisdn(id);
|
||||
}
|
||||
}
|
||||
|
||||
NS_ConvertUTF16toUTF8 idBytes(id);
|
||||
mAGpsRilInterface->set_set_id(type, idBytes.get());
|
||||
}
|
||||
|
||||
NS_ConvertUTF16toUTF8 idBytes(id);
|
||||
mAGpsRilInterface->set_set_id(type, idBytes.get());
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -44,11 +44,6 @@ const RILCONTENTHELPER_CID =
|
||||
Components.ID("{472816e1-1fd6-4405-996c-806f9ea68174}");
|
||||
|
||||
const RIL_IPC_MSG_NAMES = [
|
||||
"RIL:CardStateChanged",
|
||||
"RIL:IccInfoChanged",
|
||||
"RIL:GetCardLockResult",
|
||||
"RIL:SetUnlockCardLockResult",
|
||||
"RIL:CardLockRetryCount",
|
||||
"RIL:StkCommand",
|
||||
"RIL:StkSessionEnd",
|
||||
"RIL:IccOpenChannel",
|
||||
@ -56,8 +51,6 @@ const RIL_IPC_MSG_NAMES = [
|
||||
"RIL:IccExchangeAPDU",
|
||||
"RIL:ReadIccContacts",
|
||||
"RIL:UpdateIccContact",
|
||||
"RIL:MatchMvno",
|
||||
"RIL:GetServiceState"
|
||||
];
|
||||
|
||||
/* global cpmm */
|
||||
@ -87,63 +80,14 @@ XPCOMUtils.defineLazyGetter(this, "gNumRadioInterfaces", function() {
|
||||
return Services.prefs.getIntPref(kPrefRilNumRadioInterfaces);
|
||||
});
|
||||
|
||||
function IccInfo() {}
|
||||
IccInfo.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIIccInfo]),
|
||||
|
||||
// nsIIccInfo
|
||||
|
||||
iccType: null,
|
||||
iccid: null,
|
||||
mcc: null,
|
||||
mnc: null,
|
||||
spn: null,
|
||||
isDisplayNetworkNameRequired: false,
|
||||
isDisplaySpnRequired: false
|
||||
};
|
||||
|
||||
function GsmIccInfo() {}
|
||||
GsmIccInfo.prototype = {
|
||||
__proto__: IccInfo.prototype,
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIGsmIccInfo,
|
||||
Ci.nsIIccInfo]),
|
||||
|
||||
// nsIGsmIccInfo
|
||||
|
||||
msisdn: null
|
||||
};
|
||||
|
||||
function CdmaIccInfo() {}
|
||||
CdmaIccInfo.prototype = {
|
||||
__proto__: IccInfo.prototype,
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsICdmaIccInfo,
|
||||
Ci.nsIIccInfo]),
|
||||
|
||||
// nsICdmaIccInfo
|
||||
|
||||
mdn: null,
|
||||
prlVersion: 0
|
||||
};
|
||||
|
||||
function RILContentHelper() {
|
||||
this.updateDebugFlag();
|
||||
|
||||
this.numClients = gNumRadioInterfaces;
|
||||
if (DEBUG) debug("Number of clients: " + this.numClients);
|
||||
|
||||
this._iccs = [];
|
||||
this.rilContexts = [];
|
||||
for (let clientId = 0; clientId < this.numClients; clientId++) {
|
||||
this._iccs.push(new Icc(this, clientId));
|
||||
this.rilContexts[clientId] = {
|
||||
cardState: Ci.nsIIcc.CARD_STATE_UNKNOWN,
|
||||
iccInfo: null
|
||||
};
|
||||
}
|
||||
|
||||
this.initDOMRequestHelper(/* aWindow */ null, RIL_IPC_MSG_NAMES);
|
||||
this._windowsMap = [];
|
||||
this._requestMap = [];
|
||||
this._iccListeners = [];
|
||||
this._iccChannelCallback = [];
|
||||
|
||||
@ -156,14 +100,12 @@ RILContentHelper.prototype = {
|
||||
__proto__: DOMRequestIpcHelper.prototype,
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIIccProvider,
|
||||
Ci.nsIIccService,
|
||||
Ci.nsIObserver,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
classID: RILCONTENTHELPER_CID,
|
||||
classInfo: XPCOMUtils.generateCI({classID: RILCONTENTHELPER_CID,
|
||||
classDescription: "RILContentHelper",
|
||||
interfaces: [Ci.nsIIccProvider,
|
||||
Ci.nsIIccService]}),
|
||||
interfaces: [Ci.nsIIccProvider]}),
|
||||
|
||||
updateDebugFlag: function() {
|
||||
try {
|
||||
@ -172,71 +114,8 @@ RILContentHelper.prototype = {
|
||||
} catch (e) {}
|
||||
},
|
||||
|
||||
// An utility function to copy objects.
|
||||
updateInfo: function(srcInfo, destInfo) {
|
||||
for (let key in srcInfo) {
|
||||
destInfo[key] = srcInfo[key];
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* We need to consider below cases when update iccInfo:
|
||||
* 1. Should clear iccInfo to null if there is no card detected.
|
||||
* 2. Need to create corresponding object based on iccType.
|
||||
*/
|
||||
updateIccInfo: function(clientId, newInfo) {
|
||||
let rilContext = this.rilContexts[clientId];
|
||||
|
||||
// Card is not detected, clear iccInfo to null.
|
||||
if (!newInfo || !newInfo.iccid) {
|
||||
if (rilContext.iccInfo) {
|
||||
rilContext.iccInfo = null;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// If iccInfo is null, new corresponding object based on iccType.
|
||||
if (!rilContext.iccInfo) {
|
||||
if (newInfo.iccType === "ruim" || newInfo.iccType === "csim") {
|
||||
rilContext.iccInfo = new CdmaIccInfo();
|
||||
} else if (newInfo.iccType === "sim" || newInfo.iccType === "usim") {
|
||||
rilContext.iccInfo = new GsmIccInfo();
|
||||
} else {
|
||||
rilContext.iccInfo = new IccInfo();
|
||||
}
|
||||
}
|
||||
|
||||
this.updateInfo(newInfo, rilContext.iccInfo);
|
||||
},
|
||||
|
||||
_windowsMap: null,
|
||||
|
||||
_requestMap: null,
|
||||
|
||||
rilContexts: null,
|
||||
|
||||
getRilContext: function(clientId) {
|
||||
// Update ril contexts by sending IPC message to chrome only when the first
|
||||
// time we require it. The information will be updated by following info
|
||||
// changed messages.
|
||||
this.getRilContext = function getRilContext(clientId) {
|
||||
return this.rilContexts[clientId];
|
||||
};
|
||||
|
||||
for (let cId = 0; cId < this.numClients; cId++) {
|
||||
let rilContext =
|
||||
cpmm.sendSyncMessage("RIL:GetRilContext", {clientId: cId})[0];
|
||||
if (!rilContext) {
|
||||
if (DEBUG) debug("Received null rilContext from chrome process.");
|
||||
continue;
|
||||
}
|
||||
this.rilContexts[cId].cardState = rilContext.cardState;
|
||||
this.updateIccInfo(cId, rilContext.iccInfo);
|
||||
}
|
||||
|
||||
return this.rilContexts[clientId];
|
||||
},
|
||||
|
||||
/**
|
||||
* nsIIccProvider
|
||||
*/
|
||||
@ -568,61 +447,6 @@ RILContentHelper.prototype = {
|
||||
let data = msg.json.data;
|
||||
let clientId = msg.json.clientId;
|
||||
switch (msg.name) {
|
||||
case "RIL:CardStateChanged":
|
||||
if (this.rilContexts[clientId].cardState != data.cardState) {
|
||||
this.rilContexts[clientId].cardState = data.cardState;
|
||||
this._deliverIccEvent(clientId,
|
||||
"notifyCardStateChanged",
|
||||
null);
|
||||
}
|
||||
break;
|
||||
case "RIL:IccInfoChanged":
|
||||
this.updateIccInfo(clientId, data);
|
||||
this._deliverIccEvent(clientId,
|
||||
"notifyIccInfoChanged",
|
||||
null);
|
||||
break;
|
||||
case "RIL:GetCardLockResult": {
|
||||
let requestId = data.requestId;
|
||||
let callback = this._requestMap[requestId];
|
||||
delete this._requestMap[requestId];
|
||||
|
||||
if (data.errorMsg) {
|
||||
callback.notifyError(data.errorMsg);
|
||||
break;
|
||||
}
|
||||
|
||||
callback.notifySuccessWithBoolean(data.enabled);
|
||||
break;
|
||||
}
|
||||
case "RIL:SetUnlockCardLockResult": {
|
||||
let requestId = data.requestId;
|
||||
let callback = this._requestMap[requestId];
|
||||
delete this._requestMap[requestId];
|
||||
|
||||
if (data.errorMsg) {
|
||||
let retryCount =
|
||||
(data.retryCount !== undefined) ? data.retryCount : -1;
|
||||
callback.notifyCardLockError(data.errorMsg, retryCount);
|
||||
break;
|
||||
}
|
||||
|
||||
callback.notifySuccess();
|
||||
break;
|
||||
}
|
||||
case "RIL:CardLockRetryCount": {
|
||||
let requestId = data.requestId;
|
||||
let callback = this._requestMap[requestId];
|
||||
delete this._requestMap[requestId];
|
||||
|
||||
if (data.errorMsg) {
|
||||
callback.notifyError(data.errorMsg);
|
||||
break;
|
||||
}
|
||||
|
||||
callback.notifyGetCardLockRetryCount(data.retryCount);
|
||||
break;
|
||||
}
|
||||
case "RIL:StkCommand":
|
||||
this._deliverEvent(clientId, "_iccListeners", "notifyStkCommand",
|
||||
[JSON.stringify(data)]);
|
||||
@ -645,30 +469,6 @@ RILContentHelper.prototype = {
|
||||
case "RIL:UpdateIccContact":
|
||||
this.handleUpdateIccContact(data);
|
||||
break;
|
||||
case "RIL:MatchMvno": {
|
||||
let requestId = data.requestId;
|
||||
let callback = this._requestMap[requestId];
|
||||
delete this._requestMap[requestId];
|
||||
|
||||
if (data.errorMsg) {
|
||||
callback.notifyError(data.errorMsg);
|
||||
break;
|
||||
}
|
||||
callback.notifySuccessWithBoolean(data.result);
|
||||
break;
|
||||
}
|
||||
case "RIL:GetServiceState": {
|
||||
let requestId = data.requestId;
|
||||
let callback = this._requestMap[requestId];
|
||||
delete this._requestMap[requestId];
|
||||
|
||||
if (data.errorMsg) {
|
||||
callback.notifyError(data.errorMsg);
|
||||
break;
|
||||
}
|
||||
callback.notifySuccessWithBoolean(data.result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@ -795,235 +595,6 @@ RILContentHelper.prototype = {
|
||||
if (DEBUG) debug("listener for " + name + " threw an exception: " + e);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* nsIIccService interface.
|
||||
*/
|
||||
|
||||
_iccs: null, // An array of Icc instances.
|
||||
|
||||
getIccByServiceId: function(serviceId) {
|
||||
let icc = this._iccs[serviceId];
|
||||
if (!icc) {
|
||||
throw Cr.NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
return icc;
|
||||
},
|
||||
|
||||
/**
|
||||
* Bridge APIs from nsIIccService to nsIIccProvider
|
||||
*/
|
||||
|
||||
_deliverIccEvent: function(clientId, name, args) {
|
||||
let icc = this._iccs[clientId];
|
||||
if (!icc) {
|
||||
if (DEBUG) debug("_deliverIccEvent: Invalid clientId: " + clientId);
|
||||
return;
|
||||
}
|
||||
|
||||
icc.deliverListenerEvent(name, args);
|
||||
},
|
||||
|
||||
getIccInfo: function(clientId) {
|
||||
let context = this.getRilContext(clientId);
|
||||
return context && context.iccInfo;
|
||||
},
|
||||
|
||||
getCardState: function(clientId) {
|
||||
let context = this.getRilContext(clientId);
|
||||
return context && context.cardState;
|
||||
},
|
||||
|
||||
matchMvno: function(clientId, mvnoType, mvnoData, callback) {
|
||||
let requestId = UUIDGenerator.generateUUID().toString();
|
||||
this._requestMap[requestId] = callback;
|
||||
|
||||
cpmm.sendAsyncMessage("RIL:MatchMvno", {
|
||||
clientId: clientId,
|
||||
data: {
|
||||
requestId: requestId,
|
||||
mvnoType: mvnoType,
|
||||
mvnoData: mvnoData
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
getCardLockEnabled: function(clientId, lockType, callback) {
|
||||
let requestId = UUIDGenerator.generateUUID().toString();
|
||||
this._requestMap[requestId] = callback;
|
||||
|
||||
cpmm.sendAsyncMessage("RIL:GetCardLockEnabled", {
|
||||
clientId: clientId,
|
||||
data: {
|
||||
lockType: lockType,
|
||||
requestId: requestId
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
unlockCardLock: function(clientId, lockType, password, newPin, callback) {
|
||||
let requestId = UUIDGenerator.generateUUID().toString();
|
||||
this._requestMap[requestId] = callback;
|
||||
|
||||
cpmm.sendAsyncMessage("RIL:UnlockCardLock", {
|
||||
clientId: clientId,
|
||||
data: {
|
||||
lockType: lockType,
|
||||
password: password,
|
||||
newPin: newPin,
|
||||
requestId: requestId
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
setCardLockEnabled: function(clientId, lockType, password, enabled, callback) {
|
||||
let requestId = UUIDGenerator.generateUUID().toString();
|
||||
this._requestMap[requestId] = callback;
|
||||
|
||||
cpmm.sendAsyncMessage("RIL:SetCardLockEnabled", {
|
||||
clientId: clientId,
|
||||
data: {
|
||||
lockType: lockType,
|
||||
password: password,
|
||||
enabled: enabled,
|
||||
requestId: requestId
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
changeCardLockPassword: function(clientId, lockType, password, newPassword,
|
||||
callback) {
|
||||
let requestId = UUIDGenerator.generateUUID().toString();
|
||||
this._requestMap[requestId] = callback;
|
||||
|
||||
cpmm.sendAsyncMessage("RIL:ChangeCardLockPassword", {
|
||||
clientId: clientId,
|
||||
data: {
|
||||
lockType: lockType,
|
||||
password: password,
|
||||
newPassword: newPassword,
|
||||
requestId: requestId
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
getCardLockRetryCount: function(clientId, lockType, callback) {
|
||||
let requestId = UUIDGenerator.generateUUID().toString();
|
||||
this._requestMap[requestId] = callback;
|
||||
|
||||
cpmm.sendAsyncMessage("RIL:GetCardLockRetryCount", {
|
||||
clientId: clientId,
|
||||
data: {
|
||||
lockType: lockType,
|
||||
requestId: requestId
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
getServiceStateEnabled: function(clientId, service, callback) {
|
||||
let requestId = UUIDGenerator.generateUUID().toString();
|
||||
this._requestMap[requestId] = callback;
|
||||
|
||||
cpmm.sendAsyncMessage("RIL:GetServiceState", {
|
||||
clientId: clientId,
|
||||
data: {
|
||||
requestId: requestId,
|
||||
service: service
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function Icc(aIccProvider, aClientId) {
|
||||
this._iccProvider = aIccProvider;
|
||||
this._clientId = aClientId;
|
||||
this._listeners = [];
|
||||
}
|
||||
Icc.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIIcc]),
|
||||
|
||||
_iccProvider: null,
|
||||
_clientId: -1,
|
||||
_listeners: null,
|
||||
|
||||
deliverListenerEvent: function(aName, aArgs) {
|
||||
let listeners = this._listeners.slice();
|
||||
for (let listener of listeners) {
|
||||
if (this._listeners.indexOf(listener) === -1) {
|
||||
continue;
|
||||
}
|
||||
let handler = listener[aName];
|
||||
if (typeof handler != "function") {
|
||||
throw new Error("No handler for " + aName);
|
||||
}
|
||||
try {
|
||||
handler.apply(listener, aArgs);
|
||||
} catch (e) {
|
||||
if (DEBUG) {
|
||||
debug("listener for " + aName + " threw an exception: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* nsIIcc interface.
|
||||
*/
|
||||
registerListener: function(aListener) {
|
||||
if (this._listeners.indexOf(aListener) >= 0) {
|
||||
throw Cr.NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
this._listeners.push(aListener);
|
||||
cpmm.sendAsyncMessage("RIL:RegisterIccMsg");
|
||||
},
|
||||
|
||||
unregisterListener: function(aListener) {
|
||||
let index = this._listeners.indexOf(aListener);
|
||||
if (index >= 0) {
|
||||
this._listeners.splice(index, 1);
|
||||
}
|
||||
},
|
||||
|
||||
get iccInfo() {
|
||||
return this._iccProvider.getIccInfo(this._clientId);
|
||||
},
|
||||
|
||||
get cardState() {
|
||||
return this._iccProvider.getCardState(this._clientId);
|
||||
},
|
||||
|
||||
getCardLockEnabled: function(aLockType, aCallback) {
|
||||
this._iccProvider.getCardLockEnabled(this._clientId, aLockType, aCallback);
|
||||
},
|
||||
|
||||
unlockCardLock: function(aLockType, aPassword, aNewPin, aCallback) {
|
||||
this._iccProvider.unlockCardLock(this._clientId, aLockType,
|
||||
aPassword, aNewPin, aCallback);
|
||||
},
|
||||
|
||||
setCardLockEnabled: function(aLockType, aPassword, aEnabled, aCallback) {
|
||||
this._iccProvider.setCardLockEnabled(this._clientId, aLockType,
|
||||
aPassword, aEnabled, aCallback);
|
||||
},
|
||||
|
||||
changeCardLockPassword: function(aLockType, aPassword, aNewPassword, aCallback) {
|
||||
this._iccProvider.changeCardLockPassword(this._clientId, aLockType,
|
||||
aPassword, aNewPassword, aCallback);
|
||||
},
|
||||
|
||||
getCardLockRetryCount: function(aLockType, aCallback) {
|
||||
this._iccProvider.getCardLockRetryCount(this._clientId, aLockType, aCallback);
|
||||
},
|
||||
|
||||
matchMvno: function(aMvnoType, aMvnoData, aCallback) {
|
||||
this._iccProvider.matchMvno(this._clientId, aMvnoType, aMvnoData, aCallback);
|
||||
},
|
||||
|
||||
getServiceStateEnabled: function(aService, aCallback) {
|
||||
this._iccProvider.getServiceStateEnabled(this._clientId, aService, aCallback);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -89,24 +89,16 @@ const NETWORK_TYPE_MOBILE_DUN = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN;
|
||||
|
||||
// TODO: Bug 815526, deprecate RILContentHelper.
|
||||
const RIL_IPC_ICCMANAGER_MSG_NAMES = [
|
||||
"RIL:GetRilContext",
|
||||
"RIL:SendStkResponse",
|
||||
"RIL:SendStkMenuSelection",
|
||||
"RIL:SendStkTimerExpiration",
|
||||
"RIL:SendStkEventDownload",
|
||||
"RIL:GetCardLockEnabled",
|
||||
"RIL:UnlockCardLock",
|
||||
"RIL:SetCardLockEnabled",
|
||||
"RIL:ChangeCardLockPassword",
|
||||
"RIL:GetCardLockRetryCount",
|
||||
"RIL:IccOpenChannel",
|
||||
"RIL:IccExchangeAPDU",
|
||||
"RIL:IccCloseChannel",
|
||||
"RIL:ReadIccContacts",
|
||||
"RIL:UpdateIccContact",
|
||||
"RIL:RegisterIccMsg",
|
||||
"RIL:MatchMvno",
|
||||
"RIL:GetServiceState"
|
||||
];
|
||||
|
||||
// set to true in ril_consts.js to see debug messages
|
||||
@ -169,7 +161,7 @@ XPCOMUtils.defineLazyServiceGetter(this, "gMobileConnectionService",
|
||||
"nsIGonkMobileConnectionService");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gCellBroadcastService",
|
||||
"@mozilla.org/cellbroadcast/gonkservice;1",
|
||||
"@mozilla.org/cellbroadcast/cellbroadcastservice;1",
|
||||
"nsIGonkCellBroadcastService");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gIccMessenger",
|
||||
@ -881,44 +873,6 @@ try {
|
||||
})());
|
||||
} catch (e) {}
|
||||
|
||||
function IccInfo() {}
|
||||
IccInfo.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIIccInfo]),
|
||||
|
||||
// nsIIccInfo
|
||||
|
||||
iccType: null,
|
||||
iccid: null,
|
||||
mcc: null,
|
||||
mnc: null,
|
||||
spn: null,
|
||||
isDisplayNetworkNameRequired: false,
|
||||
isDisplaySpnRequired: false
|
||||
};
|
||||
|
||||
function GsmIccInfo() {}
|
||||
GsmIccInfo.prototype = {
|
||||
__proto__: IccInfo.prototype,
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIGsmIccInfo,
|
||||
Ci.nsIIccInfo]),
|
||||
|
||||
// nsIGsmIccInfo
|
||||
|
||||
msisdn: null
|
||||
};
|
||||
|
||||
function CdmaIccInfo() {}
|
||||
CdmaIccInfo.prototype = {
|
||||
__proto__: IccInfo.prototype,
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsICdmaIccInfo,
|
||||
Ci.nsIIccInfo]),
|
||||
|
||||
// nsICdmaIccInfo
|
||||
|
||||
mdn: null,
|
||||
prlVersion: 0
|
||||
};
|
||||
|
||||
function DataConnectionHandler(clientId, radioInterface) {
|
||||
// Initial owning attributes.
|
||||
this.clientId = clientId;
|
||||
@ -1441,7 +1395,6 @@ RadioInterfaceLayer.prototype = {
|
||||
interfaces: [Ci.nsIRadioInterfaceLayer]}),
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIRadioInterfaceLayer,
|
||||
Ci.nsIRadioInterfaceLayer_new, // TODO: Bug 815526, deprecate RILContentHelper.
|
||||
Ci.nsIObserver]),
|
||||
|
||||
/**
|
||||
@ -1689,12 +1642,6 @@ function RadioInterface(aClientId, aWorkerMessenger) {
|
||||
};
|
||||
aWorkerMessenger.registerClient(aClientId, this);
|
||||
|
||||
this.rilContext = {
|
||||
cardState: Ci.nsIIcc.CARD_STATE_UNKNOWN,
|
||||
iccInfo: null,
|
||||
imsi: null
|
||||
};
|
||||
|
||||
this.operatorInfo = {};
|
||||
|
||||
let lock = gSettingsService.createLock();
|
||||
@ -1752,42 +1699,14 @@ RadioInterface.prototype = {
|
||||
Services.obs.removeObserver(this, kNetworkConnStateChangedTopic);
|
||||
},
|
||||
|
||||
/**
|
||||
* A utility function to copy objects. The srcInfo may contain
|
||||
* "rilMessageType", should ignore it.
|
||||
*/
|
||||
updateInfo: function(srcInfo, destInfo) {
|
||||
for (let key in srcInfo) {
|
||||
if (key === "rilMessageType") {
|
||||
continue;
|
||||
}
|
||||
destInfo[key] = srcInfo[key];
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* A utility function to compare objects. The srcInfo may contain
|
||||
* "rilMessageType", should ignore it.
|
||||
*/
|
||||
isInfoChanged: function(srcInfo, destInfo) {
|
||||
if (!destInfo) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (let key in srcInfo) {
|
||||
if (key === "rilMessageType") {
|
||||
continue;
|
||||
}
|
||||
if (srcInfo[key] !== destInfo[key]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
getIccInfo: function() {
|
||||
let icc = gIccService.getIccByServiceId(this.clientId);
|
||||
return icc ? icc.iccInfo : null;
|
||||
},
|
||||
|
||||
isCardPresent: function() {
|
||||
let cardState = this.rilContext.cardState;
|
||||
let icc = gIccService.getIccByServiceId(this.clientId);
|
||||
let cardState = icc ? icc.cardState : Ci.nsIIcc.CARD_STATE_UNKNOWN;
|
||||
return cardState !== Ci.nsIIcc.CARD_STATE_UNDETECTED &&
|
||||
cardState !== Ci.nsIIcc.CARD_STATE_UNKNOWN;
|
||||
},
|
||||
@ -1799,29 +1718,6 @@ RadioInterface.prototype = {
|
||||
*/
|
||||
receiveMessage: function(msg) {
|
||||
switch (msg.name) {
|
||||
case "RIL:GetRilContext":
|
||||
// This message is sync.
|
||||
return this.rilContext;
|
||||
case "RIL:GetCardLockEnabled":
|
||||
this.workerMessenger.sendWithIPCMessage(msg, "iccGetCardLockEnabled",
|
||||
"RIL:GetCardLockResult");
|
||||
break;
|
||||
case "RIL:UnlockCardLock":
|
||||
this.workerMessenger.sendWithIPCMessage(msg, "iccUnlockCardLock",
|
||||
"RIL:SetUnlockCardLockResult");
|
||||
break;
|
||||
case "RIL:SetCardLockEnabled":
|
||||
this.workerMessenger.sendWithIPCMessage(msg, "iccSetCardLockEnabled",
|
||||
"RIL:SetUnlockCardLockResult");
|
||||
break;
|
||||
case "RIL:ChangeCardLockPassword":
|
||||
this.workerMessenger.sendWithIPCMessage(msg, "iccChangeCardLockPassword",
|
||||
"RIL:SetUnlockCardLockResult");
|
||||
break;
|
||||
case "RIL:GetCardLockRetryCount":
|
||||
this.workerMessenger.sendWithIPCMessage(msg, "iccGetCardLockRetryCount",
|
||||
"RIL:CardLockRetryCount");
|
||||
break;
|
||||
case "RIL:SendStkResponse":
|
||||
this.workerMessenger.send("sendStkTerminalResponse", msg.json.data);
|
||||
break;
|
||||
@ -1849,12 +1745,6 @@ RadioInterface.prototype = {
|
||||
case "RIL:UpdateIccContact":
|
||||
this.workerMessenger.sendWithIPCMessage(msg, "updateICCContact");
|
||||
break;
|
||||
case "RIL:MatchMvno":
|
||||
this.matchMvno(msg.target, msg.json.data);
|
||||
break;
|
||||
case "RIL:GetServiceState":
|
||||
this.workerMessenger.sendWithIPCMessage(msg, "getIccServiceState");
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
@ -1924,13 +1814,9 @@ RadioInterface.prototype = {
|
||||
message.radioState);
|
||||
break;
|
||||
case "cardstatechange":
|
||||
this.rilContext.cardState = message.cardState;
|
||||
gRadioEnabledController.receiveCardState(this.clientId);
|
||||
gIccService.notifyCardStateChanged(this.clientId,
|
||||
this.rilContext.cardState);
|
||||
// TODO: Bug 815526, deprecate RILContentHelper.
|
||||
gMessageManager.sendIccMessage("RIL:CardStateChanged",
|
||||
this.clientId, message);
|
||||
message.cardState);
|
||||
gRadioEnabledController.receiveCardState(this.clientId);
|
||||
break;
|
||||
case "sms-received":
|
||||
this.handleSmsReceived(message);
|
||||
@ -1942,11 +1828,11 @@ RadioInterface.prototype = {
|
||||
this.handleNitzTime(message);
|
||||
break;
|
||||
case "iccinfochange":
|
||||
this.handleIccInfoChange(message);
|
||||
gIccService.notifyIccInfoChanged(this.clientId,
|
||||
message.iccid ? message : null);
|
||||
break;
|
||||
case "iccimsi":
|
||||
this.rilContext.imsi = message.imsi;
|
||||
gIccService.notifyImsiChanged(this.clientId, this.rilContext.imsi);
|
||||
gIccService.notifyImsiChanged(this.clientId, message.imsi);
|
||||
break;
|
||||
case "iccmbdn":
|
||||
this.handleIccMbdn(message);
|
||||
@ -1970,85 +1856,6 @@ RadioInterface.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
// Matches the mvnoData pattern with imsi. Characters 'x' and 'X' are skipped
|
||||
// and not compared. E.g., if the mvnoData passed is '310260x10xxxxxx',
|
||||
// then the function returns true only if imsi has the same first 6 digits,
|
||||
// 8th and 9th digit.
|
||||
// TODO: Bug 815526, deprecate RILContentHelper.
|
||||
isImsiMatches: function(mvnoData) {
|
||||
let imsi = this.rilContext.imsi;
|
||||
|
||||
// This should not be an error, but a mismatch.
|
||||
if (mvnoData.length > imsi.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0; i < mvnoData.length; i++) {
|
||||
let c = mvnoData[i];
|
||||
if ((c !== 'x') && (c !== 'X') && (c !== imsi[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
// TODO: Bug 815526, deprecate RILContentHelper.
|
||||
matchMvno: function(target, message) {
|
||||
if (DEBUG) this.debug("matchMvno: " + JSON.stringify(message));
|
||||
|
||||
if (!message || !message.mvnoData) {
|
||||
message.errorMsg = RIL.GECKO_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!message.errorMsg) {
|
||||
switch (message.mvnoType) {
|
||||
case RIL.GECKO_CARDMVNO_TYPE_IMSI:
|
||||
if (!this.rilContext.imsi) {
|
||||
message.errorMsg = RIL.GECKO_ERROR_GENERIC_FAILURE;
|
||||
break;
|
||||
}
|
||||
message.result = this.isImsiMatches(message.mvnoData);
|
||||
break;
|
||||
case RIL.GECKO_CARDMVNO_TYPE_SPN:
|
||||
let spn = this.rilContext.iccInfo && this.rilContext.iccInfo.spn;
|
||||
if (!spn) {
|
||||
message.errorMsg = RIL.GECKO_ERROR_GENERIC_FAILURE;
|
||||
break;
|
||||
}
|
||||
message.result = spn == message.mvnoData;
|
||||
break;
|
||||
case RIL.GECKO_CARDMVNO_TYPE_GID:
|
||||
this.workerMessenger.send("getGID1", null, (function(response) {
|
||||
let gid = response.gid1;
|
||||
let mvnoDataLength = message.mvnoData.length;
|
||||
|
||||
if (!gid) {
|
||||
message.errorMsg = RIL.GECKO_ERROR_GENERIC_FAILURE;
|
||||
} else if (mvnoDataLength > gid.length) {
|
||||
message.result = false;
|
||||
} else {
|
||||
message.result =
|
||||
gid.substring(0, mvnoDataLength).toLowerCase() ==
|
||||
message.mvnoData.toLowerCase();
|
||||
}
|
||||
|
||||
target.sendAsyncMessage("RIL:MatchMvno", {
|
||||
clientId: this.clientId,
|
||||
data: message
|
||||
});
|
||||
}).bind(this));
|
||||
return;
|
||||
default:
|
||||
message.errorMsg = RIL.GECKO_ERROR_MODE_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
target.sendAsyncMessage("RIL:MatchMvno", {
|
||||
clientId: this.clientId,
|
||||
data: message
|
||||
});
|
||||
},
|
||||
|
||||
setDataRegistration: function(attach) {
|
||||
let deferred = Promise.defer();
|
||||
this.workerMessenger.send("setDataRegistration",
|
||||
@ -2227,71 +2034,12 @@ RadioInterface.prototype = {
|
||||
null, null);
|
||||
},
|
||||
|
||||
handleIccInfoChange: function(message) {
|
||||
let oldSpn = this.rilContext.iccInfo ? this.rilContext.iccInfo.spn : null;
|
||||
|
||||
// TODO: Bug 815526, deprecate RILContentHelper:
|
||||
// Move the logic of updating iccInfo to IccService.js.
|
||||
if (!message || !message.iccid) {
|
||||
// If iccInfo is already `null`, don't have to clear it and send
|
||||
// RIL:IccInfoChanged.
|
||||
if (!this.rilContext.iccInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Card is not detected, clear iccInfo to null.
|
||||
this.rilContext.iccInfo = null;
|
||||
} else {
|
||||
if (!this.rilContext.iccInfo) {
|
||||
if (message.iccType === "ruim" || message.iccType === "csim") {
|
||||
this.rilContext.iccInfo = new CdmaIccInfo();
|
||||
} else if (message.iccType === "sim" || message.iccType === "usim") {
|
||||
this.rilContext.iccInfo = new GsmIccInfo();
|
||||
} else {
|
||||
this.rilContext.iccInfo = new IccInfo();
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.isInfoChanged(message, this.rilContext.iccInfo)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateInfo(message, this.rilContext.iccInfo);
|
||||
}
|
||||
|
||||
// RIL:IccInfoChanged corresponds to a DOM event that gets fired only
|
||||
// when iccInfo has changed.
|
||||
// TODO: Bug 815526, deprecate RILContentHelper.
|
||||
gMessageManager.sendIccMessage("RIL:IccInfoChanged",
|
||||
this.clientId,
|
||||
message.iccid ? message : null);
|
||||
gIccService.notifyIccInfoChanged(this.clientId,
|
||||
message.iccid ? message : null);
|
||||
|
||||
// Update lastKnownHomeNetwork.
|
||||
if (message.mcc && message.mnc) {
|
||||
let lastKnownHomeNetwork = message.mcc + "-" + message.mnc;
|
||||
// Append spn information if available.
|
||||
if (message.spn) {
|
||||
lastKnownHomeNetwork += "-" + message.spn;
|
||||
}
|
||||
|
||||
gMobileConnectionService.notifyLastHomeNetworkChanged(this.clientId,
|
||||
lastKnownHomeNetwork);
|
||||
}
|
||||
|
||||
// If spn becomes available, we should check roaming again.
|
||||
if (!oldSpn && message.spn) {
|
||||
gMobileConnectionService.notifySpnAvailable(this.clientId);
|
||||
}
|
||||
},
|
||||
|
||||
handleStkProactiveCommand: function(message) {
|
||||
if (DEBUG) this.debug("handleStkProactiveCommand " + JSON.stringify(message));
|
||||
let iccId = this.rilContext.iccInfo && this.rilContext.iccInfo.iccid;
|
||||
if (iccId) {
|
||||
let iccInfo = this.getIccInfo();
|
||||
if (iccInfo && iccInfo.iccid) {
|
||||
gIccMessenger
|
||||
.notifyStkProactiveCommand(iccId,
|
||||
.notifyStkProactiveCommand(iccInfo.iccid,
|
||||
gStkCmdFactory.createCommand(message));
|
||||
}
|
||||
// TODO: Bug 815526, deprecate RILContentHelper.
|
||||
@ -2589,8 +2337,6 @@ RadioInterface.prototype = {
|
||||
|
||||
// nsIRadioInterface
|
||||
|
||||
rilContext: null,
|
||||
|
||||
// TODO: Bug 928861 - B2G NetworkManager: Provide a more generic function
|
||||
// for connecting
|
||||
setupDataCallByType: function(networkType) {
|
||||
@ -3226,8 +2972,8 @@ RILNetworkInterface.prototype = {
|
||||
},
|
||||
|
||||
get iccId() {
|
||||
let iccInfo = this.dataConnectionHandler.radioInterface.rilContext.iccInfo;
|
||||
return iccInfo && iccInfo.iccid;
|
||||
let iccInfo = this.dataConnectionHandler.radioInterface.getIccInfo();
|
||||
return iccInfo ? iccInfo.iccid : null;
|
||||
},
|
||||
|
||||
get mmsc() {
|
||||
|
@ -21,30 +21,15 @@ interface nsIRilNetworkInterface : nsINetworkInterface
|
||||
readonly attribute long mmsPort; // -1 if not set.
|
||||
};
|
||||
|
||||
[scriptable, uuid(4441e660-4ad0-11e4-916c-0800200c9a66)]
|
||||
interface nsIRilContext : nsISupports
|
||||
{
|
||||
/**
|
||||
* One of the nsIIcc.CARD_STATE_* values.
|
||||
*/
|
||||
readonly attribute unsigned long cardState;
|
||||
|
||||
readonly attribute DOMString imsi;
|
||||
|
||||
readonly attribute nsIIccInfo iccInfo;
|
||||
};
|
||||
|
||||
[scriptable, function, uuid(3bc96351-53b0-47a1-a888-c74c64b60f25)]
|
||||
interface nsIRilSendWorkerMessageCallback : nsISupports
|
||||
{
|
||||
boolean handleResponse(in jsval response);
|
||||
};
|
||||
|
||||
[scriptable, uuid(fe01c648-867a-11e4-915f-033b36e8177b)]
|
||||
[scriptable, uuid(1a3ef88a-e4d1-11e4-8512-176220f2b32b)]
|
||||
interface nsIRadioInterface : nsISupports
|
||||
{
|
||||
readonly attribute nsIRilContext rilContext;
|
||||
|
||||
/**
|
||||
* PDP APIs
|
||||
*
|
||||
@ -79,13 +64,3 @@ interface nsIRadioInterfaceLayer : nsISupports
|
||||
|
||||
void setMicrophoneMuted(in boolean muted);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helper Interface to define new APIs of nsIRadioInterfaceLayer during
|
||||
* ril-interfaces frozen phase.
|
||||
*/
|
||||
[scriptable, uuid(f8ec63da-c22e-11e4-89f3-b767dae42a13)]
|
||||
interface nsIRadioInterfaceLayer_new : nsIRadioInterfaceLayer
|
||||
{
|
||||
};
|
||||
|
@ -61,7 +61,7 @@ var ecmaGlobals =
|
||||
"Int32Array",
|
||||
"Int8Array",
|
||||
"InternalError",
|
||||
{name: "Intl", desktop: true},
|
||||
{name: "Intl", android: false},
|
||||
"Iterator",
|
||||
"JSON",
|
||||
"Map",
|
||||
@ -1391,6 +1391,7 @@ function createInterfaceMap(isXBLScope) {
|
||||
var isRelease = !version.contains("a");
|
||||
var isDesktop = !/Mobile|Tablet/.test(navigator.userAgent);
|
||||
var isB2G = !isDesktop && !navigator.userAgent.contains("Android");
|
||||
var isAndroid = navigator.userAgent.contains("Android");
|
||||
var hasPermission = function (aPermissions) {
|
||||
var result = false;
|
||||
for (var p of aPermissions) {
|
||||
@ -1410,6 +1411,7 @@ function createInterfaceMap(isXBLScope) {
|
||||
(entry.xbl === !isXBLScope) ||
|
||||
(entry.desktop === !isDesktop) ||
|
||||
(entry.b2g === !isB2G) ||
|
||||
(entry.android === !isAndroid) ||
|
||||
(entry.release === !isRelease) ||
|
||||
(entry.pref && !prefs.getBoolPref(entry.pref)) ||
|
||||
(entry.permission && !hasPermission(entry.permission))) {
|
||||
|
@ -37,9 +37,9 @@ XPCOMUtils.defineLazyGetter(this, "CP", function () {
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gSystemMessenger",
|
||||
"@mozilla.org/system-message-internal;1",
|
||||
"nsISystemMessagesInternal");
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gRIL",
|
||||
"@mozilla.org/ril;1",
|
||||
"nsIRadioInterfaceLayer");
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gIccService",
|
||||
"@mozilla.org/icc/iccservice;1",
|
||||
"nsIIccService");
|
||||
|
||||
/**
|
||||
* Helpers for WAP PDU processing.
|
||||
@ -104,7 +104,8 @@ this.WapPushManager = {
|
||||
let mac = params && params.mac;
|
||||
authInfo = CP.Authenticator.check(data.array.subarray(data.offset),
|
||||
sec, mac, function getNetworkPin() {
|
||||
let imsi = gRIL.getRadioInterface(options.serviceId).rilContext.imsi;
|
||||
let icc = gIccService.getIccByServiceId(options.serviceId);
|
||||
let imsi = icc ? icc.imsi : null;
|
||||
return CP.Authenticator.formatImsi(imsi);
|
||||
});
|
||||
}
|
||||
|
@ -418,21 +418,47 @@ CompareNetwork::OnStreamComplete(nsIStreamLoader* aLoader, nsISupports* aContext
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(request);
|
||||
if (!httpChannel) {
|
||||
mManager->NetworkFinished(NS_ERROR_FAILURE);
|
||||
return NS_OK;
|
||||
}
|
||||
if (httpChannel) {
|
||||
bool requestSucceeded;
|
||||
rv = httpChannel->GetRequestSucceeded(&requestSucceeded);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
mManager->NetworkFinished(rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool requestSucceeded;
|
||||
rv = httpChannel->GetRequestSucceeded(&requestSucceeded);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
mManager->NetworkFinished(rv);
|
||||
return NS_OK;
|
||||
if (!requestSucceeded) {
|
||||
mManager->NetworkFinished(NS_ERROR_FAILURE);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// The only supported request schemes are http, https, and app.
|
||||
// Above, we check to ensure that the request is http or https
|
||||
// based on the channel qi. Here we test the scheme to ensure
|
||||
// that it is app. Otherwise, bail.
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
|
||||
if (NS_WARN_IF(!channel)) {
|
||||
mManager->NetworkFinished(NS_ERROR_FAILURE);
|
||||
return NS_OK;
|
||||
}
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = channel->GetURI(getter_AddRefs(uri));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
mManager->NetworkFinished(rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!requestSucceeded) {
|
||||
mManager->NetworkFinished(NS_ERROR_FAILURE);
|
||||
return NS_OK;
|
||||
nsAutoCString scheme;
|
||||
rv = uri->GetScheme(scheme);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
mManager->NetworkFinished(rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!scheme.LowerCaseEqualsLiteral("app")) {
|
||||
mManager->NetworkFinished(NS_ERROR_FAILURE);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(nsm): "Extract mime type..."
|
||||
|
@ -35,7 +35,7 @@ var ecmaGlobals =
|
||||
"Int32Array",
|
||||
"Int8Array",
|
||||
"InternalError",
|
||||
{name: "Intl", b2g: false, android: false},
|
||||
{name: "Intl", android: false},
|
||||
"Iterator",
|
||||
"JSON",
|
||||
"Map",
|
||||
|
@ -35,7 +35,7 @@ var ecmaGlobals =
|
||||
"Int32Array",
|
||||
"Int8Array",
|
||||
"InternalError",
|
||||
{name: "Intl", b2g: false, android: false},
|
||||
{name: "Intl", android: false},
|
||||
"Iterator",
|
||||
"JSON",
|
||||
"Map",
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
#include "mozilla/ipc/DataSocket.h"
|
||||
#include "mozilla/ipc/UnixSocketWatcher.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
|
@ -1838,12 +1838,15 @@ class _GenerateProtocolCode(ipdl.ast.Visitor):
|
||||
if usesend or userecv:
|
||||
transitionfunc.addstmt(Whitespace.NL)
|
||||
|
||||
transitionfunc.addstmts([
|
||||
fromswitch,
|
||||
# all --> Error transitions break to here
|
||||
StmtExpr(ExprAssn(ExprDeref(nextvar), _errorState())),
|
||||
StmtReturn(ExprLiteral.FALSE)
|
||||
])
|
||||
transitionfunc.addstmt(fromswitch)
|
||||
# all --> Error transitions break to here. But only insert this
|
||||
# block if there is any possibility of such transitions.
|
||||
if self.protocol.transitionStmts:
|
||||
transitionfunc.addstmts([
|
||||
StmtExpr(ExprAssn(ExprDeref(nextvar), _errorState())),
|
||||
StmtReturn(ExprLiteral.FALSE),
|
||||
])
|
||||
|
||||
return transitionfunc
|
||||
|
||||
##--------------------------------------------------
|
||||
|
48
ipc/unixsocket/DataSocket.cpp
Normal file
48
ipc/unixsocket/DataSocket.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
/* -*- 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 "mozilla/ipc/DataSocket.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
//
|
||||
// DataSocketIO
|
||||
//
|
||||
|
||||
DataSocketIO::~DataSocketIO()
|
||||
{ }
|
||||
|
||||
void
|
||||
DataSocketIO::EnqueueData(UnixSocketIOBuffer* aBuffer)
|
||||
{
|
||||
if (!aBuffer->GetSize()) {
|
||||
delete aBuffer; // delete empty data immediately
|
||||
return;
|
||||
}
|
||||
mOutgoingQ.AppendElement(aBuffer);
|
||||
}
|
||||
|
||||
bool
|
||||
DataSocketIO::HasPendingData() const
|
||||
{
|
||||
return !mOutgoingQ.IsEmpty();
|
||||
}
|
||||
|
||||
DataSocketIO::DataSocketIO()
|
||||
{ }
|
||||
|
||||
//
|
||||
// DataSocket
|
||||
//
|
||||
|
||||
DataSocket::~DataSocket()
|
||||
{ }
|
||||
|
||||
}
|
||||
}
|
204
ipc/unixsocket/DataSocket.h
Normal file
204
ipc/unixsocket/DataSocket.h
Normal file
@ -0,0 +1,204 @@
|
||||
/* -*- 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_datasocket_h
|
||||
#define mozilla_ipc_datasocket_h
|
||||
|
||||
#include "mozilla/ipc/SocketBase.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
//
|
||||
// DataSocket
|
||||
//
|
||||
|
||||
/**
|
||||
* |DataSocket| represents a socket that can send or receive data. This
|
||||
* can be a stream-based socket, a datagram-based socket, or any other
|
||||
* socket that transfers data.
|
||||
*/
|
||||
class DataSocket : public SocketBase
|
||||
{
|
||||
public:
|
||||
virtual ~DataSocket();
|
||||
|
||||
/**
|
||||
* Queue data to be sent to the socket on the IO thread. Can only be called on
|
||||
* originating thread.
|
||||
*
|
||||
* @param aBuffer Data to be sent to socket
|
||||
*/
|
||||
virtual void SendSocketData(UnixSocketIOBuffer* aBuffer) = 0;
|
||||
};
|
||||
|
||||
//
|
||||
// DataSocketIO
|
||||
//
|
||||
|
||||
/**
|
||||
* |DataSocketIO| is a base class for Socket I/O classes that
|
||||
* transfer data on the I/O thread. It provides methods for the
|
||||
* most common read and write scenarios.
|
||||
*/
|
||||
class DataSocketIO : public SocketIOBase
|
||||
{
|
||||
public:
|
||||
virtual ~DataSocketIO();
|
||||
|
||||
/**
|
||||
* Allocates a buffer for receiving data from the socket. The method
|
||||
* shall return the buffer in the arguments. The buffer is owned by the
|
||||
* I/O class. |DataSocketIO| will never ask for more than one buffer
|
||||
* at a time, so I/O classes can handout the same buffer on each invokation
|
||||
* of this method. I/O-thread only.
|
||||
*
|
||||
* @param[out] aBuffer returns a pointer to the I/O buffer
|
||||
* @return NS_OK on success, or an error code otherwise
|
||||
*/
|
||||
virtual nsresult QueryReceiveBuffer(UnixSocketIOBuffer** aBuffer) = 0;
|
||||
|
||||
/**
|
||||
* Marks the current socket buffer to by consumed by the I/O class. The
|
||||
* class is resonsible for releasing the buffer afterwards. I/O-thread
|
||||
* only.
|
||||
*
|
||||
* @param aIndex the socket's index
|
||||
* @param[out] aBuffer the receive buffer
|
||||
* @param[out] aSize the receive buffer's size
|
||||
*/
|
||||
virtual void ConsumeBuffer() = 0;
|
||||
|
||||
/**
|
||||
* Marks the current socket buffer to be discarded. The I/O class is
|
||||
* resonsible for releasing the buffer's memory. I/O-thread only.
|
||||
*
|
||||
* @param aIndex the socket's index
|
||||
*/
|
||||
virtual void DiscardBuffer() = 0;
|
||||
|
||||
void EnqueueData(UnixSocketIOBuffer* aBuffer);
|
||||
bool HasPendingData() const;
|
||||
|
||||
template <typename T>
|
||||
ssize_t ReceiveData(int aFd, T* aIO)
|
||||
{
|
||||
MOZ_ASSERT(aFd >= 0);
|
||||
MOZ_ASSERT(aIO);
|
||||
|
||||
UnixSocketIOBuffer* incoming;
|
||||
nsresult rv = QueryReceiveBuffer(&incoming);
|
||||
if (NS_FAILED(rv)) {
|
||||
/* an error occured */
|
||||
nsRefPtr<nsRunnable> r = new SocketIORequestClosingRunnable<T>(aIO);
|
||||
NS_DispatchToMainThread(r);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t res = incoming->Receive(aFd);
|
||||
if (res < 0) {
|
||||
/* an I/O error occured */
|
||||
DiscardBuffer();
|
||||
nsRefPtr<nsRunnable> r = new SocketIORequestClosingRunnable<T>(aIO);
|
||||
NS_DispatchToMainThread(r);
|
||||
return -1;
|
||||
} else if (!res) {
|
||||
/* EOF or peer shut down sending */
|
||||
DiscardBuffer();
|
||||
nsRefPtr<nsRunnable> r = new SocketIORequestClosingRunnable<T>(aIO);
|
||||
NS_DispatchToMainThread(r);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef MOZ_TASK_TRACER
|
||||
// Make unix socket creation events to be the source events of TaskTracer,
|
||||
// and originate the rest correlation tasks from here.
|
||||
AutoSourceEvent taskTracerEvent(SourceEventType::Unixsocket);
|
||||
#endif
|
||||
|
||||
ConsumeBuffer();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
nsresult SendPendingData(int aFd, T* aIO)
|
||||
{
|
||||
MOZ_ASSERT(aFd >= 0);
|
||||
MOZ_ASSERT(aIO);
|
||||
|
||||
while (HasPendingData()) {
|
||||
UnixSocketIOBuffer* outgoing = mOutgoingQ.ElementAt(0);
|
||||
|
||||
ssize_t res = outgoing->Send(aFd);
|
||||
if (res < 0) {
|
||||
/* an I/O error occured */
|
||||
nsRefPtr<nsRunnable> r = new SocketIORequestClosingRunnable<T>(aIO);
|
||||
NS_DispatchToMainThread(r);
|
||||
return NS_ERROR_FAILURE;
|
||||
} else if (!res && outgoing->GetSize()) {
|
||||
/* I/O is currently blocked; try again later */
|
||||
return NS_OK;
|
||||
}
|
||||
if (!outgoing->GetSize()) {
|
||||
mOutgoingQ.RemoveElementAt(0);
|
||||
delete outgoing;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
DataSocketIO();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Raw data queue. Must be pushed/popped from I/O thread only.
|
||||
*/
|
||||
nsTArray<UnixSocketIOBuffer*> mOutgoingQ;
|
||||
};
|
||||
|
||||
//
|
||||
// Tasks
|
||||
//
|
||||
|
||||
/* |SocketIOSendTask| transfers an instance of |Tdata|, such as
|
||||
* |UnixSocketRawData|, to the I/O thread and queues it up for
|
||||
* sending the contained data.
|
||||
*/
|
||||
template<typename Tio, typename Tdata>
|
||||
class SocketIOSendTask final : public SocketIOTask<Tio>
|
||||
{
|
||||
public:
|
||||
SocketIOSendTask(Tio* aIO, Tdata* aData)
|
||||
: SocketIOTask<Tio>(aIO)
|
||||
, mData(aData)
|
||||
{
|
||||
MOZ_ASSERT(aData);
|
||||
}
|
||||
|
||||
void Run() override
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_ASSERT(!SocketIOTask<Tio>::IsCanceled());
|
||||
|
||||
Tio* io = SocketIOTask<Tio>::GetIO();
|
||||
MOZ_ASSERT(!io->IsShutdownOnIOThread());
|
||||
|
||||
io->Send(mData);
|
||||
}
|
||||
|
||||
private:
|
||||
Tdata* mData;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -7,12 +7,11 @@
|
||||
#include "ListenSocket.h"
|
||||
#include <fcntl.h>
|
||||
#include "ConnectionOrientedSocket.h"
|
||||
#include "DataSocket.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "UnixSocketConnector.h"
|
||||
|
||||
static const size_t MAX_READ_SIZE = 1; /* any small constant */
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
@ -32,9 +31,9 @@ public:
|
||||
const nsACString& aAddress);
|
||||
~ListenSocketIO();
|
||||
|
||||
void GetSocketAddr(nsAString& aAddrStr) const;
|
||||
SocketConsumerBase* GetConsumer();
|
||||
SocketBase* GetSocketBase();
|
||||
void GetSocketAddr(nsAString& aAddrStr) const;
|
||||
DataSocket* GetDataSocket();
|
||||
SocketBase* GetSocketBase();
|
||||
|
||||
// Shutdown state
|
||||
//
|
||||
@ -107,13 +106,13 @@ ListenSocketIO::ListenSocketIO(MessageLoop* mIOLoop,
|
||||
ListenSocket* aListenSocket,
|
||||
UnixSocketConnector* aConnector,
|
||||
const nsACString& aAddress)
|
||||
: UnixSocketWatcher(mIOLoop)
|
||||
, SocketIOBase(MAX_READ_SIZE)
|
||||
, mListenSocket(aListenSocket)
|
||||
, mConnector(aConnector)
|
||||
, mShuttingDownOnIOThread(false)
|
||||
, mAddress(aAddress)
|
||||
, mCOSocketIO(nullptr)
|
||||
: UnixSocketWatcher(mIOLoop)
|
||||
, SocketIOBase()
|
||||
, mListenSocket(aListenSocket)
|
||||
, mConnector(aConnector)
|
||||
, mShuttingDownOnIOThread(false)
|
||||
, mAddress(aAddress)
|
||||
, mCOSocketIO(nullptr)
|
||||
{
|
||||
MOZ_ASSERT(mListenSocket);
|
||||
MOZ_ASSERT(mConnector);
|
||||
@ -136,6 +135,14 @@ ListenSocketIO::GetSocketAddr(nsAString& aAddrStr) const
|
||||
mConnector->GetSocketAddr(mAddr, aAddrStr);
|
||||
}
|
||||
|
||||
DataSocket*
|
||||
ListenSocketIO::GetDataSocket()
|
||||
{
|
||||
MOZ_CRASH("Listen sockets cannot transfer data");
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SocketBase*
|
||||
ListenSocketIO::GetSocketBase()
|
||||
{
|
||||
|
@ -268,41 +268,15 @@ SocketBase::SetConnectionStatus(SocketConnectionStatus aConnectionStatus)
|
||||
mConnectionStatus = aConnectionStatus;
|
||||
}
|
||||
|
||||
//
|
||||
// SocketConsumerBase
|
||||
//
|
||||
|
||||
SocketConsumerBase::~SocketConsumerBase()
|
||||
{ }
|
||||
|
||||
//
|
||||
// SocketIOBase
|
||||
//
|
||||
|
||||
SocketIOBase::SocketIOBase()
|
||||
{ }
|
||||
|
||||
SocketIOBase::~SocketIOBase()
|
||||
{ }
|
||||
|
||||
void
|
||||
SocketIOBase::EnqueueData(UnixSocketIOBuffer* aBuffer)
|
||||
{
|
||||
if (!aBuffer->GetSize()) {
|
||||
delete aBuffer; // delete empty data immediately
|
||||
return;
|
||||
}
|
||||
mOutgoingQ.AppendElement(aBuffer);
|
||||
}
|
||||
|
||||
bool
|
||||
SocketIOBase::HasPendingData() const
|
||||
{
|
||||
return !mOutgoingQ.IsEmpty();
|
||||
}
|
||||
|
||||
SocketIOBase::SocketIOBase(size_t aMaxReadSize)
|
||||
: mMaxReadSize(aMaxReadSize)
|
||||
{
|
||||
MOZ_ASSERT(mMaxReadSize);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -310,32 +310,6 @@ private:
|
||||
uint32_t mConnectDelayMs;
|
||||
};
|
||||
|
||||
//
|
||||
// SocketConsumerBase
|
||||
//
|
||||
|
||||
class SocketConsumerBase : public SocketBase
|
||||
{
|
||||
public:
|
||||
virtual ~SocketConsumerBase();
|
||||
|
||||
/**
|
||||
* Function to be called whenever data is received. This is only called on the
|
||||
* main thread.
|
||||
*
|
||||
* @param aBuffer Data received from the socket.
|
||||
*/
|
||||
virtual void ReceiveSocketData(nsAutoPtr<UnixSocketBuffer>& aBuffer) = 0;
|
||||
|
||||
/**
|
||||
* Queue data to be sent to the socket on the IO thread. Can only be called on
|
||||
* originating thread.
|
||||
*
|
||||
* @param aBuffer Data to be sent to socket
|
||||
*/
|
||||
virtual void SendSocketData(UnixSocketIOBuffer* aBuffer) = 0;
|
||||
};
|
||||
|
||||
//
|
||||
// Socket I/O runnables
|
||||
//
|
||||
@ -415,43 +389,6 @@ private:
|
||||
SocketEvent mEvent;
|
||||
};
|
||||
|
||||
/* |SocketReceiveRunnable| transfers data received on the I/O thread
|
||||
* to the consumer on the main thread.
|
||||
*/
|
||||
template <typename T>
|
||||
class SocketIOReceiveRunnable final : public SocketIORunnable<T>
|
||||
{
|
||||
public:
|
||||
SocketIOReceiveRunnable(T* aIO, UnixSocketBuffer* aBuffer)
|
||||
: SocketIORunnable<T>(aIO)
|
||||
, mBuffer(aBuffer)
|
||||
{ }
|
||||
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
T* io = SocketIORunnable<T>::GetIO();
|
||||
|
||||
if (io->IsShutdownOnMainThread()) {
|
||||
NS_WARNING("mConsumer is null, aborting receive!");
|
||||
// Since we've already explicitly closed and the close happened before
|
||||
// this, this isn't really an error. Since we've warned, return OK.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
SocketConsumerBase* consumer = io->GetConsumer();
|
||||
MOZ_ASSERT(consumer);
|
||||
|
||||
consumer->ReceiveSocketData(mBuffer);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsAutoPtr<UnixSocketBuffer> mBuffer;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class SocketIORequestClosingRunnable final : public SocketIORunnable<T>
|
||||
{
|
||||
@ -507,91 +444,17 @@ private:
|
||||
// SocketIOBase
|
||||
//
|
||||
|
||||
/* |SocketIOBase| is a base class for Socket I/O classes that
|
||||
* perform operations on the I/O thread. It provides methods
|
||||
* for the most common read and write scenarios.
|
||||
/**
|
||||
* |SocketIOBase| is a base class for Socket I/O classes that
|
||||
* perform operations on the I/O thread.
|
||||
*/
|
||||
class SocketIOBase
|
||||
{
|
||||
public:
|
||||
virtual ~SocketIOBase();
|
||||
|
||||
void EnqueueData(UnixSocketIOBuffer* aBuffer);
|
||||
bool HasPendingData() const;
|
||||
|
||||
template <typename T>
|
||||
ssize_t ReceiveData(int aFd, T* aIO)
|
||||
{
|
||||
MOZ_ASSERT(aFd >= 0);
|
||||
MOZ_ASSERT(aIO);
|
||||
|
||||
nsAutoPtr<UnixSocketRawData> incoming(
|
||||
new UnixSocketRawData(mMaxReadSize));
|
||||
|
||||
ssize_t res = incoming->Receive(aFd);
|
||||
if (res < 0) {
|
||||
/* an I/O error occured */
|
||||
nsRefPtr<nsRunnable> r = new SocketIORequestClosingRunnable<T>(aIO);
|
||||
NS_DispatchToMainThread(r);
|
||||
return -1;
|
||||
} else if (!res) {
|
||||
/* EOF or peer shut down sending */
|
||||
nsRefPtr<nsRunnable> r = new SocketIORequestClosingRunnable<T>(aIO);
|
||||
NS_DispatchToMainThread(r);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef MOZ_TASK_TRACER
|
||||
// Make unix socket creation events to be the source events of TaskTracer,
|
||||
// and originate the rest correlation tasks from here.
|
||||
AutoSourceEvent taskTracerEvent(SourceEventType::Unixsocket);
|
||||
#endif
|
||||
|
||||
nsRefPtr<nsRunnable> r =
|
||||
new SocketIOReceiveRunnable<T>(aIO, incoming.forget());
|
||||
NS_DispatchToMainThread(r);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
nsresult SendPendingData(int aFd, T* aIO)
|
||||
{
|
||||
MOZ_ASSERT(aFd >= 0);
|
||||
MOZ_ASSERT(aIO);
|
||||
|
||||
while (HasPendingData()) {
|
||||
UnixSocketIOBuffer* outgoing = mOutgoingQ.ElementAt(0);
|
||||
|
||||
ssize_t res = outgoing->Send(aFd);
|
||||
if (res < 0) {
|
||||
/* an I/O error occured */
|
||||
nsRefPtr<nsRunnable> r = new SocketIORequestClosingRunnable<T>(aIO);
|
||||
NS_DispatchToMainThread(r);
|
||||
return NS_ERROR_FAILURE;
|
||||
} else if (!res && outgoing->GetSize()) {
|
||||
/* I/O is currently blocked; try again later */
|
||||
return NS_OK;
|
||||
}
|
||||
if (!outgoing->GetSize()) {
|
||||
mOutgoingQ.RemoveElementAt(0);
|
||||
delete outgoing;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
SocketIOBase(size_t aMaxReadSize);
|
||||
|
||||
private:
|
||||
const size_t mMaxReadSize;
|
||||
|
||||
/**
|
||||
* Raw data queue. Must be pushed/popped from I/O thread only.
|
||||
*/
|
||||
nsTArray<UnixSocketIOBuffer*> mOutgoingQ;
|
||||
SocketIOBase();
|
||||
};
|
||||
|
||||
//
|
||||
@ -634,36 +497,6 @@ private:
|
||||
Tio* mIO;
|
||||
};
|
||||
|
||||
/* |SocketIOSendTask| transfers an instance of |Tdata|, such as
|
||||
* |UnixSocketRawData|, to the I/O thread and queues it up for
|
||||
* sending the contained data.
|
||||
*/
|
||||
template<typename Tio, typename Tdata>
|
||||
class SocketIOSendTask final : public SocketIOTask<Tio>
|
||||
{
|
||||
public:
|
||||
SocketIOSendTask(Tio* aIO, Tdata* aData)
|
||||
: SocketIOTask<Tio>(aIO)
|
||||
, mData(aData)
|
||||
{
|
||||
MOZ_ASSERT(aData);
|
||||
}
|
||||
|
||||
void Run() override
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_ASSERT(!SocketIOTask<Tio>::IsCanceled());
|
||||
|
||||
Tio* io = SocketIOTask<Tio>::GetIO();
|
||||
MOZ_ASSERT(!io->IsShutdownOnIOThread());
|
||||
|
||||
io->Send(mData);
|
||||
}
|
||||
|
||||
private:
|
||||
Tdata* mData;
|
||||
};
|
||||
|
||||
/* |SocketIOShutdownTask| signals shutdown to the Socket I/O object on
|
||||
* the I/O thread and sends it to the main thread for destruction.
|
||||
*/
|
||||
|
@ -19,13 +19,15 @@ namespace ipc {
|
||||
// StreamSocketIO
|
||||
//
|
||||
|
||||
class StreamSocketIO final : public UnixSocketWatcher
|
||||
, protected SocketIOBase
|
||||
, public ConnectionOrientedSocketIO
|
||||
class StreamSocketIO final
|
||||
: public UnixSocketWatcher
|
||||
, protected DataSocketIO
|
||||
, public ConnectionOrientedSocketIO
|
||||
{
|
||||
public:
|
||||
class ConnectTask;
|
||||
class DelayedConnectTask;
|
||||
class ReceiveRunnable;
|
||||
|
||||
StreamSocketIO(MessageLoop* mIOLoop,
|
||||
StreamSocket* aStreamSocket,
|
||||
@ -38,9 +40,11 @@ public:
|
||||
const nsACString& aAddress);
|
||||
~StreamSocketIO();
|
||||
|
||||
void GetSocketAddr(nsAString& aAddrStr) const;
|
||||
SocketConsumerBase* GetConsumer();
|
||||
SocketBase* GetSocketBase();
|
||||
void GetSocketAddr(nsAString& aAddrStr) const;
|
||||
|
||||
StreamSocket* GetStreamSocket();
|
||||
DataSocket* GetDataSocket();
|
||||
SocketBase* GetSocketBase();
|
||||
|
||||
// StreamSocketIOBase
|
||||
//
|
||||
@ -85,6 +89,13 @@ public:
|
||||
void OnSocketCanReceiveWithoutBlocking() override;
|
||||
void OnSocketCanSendWithoutBlocking() override;
|
||||
|
||||
// Methods for |DataSocket|
|
||||
//
|
||||
|
||||
nsresult QueryReceiveBuffer(UnixSocketIOBuffer** aBuffer);
|
||||
void ConsumeBuffer();
|
||||
void DiscardBuffer();
|
||||
|
||||
private:
|
||||
void FireSocketError();
|
||||
|
||||
@ -127,19 +138,23 @@ private:
|
||||
* Task member for delayed connect task. Should only be access on main thread.
|
||||
*/
|
||||
CancelableTask* mDelayedConnectTask;
|
||||
|
||||
/**
|
||||
* I/O buffer for received data
|
||||
*/
|
||||
nsAutoPtr<UnixSocketRawData> mBuffer;
|
||||
};
|
||||
|
||||
StreamSocketIO::StreamSocketIO(MessageLoop* mIOLoop,
|
||||
StreamSocket* aStreamSocket,
|
||||
UnixSocketConnector* aConnector,
|
||||
const nsACString& aAddress)
|
||||
: UnixSocketWatcher(mIOLoop)
|
||||
, SocketIOBase(MAX_READ_SIZE)
|
||||
, mStreamSocket(aStreamSocket)
|
||||
, mConnector(aConnector)
|
||||
, mShuttingDownOnIOThread(false)
|
||||
, mAddress(aAddress)
|
||||
, mDelayedConnectTask(nullptr)
|
||||
: UnixSocketWatcher(mIOLoop)
|
||||
, mStreamSocket(aStreamSocket)
|
||||
, mConnector(aConnector)
|
||||
, mShuttingDownOnIOThread(false)
|
||||
, mAddress(aAddress)
|
||||
, mDelayedConnectTask(nullptr)
|
||||
{
|
||||
MOZ_ASSERT(mStreamSocket);
|
||||
MOZ_ASSERT(mConnector);
|
||||
@ -150,13 +165,12 @@ StreamSocketIO::StreamSocketIO(MessageLoop* mIOLoop, int aFd,
|
||||
StreamSocket* aStreamSocket,
|
||||
UnixSocketConnector* aConnector,
|
||||
const nsACString& aAddress)
|
||||
: UnixSocketWatcher(mIOLoop, aFd, aConnectionStatus)
|
||||
, SocketIOBase(MAX_READ_SIZE)
|
||||
, mStreamSocket(aStreamSocket)
|
||||
, mConnector(aConnector)
|
||||
, mShuttingDownOnIOThread(false)
|
||||
, mAddress(aAddress)
|
||||
, mDelayedConnectTask(nullptr)
|
||||
: UnixSocketWatcher(mIOLoop, aFd, aConnectionStatus)
|
||||
, mStreamSocket(aStreamSocket)
|
||||
, mConnector(aConnector)
|
||||
, mShuttingDownOnIOThread(false)
|
||||
, mAddress(aAddress)
|
||||
, mDelayedConnectTask(nullptr)
|
||||
{
|
||||
MOZ_ASSERT(mStreamSocket);
|
||||
MOZ_ASSERT(mConnector);
|
||||
@ -179,8 +193,14 @@ StreamSocketIO::GetSocketAddr(nsAString& aAddrStr) const
|
||||
mConnector->GetSocketAddr(mAddr, aAddrStr);
|
||||
}
|
||||
|
||||
SocketConsumerBase*
|
||||
StreamSocketIO::GetConsumer()
|
||||
StreamSocket*
|
||||
StreamSocketIO::GetStreamSocket()
|
||||
{
|
||||
return mStreamSocket.get();
|
||||
}
|
||||
|
||||
DataSocket*
|
||||
StreamSocketIO::GetDataSocket()
|
||||
{
|
||||
return mStreamSocket.get();
|
||||
}
|
||||
@ -188,7 +208,7 @@ StreamSocketIO::GetConsumer()
|
||||
SocketBase*
|
||||
StreamSocketIO::GetSocketBase()
|
||||
{
|
||||
return GetConsumer();
|
||||
return GetDataSocket();
|
||||
}
|
||||
|
||||
bool
|
||||
@ -497,6 +517,68 @@ StreamSocketIO::SetSocketFlags(int aFd)
|
||||
return true;
|
||||
}
|
||||
|
||||
nsresult
|
||||
StreamSocketIO::QueryReceiveBuffer(UnixSocketIOBuffer** aBuffer)
|
||||
{
|
||||
MOZ_ASSERT(aBuffer);
|
||||
|
||||
if (!mBuffer) {
|
||||
mBuffer = new UnixSocketRawData(MAX_READ_SIZE);
|
||||
}
|
||||
*aBuffer = mBuffer.get();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* |ReceiveRunnable| transfers data received on the I/O thread
|
||||
* to an instance of |StreamSocket| on the main thread.
|
||||
*/
|
||||
class StreamSocketIO::ReceiveRunnable final
|
||||
: public SocketIORunnable<StreamSocketIO>
|
||||
{
|
||||
public:
|
||||
ReceiveRunnable(StreamSocketIO* aIO, UnixSocketBuffer* aBuffer)
|
||||
: SocketIORunnable<StreamSocketIO>(aIO)
|
||||
, mBuffer(aBuffer)
|
||||
{ }
|
||||
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
StreamSocketIO* io = SocketIORunnable<StreamSocketIO>::GetIO();
|
||||
|
||||
if (NS_WARN_IF(io->IsShutdownOnMainThread())) {
|
||||
// Since we've already explicitly closed and the close
|
||||
// happened before this, this isn't really an error.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
StreamSocket* streamSocket = io->GetStreamSocket();
|
||||
MOZ_ASSERT(streamSocket);
|
||||
|
||||
streamSocket->ReceiveSocketData(mBuffer);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsAutoPtr<UnixSocketBuffer> mBuffer;
|
||||
};
|
||||
|
||||
void
|
||||
StreamSocketIO::ConsumeBuffer()
|
||||
{
|
||||
NS_DispatchToMainThread(new ReceiveRunnable(this, mBuffer.forget()));
|
||||
}
|
||||
|
||||
void
|
||||
StreamSocketIO::DiscardBuffer()
|
||||
{
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
//
|
||||
// Socket tasks
|
||||
//
|
||||
|
@ -7,7 +7,7 @@
|
||||
#ifndef mozilla_ipc_streamsocket_h
|
||||
#define mozilla_ipc_streamsocket_h
|
||||
|
||||
#include "mozilla/ipc/SocketBase.h"
|
||||
#include "mozilla/ipc/DataSocket.h"
|
||||
#include "ConnectionOrientedSocket.h"
|
||||
|
||||
namespace mozilla {
|
||||
@ -16,12 +16,20 @@ namespace ipc {
|
||||
class StreamSocketIO;
|
||||
class UnixSocketConnector;
|
||||
|
||||
class StreamSocket : public SocketConsumerBase
|
||||
class StreamSocket : public DataSocket
|
||||
, public ConnectionOrientedSocket
|
||||
{
|
||||
public:
|
||||
StreamSocket();
|
||||
|
||||
/**
|
||||
* Method to be called whenever data is received. This is only called on the
|
||||
* main thread.
|
||||
*
|
||||
* @param aBuffer Data received from the socket.
|
||||
*/
|
||||
virtual void ReceiveSocketData(nsAutoPtr<UnixSocketBuffer>& aBuffer) = 0;
|
||||
|
||||
/**
|
||||
* Queue data to be sent to the socket on the IO thread. Can only be called on
|
||||
* originating thread.
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
EXPORTS.mozilla.ipc += [
|
||||
'ConnectionOrientedSocket.h',
|
||||
'DataSocket.h',
|
||||
'ListenSocket.h',
|
||||
'SocketBase.h',
|
||||
'StreamSocket.h',
|
||||
@ -14,6 +15,7 @@ EXPORTS.mozilla.ipc += [
|
||||
|
||||
SOURCES += [
|
||||
'ConnectionOrientedSocket.cpp',
|
||||
'DataSocket.cpp',
|
||||
'ListenSocket.cpp',
|
||||
'SocketBase.cpp',
|
||||
'StreamSocket.cpp',
|
||||
|
@ -63,15 +63,34 @@ template bool js::IsVectorObject<Int32x4>(HandleValue v);
|
||||
template bool js::IsVectorObject<Float32x4>(HandleValue v);
|
||||
template bool js::IsVectorObject<Float64x2>(HandleValue v);
|
||||
|
||||
static inline bool
|
||||
ErrorBadArgs(JSContext* cx)
|
||||
{
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
ErrorWrongTypeArg(JSContext* cx, size_t argIndex, Handle<TypeDescr*> typeDescr)
|
||||
{
|
||||
MOZ_ASSERT(argIndex < 10);
|
||||
char charArgIndex[2];
|
||||
JS_snprintf(charArgIndex, sizeof charArgIndex, "%d", argIndex);
|
||||
|
||||
HeapSlot& typeNameSlot = typeDescr->getReservedSlotRef(JS_DESCR_SLOT_STRING_REPR);
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_SIMD_NOT_A_VECTOR,
|
||||
JS_EncodeString(cx, typeNameSlot.toString()), charArgIndex);
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename V>
|
||||
bool
|
||||
js::ToSimdConstant(JSContext* cx, HandleValue v, jit::SimdConstant* out)
|
||||
{
|
||||
typedef typename V::Elem Elem;
|
||||
if (!IsVectorObject<V>(v)) {
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_SIMD_NOT_A_VECTOR);
|
||||
return false;
|
||||
}
|
||||
Rooted<TypeDescr*> typeDescr(cx, &V::GetTypeDescr(*cx->global()));
|
||||
if (!IsVectorObject<V>(v))
|
||||
return ErrorWrongTypeArg(cx, 1, typeDescr);
|
||||
|
||||
Elem* mem = reinterpret_cast<Elem*>(v.toObject().as<TypedObject>().typedMem());
|
||||
*out = jit::SimdConstant::CreateX4(mem);
|
||||
@ -622,13 +641,6 @@ struct ShiftRightLogical {
|
||||
};
|
||||
}
|
||||
|
||||
static inline bool
|
||||
ErrorBadArgs(JSContext* cx)
|
||||
{
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename Out>
|
||||
static bool
|
||||
StoreResult(JSContext* cx, CallArgs& args, typename Out::Elem* result)
|
||||
|
@ -658,14 +658,15 @@ NonLocalExitScope::prepareForNonLocalJump(StmtInfoBCE* toStmt)
|
||||
if (stmt->isBlockScope) {
|
||||
MOZ_ASSERT(stmt->isNestedScope);
|
||||
StaticBlockObject& blockObj = stmt->staticBlock();
|
||||
if (!bce->emit1(JSOP_DEBUGLEAVEBLOCK))
|
||||
return false;
|
||||
if (!popScopeForNonLocalExit(stmt->blockScopeIndex))
|
||||
return false;
|
||||
if (blockObj.needsClone()) {
|
||||
if (!bce->emit1(JSOP_POPBLOCKSCOPE))
|
||||
return false;
|
||||
} else {
|
||||
if (!bce->emit1(JSOP_DEBUGLEAVEBLOCK))
|
||||
return false;
|
||||
}
|
||||
if (!popScopeForNonLocalExit(stmt->blockScopeIndex))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -877,12 +878,18 @@ BytecodeEmitter::computeLocalOffset(Handle<StaticBlockObject*> blockObj)
|
||||
// Only functions have fixed var bindings.
|
||||
//
|
||||
// To assist the debugger, we emit a DEBUGLEAVEBLOCK opcode before leaving a
|
||||
// block scope, even if the block has no aliased locals. This allows
|
||||
// DebugScopes to invalidate any association between a debugger scope object,
|
||||
// which can proxy access to unaliased stack locals, and the actual live frame.
|
||||
// In normal, non-debug mode, this opcode does not cause any baseline code to be
|
||||
// block scope, if the block has no aliased locals. This allows DebugScopes
|
||||
// to invalidate any association between a debugger scope object, which can
|
||||
// proxy access to unaliased stack locals, and the actual live frame. In
|
||||
// normal, non-debug mode, this opcode does not cause any baseline code to be
|
||||
// emitted.
|
||||
//
|
||||
// If the block has aliased locals, no DEBUGLEAVEBLOCK is emitted, and
|
||||
// POPBLOCKSCOPE itself balances the debug scope mapping. This gets around a
|
||||
// comedic situation where DEBUGLEAVEBLOCK may remove a block scope from the
|
||||
// debug scope map, but the immediate following POPBLOCKSCOPE adds it back due
|
||||
// to an onStep hook.
|
||||
//
|
||||
// Enter a nested scope with enterNestedScope. It will emit
|
||||
// PUSHBLOCKSCOPE/ENTERWITH if needed, and arrange to record the PC bounds of
|
||||
// the scope. Leave a nested scope with leaveNestedScope, which, for blocks,
|
||||
@ -974,11 +981,16 @@ BytecodeEmitter::leaveNestedScope(StmtInfoBCE* stmt)
|
||||
|
||||
popStatement();
|
||||
|
||||
if (!emit1(stmt->isBlockScope ? JSOP_DEBUGLEAVEBLOCK : JSOP_LEAVEWITH))
|
||||
return false;
|
||||
|
||||
if (stmt->isBlockScope && stmt->staticScope->as<StaticBlockObject>().needsClone()) {
|
||||
if (!emit1(JSOP_POPBLOCKSCOPE))
|
||||
if (stmt->isBlockScope) {
|
||||
if (stmt->staticScope->as<StaticBlockObject>().needsClone()) {
|
||||
if (!emit1(JSOP_POPBLOCKSCOPE))
|
||||
return false;
|
||||
} else {
|
||||
if (!emit1(JSOP_DEBUGLEAVEBLOCK))
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!emit1(JSOP_LEAVEWITH))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -633,6 +633,15 @@ class FullParseHandler
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isReturnStatement(ParseNode* node) {
|
||||
return node->isKind(PNK_RETURN);
|
||||
}
|
||||
|
||||
bool isStatementPermittedAfterReturnStatement(ParseNode *node) {
|
||||
ParseNodeKind kind = node->getKind();
|
||||
return kind == PNK_FUNCTION || kind == PNK_VAR || kind == PNK_BREAK || kind == PNK_THROW;
|
||||
}
|
||||
|
||||
inline bool finishInitializerAssignment(ParseNode* pn, ParseNode* init, JSOp op);
|
||||
|
||||
void setBeginPosition(ParseNode* pn, ParseNode* oth) {
|
||||
@ -659,11 +668,23 @@ class FullParseHandler
|
||||
}
|
||||
|
||||
ParseNode* newList(ParseNodeKind kind, JSOp op = JSOP_NOP) {
|
||||
MOZ_ASSERT(kind != PNK_VAR);
|
||||
return new_<ListNode>(kind, op, pos());
|
||||
}
|
||||
ParseNode* newDeclarationList(ParseNodeKind kind, JSOp op = JSOP_NOP) {
|
||||
MOZ_ASSERT(kind == PNK_VAR || kind == PNK_CONST || kind == PNK_LET ||
|
||||
kind == PNK_GLOBALCONST);
|
||||
return new_<ListNode>(kind, op, pos());
|
||||
}
|
||||
|
||||
/* New list with one initial child node. kid must be non-null. */
|
||||
ParseNode* newList(ParseNodeKind kind, ParseNode* kid, JSOp op = JSOP_NOP) {
|
||||
MOZ_ASSERT(kind != PNK_VAR);
|
||||
return new_<ListNode>(kind, op, kid);
|
||||
}
|
||||
ParseNode* newDeclarationList(ParseNodeKind kind, ParseNode* kid, JSOp op = JSOP_NOP) {
|
||||
MOZ_ASSERT(kind == PNK_VAR || kind == PNK_CONST || kind == PNK_LET ||
|
||||
kind == PNK_GLOBALCONST);
|
||||
return new_<ListNode>(kind, op, kid);
|
||||
}
|
||||
|
||||
|
@ -1670,7 +1670,7 @@ Parser<ParseHandler>::functionArguments(FunctionSyntaxKind kind, FunctionType ty
|
||||
if (list) {
|
||||
handler.addList(list, item);
|
||||
} else {
|
||||
list = handler.newList(PNK_VAR, item);
|
||||
list = handler.newDeclarationList(PNK_VAR, item);
|
||||
if (!list)
|
||||
return false;
|
||||
*listp = list;
|
||||
@ -2820,6 +2820,9 @@ Parser<ParseHandler>::statements()
|
||||
pc->blockNode = pn;
|
||||
|
||||
bool canHaveDirectives = pc->atBodyLevel();
|
||||
bool afterReturn = false;
|
||||
bool warnedAboutStatementsAfterReturn = false;
|
||||
uint32_t statementBegin;
|
||||
for (;;) {
|
||||
TokenKind tt;
|
||||
if (!tokenStream.peekToken(&tt, TokenStream::Operand)) {
|
||||
@ -2829,12 +2832,32 @@ Parser<ParseHandler>::statements()
|
||||
}
|
||||
if (tt == TOK_EOF || tt == TOK_RC)
|
||||
break;
|
||||
if (afterReturn) {
|
||||
TokenPos pos(0, 0);
|
||||
if (!tokenStream.peekTokenPos(&pos, TokenStream::Operand))
|
||||
return null();
|
||||
statementBegin = pos.begin;
|
||||
}
|
||||
Node next = statement(canHaveDirectives);
|
||||
if (!next) {
|
||||
if (tokenStream.isEOF())
|
||||
isUnexpectedEOF_ = true;
|
||||
return null();
|
||||
}
|
||||
if (!warnedAboutStatementsAfterReturn) {
|
||||
if (afterReturn) {
|
||||
if (!handler.isStatementPermittedAfterReturnStatement(next)) {
|
||||
if (!reportWithOffset(ParseWarning, false, statementBegin,
|
||||
JSMSG_STMT_AFTER_RETURN))
|
||||
{
|
||||
return null();
|
||||
}
|
||||
warnedAboutStatementsAfterReturn = true;
|
||||
}
|
||||
} else if (handler.isReturnStatement(next)) {
|
||||
afterReturn = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (canHaveDirectives) {
|
||||
if (!maybeParseDirective(pn, next, &canHaveDirectives))
|
||||
@ -3803,7 +3826,7 @@ Parser<ParseHandler>::variables(ParseNodeKind kind, bool* psimple,
|
||||
else if (kind == PNK_GLOBALCONST)
|
||||
op = JSOP_DEFCONST;
|
||||
|
||||
Node pn = handler.newList(kind, op);
|
||||
Node pn = handler.newDeclarationList(kind, op);
|
||||
if (!pn)
|
||||
return null();
|
||||
|
||||
@ -5168,14 +5191,37 @@ Parser<ParseHandler>::switchStatement()
|
||||
if (!body)
|
||||
return null();
|
||||
|
||||
bool afterReturn = false;
|
||||
bool warnedAboutStatementsAfterReturn = false;
|
||||
uint32_t statementBegin;
|
||||
while (true) {
|
||||
if (!tokenStream.peekToken(&tt, TokenStream::Operand))
|
||||
return null();
|
||||
if (tt == TOK_RC || tt == TOK_CASE || tt == TOK_DEFAULT)
|
||||
break;
|
||||
if (afterReturn) {
|
||||
TokenPos pos(0, 0);
|
||||
if (!tokenStream.peekTokenPos(&pos, TokenStream::Operand))
|
||||
return null();
|
||||
statementBegin = pos.begin;
|
||||
}
|
||||
Node stmt = statement();
|
||||
if (!stmt)
|
||||
return null();
|
||||
if (!warnedAboutStatementsAfterReturn) {
|
||||
if (afterReturn) {
|
||||
if (!handler.isStatementPermittedAfterReturnStatement(stmt)) {
|
||||
if (!reportWithOffset(ParseWarning, false, statementBegin,
|
||||
JSMSG_STMT_AFTER_RETURN))
|
||||
{
|
||||
return null();
|
||||
}
|
||||
warnedAboutStatementsAfterReturn = true;
|
||||
}
|
||||
} else if (handler.isReturnStatement(stmt)) {
|
||||
afterReturn = true;
|
||||
}
|
||||
}
|
||||
handler.addList(body, stmt);
|
||||
}
|
||||
|
||||
@ -5319,19 +5365,7 @@ Parser<ParseHandler>::returnStatement()
|
||||
if (!tokenStream.peekTokenSameLine(&tt, TokenStream::Operand))
|
||||
return null();
|
||||
switch (tt) {
|
||||
case TOK_EOL: {
|
||||
bool startsExpr;
|
||||
if (!tokenStream.nextTokenStartsExpr(&startsExpr, TokenStream::Operand))
|
||||
return null();
|
||||
if (startsExpr) {
|
||||
TokenPos pos;
|
||||
if (!tokenStream.peekTokenPos(&pos, TokenStream::Operand))
|
||||
return null();
|
||||
if (!reportWithOffset(ParseWarning, false, pos.begin, JSMSG_STMT_AFTER_SEMI_LESS))
|
||||
return null();
|
||||
}
|
||||
// Fall through.
|
||||
}
|
||||
case TOK_EOL:
|
||||
case TOK_EOF:
|
||||
case TOK_SEMI:
|
||||
case TOK_RC:
|
||||
|
@ -43,6 +43,10 @@ class SyntaxParseHandler
|
||||
NodeGetProp,
|
||||
NodeStringExprStatement,
|
||||
NodeLValue,
|
||||
NodeReturn,
|
||||
NodeHoistableDeclaration,
|
||||
NodeBreak,
|
||||
NodeThrow,
|
||||
|
||||
// In rare cases a parenthesized |node| doesn't have the same semantics
|
||||
// as |node|. Each such node has a special Node value, and we use a
|
||||
@ -214,14 +218,14 @@ class SyntaxParseHandler
|
||||
Node newSwitchStatement(uint32_t begin, Node discriminant, Node caseList) { return NodeGeneric; }
|
||||
Node newCaseOrDefault(uint32_t begin, Node expr, Node body) { return NodeGeneric; }
|
||||
Node newContinueStatement(PropertyName* label, const TokenPos& pos) { return NodeGeneric; }
|
||||
Node newBreakStatement(PropertyName* label, const TokenPos& pos) { return NodeGeneric; }
|
||||
Node newReturnStatement(Node expr, Node genrval, const TokenPos& pos) { return NodeGeneric; }
|
||||
Node newBreakStatement(PropertyName* label, const TokenPos& pos) { return NodeBreak; }
|
||||
Node newReturnStatement(Node expr, Node genrval, const TokenPos& pos) { return NodeReturn; }
|
||||
|
||||
Node newLabeledStatement(PropertyName* label, Node stmt, uint32_t begin) {
|
||||
return NodeGeneric;
|
||||
}
|
||||
|
||||
Node newThrowStatement(Node expr, const TokenPos& pos) { return NodeGeneric; }
|
||||
Node newThrowStatement(Node expr, const TokenPos& pos) { return NodeThrow; }
|
||||
Node newTryStatement(uint32_t begin, Node body, Node catchList, Node finallyBlock) {
|
||||
return NodeGeneric;
|
||||
}
|
||||
@ -238,7 +242,7 @@ class SyntaxParseHandler
|
||||
Node catchName, Node catchGuard, Node catchBody) { return true; }
|
||||
|
||||
void setLastFunctionArgumentDefault(Node funcpn, Node pn) {}
|
||||
Node newFunctionDefinition() { return NodeGeneric; }
|
||||
Node newFunctionDefinition() { return NodeHoistableDeclaration; }
|
||||
void setFunctionBody(Node pn, Node kid) {}
|
||||
void setFunctionBox(Node pn, FunctionBox* funbox) {}
|
||||
void addFunctionArgument(Node pn, Node argpn) {}
|
||||
@ -277,11 +281,23 @@ class SyntaxParseHandler
|
||||
}
|
||||
|
||||
Node newList(ParseNodeKind kind, JSOp op = JSOP_NOP) {
|
||||
MOZ_ASSERT(kind != PNK_VAR);
|
||||
return NodeGeneric;
|
||||
}
|
||||
Node newDeclarationList(ParseNodeKind kind, JSOp op = JSOP_NOP) {
|
||||
MOZ_ASSERT(kind == PNK_VAR || kind == PNK_CONST || kind == PNK_LET ||
|
||||
kind == PNK_GLOBALCONST);
|
||||
return kind == PNK_VAR ? NodeHoistableDeclaration : NodeGeneric;
|
||||
}
|
||||
Node newList(ParseNodeKind kind, Node kid, JSOp op = JSOP_NOP) {
|
||||
MOZ_ASSERT(kind != PNK_VAR);
|
||||
return NodeGeneric;
|
||||
}
|
||||
Node newDeclarationList(ParseNodeKind kind, Node kid, JSOp op = JSOP_NOP) {
|
||||
MOZ_ASSERT(kind == PNK_VAR || kind == PNK_CONST || kind == PNK_LET ||
|
||||
kind == PNK_GLOBALCONST);
|
||||
return kind == PNK_VAR ? NodeHoistableDeclaration : NodeGeneric;
|
||||
}
|
||||
|
||||
Node newCatchList() {
|
||||
return newList(PNK_CATCHLIST, JSOP_NOP);
|
||||
@ -292,7 +308,8 @@ class SyntaxParseHandler
|
||||
}
|
||||
|
||||
void addList(Node list, Node kid) {
|
||||
MOZ_ASSERT(list == NodeGeneric || list == NodeUnparenthesizedCommaExpr);
|
||||
MOZ_ASSERT(list == NodeGeneric || list == NodeUnparenthesizedCommaExpr ||
|
||||
list == NodeHoistableDeclaration);
|
||||
}
|
||||
|
||||
Node newAssignment(ParseNodeKind kind, Node lhs, Node rhs,
|
||||
@ -315,6 +332,14 @@ class SyntaxParseHandler
|
||||
return node == NodeUnparenthesizedAssignment;
|
||||
}
|
||||
|
||||
bool isReturnStatement(Node node) {
|
||||
return node == NodeReturn;
|
||||
}
|
||||
|
||||
bool isStatementPermittedAfterReturnStatement(Node pn) {
|
||||
return pn == NodeHoistableDeclaration || pn == NodeBreak || pn == NodeThrow;
|
||||
}
|
||||
|
||||
void setOp(Node pn, JSOp op) {}
|
||||
void setBlockId(Node pn, unsigned blockid) {}
|
||||
void setFlag(Node pn, unsigned flag) {}
|
||||
|
@ -322,33 +322,6 @@ TokenStream::TokenStream(ExclusiveContext* cx, const ReadOnlyCompileOptions& opt
|
||||
isExprEnding[TOK_RP] = 1;
|
||||
isExprEnding[TOK_RB] = 1;
|
||||
isExprEnding[TOK_RC] = 1;
|
||||
|
||||
memset(isExprStarting, 0, sizeof(isExprStarting));
|
||||
isExprStarting[TOK_INC] = 1;
|
||||
isExprStarting[TOK_DEC] = 1;
|
||||
isExprStarting[TOK_LB] = 1;
|
||||
isExprStarting[TOK_LC] = 1;
|
||||
isExprStarting[TOK_LP] = 1;
|
||||
isExprStarting[TOK_NAME] = 1;
|
||||
isExprStarting[TOK_NUMBER] = 1;
|
||||
isExprStarting[TOK_STRING] = 1;
|
||||
isExprStarting[TOK_TEMPLATE_HEAD] = 1;
|
||||
isExprStarting[TOK_NO_SUBS_TEMPLATE] = 1;
|
||||
isExprStarting[TOK_REGEXP] = 1;
|
||||
isExprStarting[TOK_TRUE] = 1;
|
||||
isExprStarting[TOK_FALSE] = 1;
|
||||
isExprStarting[TOK_NULL] = 1;
|
||||
isExprStarting[TOK_THIS] = 1;
|
||||
isExprStarting[TOK_NEW] = 1;
|
||||
isExprStarting[TOK_DELETE] = 1;
|
||||
isExprStarting[TOK_YIELD] = 1;
|
||||
isExprStarting[TOK_CLASS] = 1;
|
||||
isExprStarting[TOK_ADD] = 1;
|
||||
isExprStarting[TOK_SUB] = 1;
|
||||
isExprStarting[TOK_TYPEOF] = 1;
|
||||
isExprStarting[TOK_VOID] = 1;
|
||||
isExprStarting[TOK_NOT] = 1;
|
||||
isExprStarting[TOK_BITNOT] = 1;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
@ -658,6 +631,7 @@ TokenStream::reportCompileErrorNumberVA(uint32_t offset, unsigned flags, unsigne
|
||||
if (offset != NoOffset && !err.report.filename && cx->isJSContext()) {
|
||||
NonBuiltinFrameIter iter(cx->asJSContext(),
|
||||
FrameIter::ALL_CONTEXTS, FrameIter::GO_THROUGH_SAVED,
|
||||
FrameIter::FOLLOW_DEBUGGER_EVAL_PREV_LINK,
|
||||
cx->compartment()->principals());
|
||||
if (!iter.done() && iter.scriptFilename()) {
|
||||
callerFilename = true;
|
||||
|
@ -494,14 +494,6 @@ class MOZ_STACK_CLASS TokenStream
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nextTokenStartsExpr(bool* startsExpr, Modifier modifier = None) {
|
||||
TokenKind tt;
|
||||
if (!peekToken(&tt, modifier))
|
||||
return false;
|
||||
*startsExpr = isExprStarting[tt];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nextTokenEndsExpr(bool* endsExpr) {
|
||||
TokenKind tt;
|
||||
if (!peekToken(&tt))
|
||||
@ -836,7 +828,6 @@ class MOZ_STACK_CLASS TokenStream
|
||||
mozilla::UniquePtr<char16_t[], JS::FreePolicy> displayURL_; // the user's requested source URL or null
|
||||
mozilla::UniquePtr<char16_t[], JS::FreePolicy> sourceMapURL_; // source map's filename or null
|
||||
CharBuffer tokenbuf; // current token string buffer
|
||||
uint8_t isExprStarting[TOK_LIMIT];// which tokens can start exprs?
|
||||
uint8_t isExprEnding[TOK_LIMIT];// which tokens definitely terminate exprs?
|
||||
ExclusiveContext* const cx;
|
||||
bool mutedErrors;
|
||||
|
@ -37,7 +37,7 @@ assertEq(asmLink(asmCompile(USE_ASM + 'function f(){;} return f'))(), undefined)
|
||||
assertAsmTypeFail(USE_ASM + 'function f(i,j){;} return f');
|
||||
assertEq(asmLink(asmCompile('"use asm";; function f(){};;; return f;;'))(), undefined);
|
||||
assertAsmTypeFail(USE_ASM + 'function f(x){} return f');
|
||||
assertAsmTypeFail(USE_ASM + 'function f(){return; return 1} return f');
|
||||
assertAsmTypeFail(USE_ASM + 'function f(){if (0) return; return 1} return f');
|
||||
assertEq(asmLink(asmCompile(USE_ASM + 'function f(x){x=x|0} return f'))(42), undefined);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + 'function f(x){x=x|0; return x|0} return f'))(42), 42);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + 'function f(x){x=x|0; return x|0;;;} return f'))(42), 42);
|
||||
|
@ -12,7 +12,7 @@ assertEq(asmLink(asmCompile(USE_ASM + "function f(i) { i=i|0; if ((i|0) == 0) i
|
||||
assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; if (i) return 0; } return f");
|
||||
assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; if (i) return 0; else return 1 } return f");
|
||||
assertAsmTypeFail(USE_ASM + "function f(i) { i=i|0; if (i) return 0; return 1.0 } return f");
|
||||
assertAsmTypeFail(USE_ASM + "function f() { return 0; 1 } return f");
|
||||
assertAsmTypeFail(USE_ASM + "function f() { if (0) return 0; 1 } return f");
|
||||
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "function f() { while (0) {} return 0} return f"))(), 0);
|
||||
assertEq(asmLink(asmCompile(USE_ASM + "function f() { for (;0;) {} return 0} return f"))(), 0);
|
||||
|
@ -30,7 +30,7 @@ assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { retu
|
||||
assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { return +(inc() + 1.1) } return f');
|
||||
assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { return (+inc() + 1)|0 } return f');
|
||||
assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { var i = 0; inc(i>>>0) } return f');
|
||||
assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { return inc(); return } return f');
|
||||
assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { if (0) return inc(); return } return f');
|
||||
assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { inc(inc()) } return f');
|
||||
assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { g(inc()) } function g() {} return f');
|
||||
assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { inc()|inc() } return f');
|
||||
|
@ -137,7 +137,7 @@ assertAsmTypeFail('glob', 'ffis', 'b', USE_ASM + IMPORT1 + 'function ch(b2) { if
|
||||
assertAsmTypeFail('glob', 'ffis', 'b', USE_ASM + IMPORT1 + 'function ch(b2) { if(len(b2) & 0xffffff || len(b2) <= 0xffffff || len(b2) > 0x80000000) return false; i8=new I8(b2); b=b2; return } function f() { return 42 } return f');
|
||||
assertAsmTypeFail('glob', 'ffis', 'b', USE_ASM + IMPORT1 + 'function ch(b2) { if(len(b2) & 0xffffff || len(b2) <= 0xffffff || len(b2) > 0x80000000) return false; i8=new I8(b2); b=b2; return 1 } function f() { return 42 } return f');
|
||||
assertAsmTypeFail('glob', 'ffis', 'b', USE_ASM + IMPORT1 + 'function ch(b2) { if(len(b2) & 0xffffff || len(b2) <= 0xffffff || len(b2) > 0x80000000) return false; i8=new I8(b2); b=b2; return false } function f() { return 42 } return f');
|
||||
assertAsmTypeFail('glob', 'ffis', 'b', USE_ASM + IMPORT1 + 'function ch(b2) { if(len(b2) & 0xffffff || len(b2) <= 0xffffff || len(b2) > 0x80000000) return false; i8=new I8(b2); b=b2; return true; 1 } function f() { return 42 } return f');
|
||||
assertAsmTypeFail('glob', 'ffis', 'b', USE_ASM + IMPORT1 + 'function ch(b2) { if(len(b2) & 0xffffff || len(b2) <= 0xffffff || len(b2) > 0x80000000) return false; i8=new I8(b2); b=b2; if (0) return true; 1 } function f() { return 42 } return f');
|
||||
assertAsmTypeFail('glob', 'ffis', 'b', USE_ASM + IMPORT2 + 'function ch(b2) { if(len(b2) & 0xffffff || len(b2) <= 0xffffff || len(b2) > 0x80000000) return false; i8=new I8(b2); b=b2; return true } function f() { return 42 } return f');
|
||||
assertAsmTypeFail('glob', 'ffis', 'b', USE_ASM + IMPORT2 + 'function ch(b2) { if(len(b2) & 0xffffff || len(b2) <= 0xffffff || len(b2) > 0x80000000) return false; i32=new I32(b2); b=b2; return true } function f() { return 42 } return f');
|
||||
assertAsmTypeFail('glob', 'ffis', 'b', USE_ASM + IMPORT2 + 'function ch(b2) { if(len(b2) & 0xffffff || len(b2) <= 0xffffff || len(b2) > 0x80000000) return false; i32=new I32(b2); i8=new I8(b2); b=b2; return true } function f() { return 42 } return f');
|
||||
|
@ -1,5 +1,4 @@
|
||||
// Warning should be shown for expression-like statement after semicolon-less
|
||||
// return (bug 1005110).
|
||||
// Warning should be shown for unreachable statement after return (bug 1151931).
|
||||
|
||||
load(libdir + "class.js");
|
||||
|
||||
@ -12,7 +11,7 @@ function testWarn(code, lineNumber, columnNumber) {
|
||||
eval(code);
|
||||
} catch (e) {
|
||||
caught = true;
|
||||
assertEq(e.message, "unreachable expression after semicolon-less return statement", code);
|
||||
assertEq(e.constructor, SyntaxError);
|
||||
assertEq(e.lineNumber, lineNumber);
|
||||
assertEq(e.columnNumber, columnNumber);
|
||||
}
|
||||
@ -23,7 +22,7 @@ function testWarn(code, lineNumber, columnNumber) {
|
||||
Reflect.parse(code);
|
||||
} catch (e) {
|
||||
caught = true;
|
||||
assertEq(e.message, "unreachable expression after semicolon-less return statement", code);
|
||||
assertEq(e.constructor, SyntaxError);
|
||||
}
|
||||
assertEq(caught, true, "warning should be caught for " + code);
|
||||
}
|
||||
@ -46,8 +45,6 @@ function testPass(code) {
|
||||
assertEq(caught, false, "warning should not be caught for " + code);
|
||||
}
|
||||
|
||||
// not EOL
|
||||
|
||||
testPass(`
|
||||
function f() {
|
||||
return (
|
||||
@ -55,16 +52,8 @@ function f() {
|
||||
);
|
||||
}
|
||||
`);
|
||||
testPass(`
|
||||
function f() {
|
||||
return;
|
||||
1 + 2;
|
||||
}
|
||||
`);
|
||||
|
||||
// starts expression
|
||||
|
||||
// TOK_INC
|
||||
// unary expression
|
||||
testWarn(`
|
||||
function f() {
|
||||
var i = 0;
|
||||
@ -72,8 +61,6 @@ function f() {
|
||||
++i;
|
||||
}
|
||||
`, 5, 4);
|
||||
|
||||
// TOK_DEC
|
||||
testWarn(`
|
||||
function f() {
|
||||
var i = 0;
|
||||
@ -82,7 +69,7 @@ function f() {
|
||||
}
|
||||
`, 5, 4);
|
||||
|
||||
// TOK_LB
|
||||
// array
|
||||
testWarn(`
|
||||
function f() {
|
||||
return
|
||||
@ -90,7 +77,7 @@ function f() {
|
||||
}
|
||||
`, 4, 4);
|
||||
|
||||
// TOK_LC
|
||||
// block (object)
|
||||
testWarn(`
|
||||
function f() {
|
||||
return
|
||||
@ -109,7 +96,7 @@ function f() {
|
||||
}
|
||||
`, 4, 2);
|
||||
|
||||
// TOK_LP
|
||||
// expression in paren
|
||||
testWarn(`
|
||||
function f() {
|
||||
return
|
||||
@ -117,7 +104,7 @@ function f() {
|
||||
}
|
||||
`, 4, 4);
|
||||
|
||||
// TOK_NAME
|
||||
// name
|
||||
testWarn(`
|
||||
function f() {
|
||||
return
|
||||
@ -125,7 +112,7 @@ function f() {
|
||||
}
|
||||
`, 4, 4);
|
||||
|
||||
// TOK_NUMBER
|
||||
// binary expression
|
||||
testWarn(`
|
||||
function f() {
|
||||
return
|
||||
@ -139,7 +126,7 @@ function f() {
|
||||
}
|
||||
`, 4, 4);
|
||||
|
||||
// TOK_STRING
|
||||
// string
|
||||
testWarn(`
|
||||
function f() {
|
||||
return
|
||||
@ -159,15 +146,13 @@ function f() {
|
||||
}
|
||||
`, 4, 4);
|
||||
|
||||
// TOK_TEMPLATE_HEAD
|
||||
// template string
|
||||
testWarn(`
|
||||
function f() {
|
||||
return
|
||||
\`foo\${1 + 2}\`;
|
||||
}
|
||||
`, 4, 4);
|
||||
|
||||
// TOK_NO_SUBS_TEMPLATE
|
||||
testWarn(`
|
||||
function f() {
|
||||
return
|
||||
@ -175,7 +160,7 @@ function f() {
|
||||
}
|
||||
`, 4, 4);
|
||||
|
||||
// TOK_REGEXP
|
||||
// RegExp
|
||||
testWarn(`
|
||||
function f() {
|
||||
return
|
||||
@ -183,15 +168,13 @@ function f() {
|
||||
}
|
||||
`, 4, 4);
|
||||
|
||||
// TOK_TRUE
|
||||
// boolean
|
||||
testWarn(`
|
||||
function f() {
|
||||
return
|
||||
true;
|
||||
}
|
||||
`, 4, 4);
|
||||
|
||||
// TOK_FALSE
|
||||
testWarn(`
|
||||
function f() {
|
||||
return
|
||||
@ -199,7 +182,7 @@ function f() {
|
||||
}
|
||||
`, 4, 4);
|
||||
|
||||
// TOK_NULL
|
||||
// null
|
||||
testWarn(`
|
||||
function f() {
|
||||
return
|
||||
@ -207,7 +190,7 @@ function f() {
|
||||
}
|
||||
`, 4, 4);
|
||||
|
||||
// TOK_THIS
|
||||
// this
|
||||
testWarn(`
|
||||
function f() {
|
||||
return
|
||||
@ -215,7 +198,7 @@ function f() {
|
||||
}
|
||||
`, 4, 4);
|
||||
|
||||
// TOK_NEW
|
||||
// new
|
||||
testWarn(`
|
||||
function f() {
|
||||
return
|
||||
@ -223,7 +206,7 @@ function f() {
|
||||
}
|
||||
`, 4, 4);
|
||||
|
||||
// TOK_DELETE
|
||||
// delete
|
||||
testWarn(`
|
||||
function f() {
|
||||
var a = {x: 10};
|
||||
@ -232,7 +215,7 @@ function f() {
|
||||
}
|
||||
`, 5, 4);
|
||||
|
||||
// TOK_YIELD
|
||||
// yield
|
||||
testWarn(`
|
||||
function* f() {
|
||||
return
|
||||
@ -240,7 +223,7 @@ function* f() {
|
||||
}
|
||||
`, 4, 4);
|
||||
|
||||
// TOK_CLASS
|
||||
// class
|
||||
if (classesEnabled()) {
|
||||
testWarn(`
|
||||
function f() {
|
||||
@ -250,31 +233,25 @@ function f() {
|
||||
`, 4, 4);
|
||||
}
|
||||
|
||||
// TOK_ADD
|
||||
// unary expression
|
||||
testWarn(`
|
||||
function f() {
|
||||
return
|
||||
+1;
|
||||
}
|
||||
`, 4, 4);
|
||||
|
||||
// TOK_SUB
|
||||
testWarn(`
|
||||
function f() {
|
||||
return
|
||||
-1;
|
||||
}
|
||||
`, 4, 4);
|
||||
|
||||
// TOK_NOT
|
||||
testWarn(`
|
||||
function f() {
|
||||
return
|
||||
!1;
|
||||
}
|
||||
`, 4, 4);
|
||||
|
||||
// TOK_BITNOT
|
||||
testWarn(`
|
||||
function f() {
|
||||
return
|
||||
@ -282,14 +259,12 @@ function f() {
|
||||
}
|
||||
`, 4, 4);
|
||||
|
||||
// don't start expression
|
||||
|
||||
// TOK_EOF
|
||||
// eof
|
||||
testPass(`
|
||||
var f = new Function("return\\n");
|
||||
`);
|
||||
|
||||
// TOK_SEMI
|
||||
// empty statement
|
||||
testPass(`
|
||||
function f() {
|
||||
return
|
||||
@ -297,7 +272,7 @@ function f() {
|
||||
}
|
||||
`);
|
||||
|
||||
// TOK_RC
|
||||
// end of block
|
||||
testPass(`
|
||||
function f() {
|
||||
{
|
||||
@ -306,7 +281,7 @@ function f() {
|
||||
}
|
||||
`);
|
||||
|
||||
// TOK_FUNCTION
|
||||
// function (hosted)
|
||||
testPass(`
|
||||
function f() {
|
||||
g();
|
||||
@ -315,16 +290,16 @@ function f() {
|
||||
}
|
||||
`);
|
||||
|
||||
// TOK_IF
|
||||
testPass(`
|
||||
// if
|
||||
testWarn(`
|
||||
function f() {
|
||||
return
|
||||
if (true)
|
||||
1 + 2;
|
||||
}
|
||||
`);
|
||||
`, 4, 2);
|
||||
|
||||
// TOK_ELSE
|
||||
// else
|
||||
testPass(`
|
||||
function f() {
|
||||
if (true)
|
||||
@ -334,8 +309,8 @@ function f() {
|
||||
}
|
||||
`);
|
||||
|
||||
// TOK_SWITCH
|
||||
testPass(`
|
||||
// switch
|
||||
testWarn(`
|
||||
function f() {
|
||||
return
|
||||
switch (1) {
|
||||
@ -343,9 +318,32 @@ function f() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
`, 4, 2);
|
||||
|
||||
// return in switch
|
||||
testWarn(`
|
||||
function f() {
|
||||
switch (1) {
|
||||
case 1:
|
||||
return;
|
||||
1 + 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
`, 6, 6);
|
||||
|
||||
// break in switch
|
||||
testPass(`
|
||||
function f() {
|
||||
switch (1) {
|
||||
case 1:
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
// TOK_CASE
|
||||
// case
|
||||
testPass(`
|
||||
function f() {
|
||||
switch (1) {
|
||||
@ -357,7 +355,7 @@ function f() {
|
||||
}
|
||||
`);
|
||||
|
||||
// TOK_DEFAULT
|
||||
// default
|
||||
testPass(`
|
||||
function f() {
|
||||
switch (1) {
|
||||
@ -369,14 +367,14 @@ function f() {
|
||||
}
|
||||
`);
|
||||
|
||||
// TOK_WHILE
|
||||
testPass(`
|
||||
// while
|
||||
testWarn(`
|
||||
function f() {
|
||||
return
|
||||
while (false)
|
||||
1 + 2;
|
||||
}
|
||||
`);
|
||||
`, 4, 2);
|
||||
testPass(`
|
||||
function f() {
|
||||
do
|
||||
@ -385,27 +383,27 @@ function f() {
|
||||
}
|
||||
`);
|
||||
|
||||
// TOK_DO
|
||||
testPass(`
|
||||
// do
|
||||
testWarn(`
|
||||
function f() {
|
||||
return
|
||||
do {
|
||||
1 + 2;
|
||||
} while (false);
|
||||
}
|
||||
`);
|
||||
`, 4, 2);
|
||||
|
||||
// TOK_FOR
|
||||
testPass(`
|
||||
// for
|
||||
testWarn(`
|
||||
function f() {
|
||||
return
|
||||
for (;;) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
`);
|
||||
`, 4, 2);
|
||||
|
||||
// TOK_BREAK
|
||||
// break in for
|
||||
testPass(`
|
||||
function f() {
|
||||
for (;;) {
|
||||
@ -413,19 +411,19 @@ function f() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
`);
|
||||
`, 5, 4);
|
||||
|
||||
// TOK_CONTINUE
|
||||
testPass(`
|
||||
// continue
|
||||
testWarn(`
|
||||
function f() {
|
||||
for (;;) {
|
||||
return
|
||||
continue;
|
||||
}
|
||||
}
|
||||
`);
|
||||
`, 5, 4);
|
||||
|
||||
// TOK_VAR
|
||||
// var (hosted)
|
||||
testPass(`
|
||||
function f() {
|
||||
return
|
||||
@ -433,43 +431,43 @@ function f() {
|
||||
}
|
||||
`);
|
||||
|
||||
// TOK_CONST
|
||||
testPass(`
|
||||
// const
|
||||
testWarn(`
|
||||
function f() {
|
||||
return
|
||||
const a = 1;
|
||||
}
|
||||
`);
|
||||
`, 4, 2);
|
||||
|
||||
// TOK_WITH
|
||||
testPass(`
|
||||
// with
|
||||
testWarn(`
|
||||
function f() {
|
||||
return
|
||||
with ({}) {
|
||||
1;
|
||||
}
|
||||
}
|
||||
`);
|
||||
`, 4, 2);
|
||||
|
||||
// TOK_RETURN
|
||||
testPass(`
|
||||
// return
|
||||
testWarn(`
|
||||
function f() {
|
||||
return
|
||||
return;
|
||||
}
|
||||
`);
|
||||
`, 4, 2);
|
||||
|
||||
// TOK_TRY
|
||||
testPass(`
|
||||
// try
|
||||
testWarn(`
|
||||
function f() {
|
||||
return
|
||||
try {
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
`);
|
||||
`, 4, 2);
|
||||
|
||||
// TOK_THROW
|
||||
// throw
|
||||
testPass(`
|
||||
function f() {
|
||||
return
|
||||
@ -477,29 +475,37 @@ function f() {
|
||||
}
|
||||
`);
|
||||
|
||||
// TOK_DEBUGGER
|
||||
testPass(`
|
||||
// debugger
|
||||
testWarn(`
|
||||
function f() {
|
||||
return
|
||||
debugger;
|
||||
}
|
||||
`);
|
||||
`, 4, 2);
|
||||
|
||||
// TOK_LET
|
||||
testPass(`
|
||||
// let
|
||||
testWarn(`
|
||||
function f() {
|
||||
return
|
||||
let a = 1;
|
||||
}
|
||||
`);
|
||||
`, 4, 2);
|
||||
|
||||
// exceptional case
|
||||
// skip hoisted
|
||||
|
||||
// It's not possible to distinguish between a label statement and an expression
|
||||
// starts with identifier, by checking a token next to return.
|
||||
testWarn(`
|
||||
function f() {
|
||||
return
|
||||
a: 1;
|
||||
var a = 0;
|
||||
(1 + 2);
|
||||
}
|
||||
`, 4, 2);
|
||||
`, 5, 2);
|
||||
|
||||
testWarn(`
|
||||
function f() {
|
||||
return
|
||||
function f() {}
|
||||
var a = 0;
|
||||
(1 + 2);
|
||||
}
|
||||
`, 6, 2);
|
21
js/src/jit-test/tests/debug/Environment-gc-03.js
Normal file
21
js/src/jit-test/tests/debug/Environment-gc-03.js
Normal file
@ -0,0 +1,21 @@
|
||||
// Test that block scopes cannot be resurrected by onStep.
|
||||
|
||||
var g = newGlobal();
|
||||
var dbg = new Debugger(g);
|
||||
dbg.onDebuggerStatement = function(frame) {
|
||||
frame.onStep = (function() {
|
||||
frame.environment;
|
||||
});
|
||||
};
|
||||
|
||||
g.eval("debugger; for (let i = 0; i < 1; i++) (function(){});");
|
||||
|
||||
// If the last freshened block scope was incorrectly resurrected by onStep
|
||||
// above, GCing will assert.
|
||||
gc();
|
||||
|
||||
g.eval("debugger; { let i = 0; (function(){ i = 42; }); }");
|
||||
gc();
|
||||
|
||||
g.eval("debugger; try { throw 42; } catch (e) { };");
|
||||
gc();
|
14
js/src/jit-test/tests/debug/bug1148917.js
Normal file
14
js/src/jit-test/tests/debug/bug1148917.js
Normal file
@ -0,0 +1,14 @@
|
||||
// |jit-test| error: Error
|
||||
|
||||
var g = newGlobal();
|
||||
g.eval('function f(a) { evaluate("f(" + " - 1);", {newContext: true}); }');
|
||||
var dbg = new Debugger(g);
|
||||
var frames = [];
|
||||
dbg.onEnterFrame = function (frame) {
|
||||
if (frames.length == 3)
|
||||
return;
|
||||
frames.push(frame);
|
||||
for (var f of frames)
|
||||
f.eval('a').return
|
||||
};
|
||||
g.f();
|
@ -2,7 +2,7 @@ var g = newGlobal();
|
||||
var dbg = new Debugger(g);
|
||||
|
||||
try {
|
||||
g.eval("function f() { var array = ['a', 'b']; [1].map(function () {}); return {array}; }");
|
||||
g.eval("function f() { [1].map(function () {}); const x = 42; x = 43; } f();");
|
||||
} catch (e) {
|
||||
// Ignore the syntax error.
|
||||
}
|
||||
|
7
js/src/jit-test/tests/ion/lexical-check-5.js
Normal file
7
js/src/jit-test/tests/ion/lexical-check-5.js
Normal file
@ -0,0 +1,7 @@
|
||||
// |jit-test| error: ReferenceError
|
||||
|
||||
{
|
||||
for (var i = 0; i < 100; i++)
|
||||
a += i;
|
||||
let a = 1;
|
||||
}
|
@ -3010,14 +3010,24 @@ BaselineCompiler::emit_JSOP_PUSHBLOCKSCOPE()
|
||||
typedef bool (*PopBlockScopeFn)(JSContext*, BaselineFrame*);
|
||||
static const VMFunction PopBlockScopeInfo = FunctionInfo<PopBlockScopeFn>(jit::PopBlockScope);
|
||||
|
||||
typedef bool (*DebugLeaveThenPopBlockScopeFn)(JSContext*, BaselineFrame*, jsbytecode*);
|
||||
static const VMFunction DebugLeaveThenPopBlockScopeInfo =
|
||||
FunctionInfo<DebugLeaveThenPopBlockScopeFn>(jit::DebugLeaveThenPopBlockScope);
|
||||
|
||||
bool
|
||||
BaselineCompiler::emit_JSOP_POPBLOCKSCOPE()
|
||||
{
|
||||
prepareVMCall();
|
||||
|
||||
masm.loadBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
|
||||
pushArg(R0.scratchReg());
|
||||
|
||||
if (compileDebugInstrumentation_) {
|
||||
pushArg(ImmPtr(pc));
|
||||
pushArg(R0.scratchReg());
|
||||
return callVM(DebugLeaveThenPopBlockScopeInfo);
|
||||
}
|
||||
|
||||
pushArg(R0.scratchReg());
|
||||
return callVM(PopBlockScopeInfo);
|
||||
}
|
||||
|
||||
@ -3025,7 +3035,7 @@ typedef bool (*FreshenBlockScopeFn)(JSContext*, BaselineFrame*);
|
||||
static const VMFunction FreshenBlockScopeInfo =
|
||||
FunctionInfo<FreshenBlockScopeFn>(jit::FreshenBlockScope);
|
||||
|
||||
typedef bool (*DebugLeaveThenFreshenBlockScopeFn)(JSContext*, BaselineFrame*, jsbytecode* pc);
|
||||
typedef bool (*DebugLeaveThenFreshenBlockScopeFn)(JSContext*, BaselineFrame*, jsbytecode*);
|
||||
static const VMFunction DebugLeaveThenFreshenBlockScopeInfo =
|
||||
FunctionInfo<DebugLeaveThenFreshenBlockScopeFn>(jit::DebugLeaveThenFreshenBlockScope);
|
||||
|
||||
|
@ -4796,39 +4796,24 @@ CodeGenerator::visitCreateThisWithProto(LCreateThisWithProto* lir)
|
||||
callVM(CreateThisWithProtoInfo, lir);
|
||||
}
|
||||
|
||||
typedef JSObject* (*NewGCObjectFn)(JSContext* cx, gc::AllocKind allocKind,
|
||||
gc::InitialHeap initialHeap, size_t ndynamic,
|
||||
const js::Class* clasp);
|
||||
static const VMFunction NewGCObjectInfo =
|
||||
FunctionInfo<NewGCObjectFn>(js::jit::NewGCObject);
|
||||
|
||||
void
|
||||
CodeGenerator::visitCreateThisWithTemplate(LCreateThisWithTemplate* lir)
|
||||
{
|
||||
JSObject* templateObject = lir->mir()->templateObject();
|
||||
gc::AllocKind allocKind = templateObject->asTenured().getAllocKind();
|
||||
gc::InitialHeap initialHeap = lir->mir()->initialHeap();
|
||||
const js::Class* clasp = templateObject->getClass();
|
||||
size_t ndynamic = 0;
|
||||
if (templateObject->isNative())
|
||||
ndynamic = templateObject->as<NativeObject>().numDynamicSlots();
|
||||
Register objReg = ToRegister(lir->output());
|
||||
Register tempReg = ToRegister(lir->temp());
|
||||
|
||||
OutOfLineCode* ool = oolCallVM(NewGCObjectInfo, lir,
|
||||
(ArgList(), Imm32(int32_t(allocKind)), Imm32(initialHeap),
|
||||
Imm32(ndynamic), ImmPtr(clasp)),
|
||||
OutOfLineCode* ool = oolCallVM(NewInitObjectWithTemplateInfo, lir,
|
||||
(ArgList(), ImmGCPtr(templateObject)),
|
||||
StoreRegisterTo(objReg));
|
||||
|
||||
// Allocate. If the FreeList is empty, call to VM, which may GC.
|
||||
masm.newGCThing(objReg, tempReg, templateObject, lir->mir()->initialHeap(), ool->entry());
|
||||
|
||||
// Initialize based on the templateObject.
|
||||
masm.bind(ool->rejoin());
|
||||
|
||||
bool initContents = !templateObject->is<PlainObject>() ||
|
||||
ShouldInitFixedSlots(lir, &templateObject->as<PlainObject>());
|
||||
masm.initGCThing(objReg, tempReg, templateObject, initContents);
|
||||
ShouldInitFixedSlots(lir, &templateObject->as<PlainObject>());
|
||||
masm.createGCObject(objReg, tempReg, templateObject, lir->mir()->initialHeap(), ool->entry(),
|
||||
initContents);
|
||||
|
||||
masm.bind(ool->rejoin());
|
||||
}
|
||||
|
||||
typedef JSObject* (*NewIonArgumentsObjectFn)(JSContext* cx, JitFrameLayout* frame, HandleObject);
|
||||
|
@ -12908,6 +12908,9 @@ IonBuilder::addLexicalCheck(MDefinition* input)
|
||||
|
||||
// If we're guaranteed to not be JS_UNINITIALIZED_LEXICAL, no need to check.
|
||||
if (input->type() == MIRType_MagicUninitializedLexical) {
|
||||
// Mark the input as implicitly used so the JS_UNINITIALIZED_LEXICAL
|
||||
// magic value will be preserved on bailout.
|
||||
input->setImplicitlyUsedUnchecked();
|
||||
lexicalCheck = MThrowUninitializedLexical::New(alloc());
|
||||
current->add(lexicalCheck);
|
||||
if (!resumeAfter(lexicalCheck))
|
||||
|
@ -1183,19 +1183,6 @@ MacroAssembler::allocateObject(Register result, Register temp, gc::AllocKind all
|
||||
bind(&success);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::newGCThing(Register result, Register temp, JSObject* templateObj,
|
||||
gc::InitialHeap initialHeap, Label* fail)
|
||||
{
|
||||
gc::AllocKind allocKind = templateObj->asTenured().getAllocKind();
|
||||
MOZ_ASSERT(gc::IsObjectAllocKind(allocKind));
|
||||
|
||||
size_t ndynamic = 0;
|
||||
if (templateObj->isNative())
|
||||
ndynamic = templateObj->as<NativeObject>().numDynamicSlots();
|
||||
allocateObject(result, temp, allocKind, ndynamic, initialHeap, fail);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::createGCObject(Register obj, Register temp, JSObject* templateObj,
|
||||
gc::InitialHeap initialHeap, Label* fail, bool initContents,
|
||||
|
@ -802,8 +802,6 @@ class MacroAssembler : public MacroAssemblerSpecific
|
||||
gc::InitialHeap initialHeap, Label* fail, bool initContents = true,
|
||||
bool convertDoubleElements = false);
|
||||
|
||||
void newGCThing(Register result, Register temp, JSObject* templateObj,
|
||||
gc::InitialHeap initialHeap, Label* fail);
|
||||
void initGCThing(Register obj, Register temp, JSObject* templateObj,
|
||||
bool initContents = true, bool convertDoubleElements = false);
|
||||
|
||||
|
@ -86,18 +86,6 @@ InvokeFunction(JSContext* cx, HandleObject obj, uint32_t argc, Value* argv, Valu
|
||||
return true;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
NewGCObject(JSContext* cx, gc::AllocKind allocKind, gc::InitialHeap initialHeap,
|
||||
size_t ndynamic, const js::Class* clasp)
|
||||
{
|
||||
JSObject* obj = js::Allocate<JSObject>(cx, allocKind, ndynamic, initialHeap, clasp);
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
SetNewObjectMetadata(cx, obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
bool
|
||||
CheckOverRecursed(JSContext* cx)
|
||||
{
|
||||
@ -996,6 +984,14 @@ PopBlockScope(JSContext* cx, BaselineFrame* frame)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
DebugLeaveThenPopBlockScope(JSContext* cx, BaselineFrame* frame, jsbytecode* pc)
|
||||
{
|
||||
MOZ_ALWAYS_TRUE(DebugLeaveBlock(cx, frame, pc));
|
||||
frame->popBlock(cx);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
FreshenBlockScope(JSContext* cx, BaselineFrame* frame)
|
||||
{
|
||||
@ -1005,7 +1001,7 @@ FreshenBlockScope(JSContext* cx, BaselineFrame* frame)
|
||||
bool
|
||||
DebugLeaveThenFreshenBlockScope(JSContext* cx, BaselineFrame* frame, jsbytecode* pc)
|
||||
{
|
||||
DebugLeaveBlock(cx, frame, pc);
|
||||
MOZ_ALWAYS_TRUE(DebugLeaveBlock(cx, frame, pc));
|
||||
return frame->freshenBlock(cx);
|
||||
}
|
||||
|
||||
|
@ -632,8 +632,6 @@ class AutoDetectInvalidation
|
||||
};
|
||||
|
||||
bool InvokeFunction(JSContext* cx, HandleObject obj0, uint32_t argc, Value* argv, Value* rval);
|
||||
JSObject* NewGCObject(JSContext* cx, gc::AllocKind allocKind, gc::InitialHeap initialHeap,
|
||||
size_t ndynamic, const js::Class* clasp);
|
||||
|
||||
bool CheckOverRecursed(JSContext* cx);
|
||||
bool CheckOverRecursedWithExtra(JSContext* cx, BaselineFrame* frame,
|
||||
@ -728,6 +726,7 @@ bool LeaveWith(JSContext* cx, BaselineFrame* frame);
|
||||
|
||||
bool PushBlockScope(JSContext* cx, BaselineFrame* frame, Handle<StaticBlockObject*> block);
|
||||
bool PopBlockScope(JSContext* cx, BaselineFrame* frame);
|
||||
bool DebugLeaveThenPopBlockScope(JSContext* cx, BaselineFrame* frame, jsbytecode* pc);
|
||||
bool FreshenBlockScope(JSContext* cx, BaselineFrame* frame);
|
||||
bool DebugLeaveThenFreshenBlockScope(JSContext* cx, BaselineFrame* frame, jsbytecode* pc);
|
||||
bool DebugLeaveBlock(JSContext* cx, BaselineFrame* frame, jsbytecode* pc);
|
||||
|
@ -304,12 +304,12 @@ MSG_DEF(JSMSG_SEMI_AFTER_FOR_COND, 0, JSEXN_SYNTAXERR, "missing ; after for-
|
||||
MSG_DEF(JSMSG_SEMI_AFTER_FOR_INIT, 0, JSEXN_SYNTAXERR, "missing ; after for-loop initializer")
|
||||
MSG_DEF(JSMSG_SEMI_BEFORE_STMNT, 0, JSEXN_SYNTAXERR, "missing ; before statement")
|
||||
MSG_DEF(JSMSG_SOURCE_TOO_LONG, 0, JSEXN_RANGEERR, "source is too long")
|
||||
MSG_DEF(JSMSG_STMT_AFTER_SEMI_LESS, 0, JSEXN_SYNTAXERR, "unreachable expression after semicolon-less return statement")
|
||||
MSG_DEF(JSMSG_STMT_AFTER_RETURN, 0, JSEXN_SYNTAXERR, "unreachable code after return statement")
|
||||
MSG_DEF(JSMSG_STRICT_CODE_LET_EXPR_STMT, 0, JSEXN_ERR, "strict mode code may not contain unparenthesized let expression statements")
|
||||
MSG_DEF(JSMSG_STRICT_CODE_WITH, 0, JSEXN_SYNTAXERR, "strict mode code may not contain 'with' statements")
|
||||
MSG_DEF(JSMSG_STRICT_FUNCTION_STATEMENT, 0, JSEXN_SYNTAXERR, "in strict mode code, functions may be declared only at top level or immediately within another function")
|
||||
MSG_DEF(JSMSG_TEMPLSTR_UNTERM_EXPR, 0, JSEXN_SYNTAXERR, "missing } in template string")
|
||||
MSG_DEF(JSMSG_SIMD_NOT_A_VECTOR, 0, JSEXN_TYPEERR, "value isn't a SIMD value object")
|
||||
MSG_DEF(JSMSG_SIMD_NOT_A_VECTOR, 2, JSEXN_TYPEERR, "expecting a SIMD {0} object as argument {1}")
|
||||
MSG_DEF(JSMSG_TOO_MANY_CASES, 0, JSEXN_INTERNALERR, "too many switch cases")
|
||||
MSG_DEF(JSMSG_TOO_MANY_CATCH_VARS, 0, JSEXN_SYNTAXERR, "too many catch variables")
|
||||
MSG_DEF(JSMSG_TOO_MANY_CON_ARGS, 0, JSEXN_SYNTAXERR, "too many constructor arguments")
|
||||
|
@ -758,16 +758,25 @@ CreateLazyScriptsForCompartment(JSContext* cx)
|
||||
// clones. See bug 1105306.
|
||||
for (gc::ZoneCellIter i(cx->zone(), JSFunction::FinalizeKind); !i.done(); i.next()) {
|
||||
JSObject* obj = i.get<JSObject>();
|
||||
if (obj->compartment() == cx->compartment() && obj->is<JSFunction>()) {
|
||||
JSFunction* fun = &obj->as<JSFunction>();
|
||||
if (fun->isInterpretedLazy()) {
|
||||
LazyScript* lazy = fun->lazyScriptOrNull();
|
||||
if (lazy && lazy->sourceObject() && !lazy->maybeScript() &&
|
||||
!lazy->hasUncompiledEnclosingScript())
|
||||
{
|
||||
if (!lazyFunctions.append(fun))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Sweeping is incremental; take care to not delazify functions that
|
||||
// are about to be finalized. GC things referenced by objects that are
|
||||
// about to be finalized (e.g., in slots) may already be freed.
|
||||
if (gc::IsAboutToBeFinalizedUnbarriered(&obj) ||
|
||||
obj->compartment() != cx->compartment() ||
|
||||
!obj->is<JSFunction>())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
JSFunction* fun = &obj->as<JSFunction>();
|
||||
if (fun->isInterpretedLazy()) {
|
||||
LazyScript* lazy = fun->lazyScriptOrNull();
|
||||
if (lazy && lazy->sourceObject() && !lazy->maybeScript() &&
|
||||
!lazy->hasUncompiledEnclosingScript())
|
||||
{
|
||||
if (!lazyFunctions.append(fun))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -342,9 +342,16 @@ class JSFunction : public js::NativeObject
|
||||
return nonLazyScript();
|
||||
}
|
||||
|
||||
JSScript* nonLazyScript() const {
|
||||
// The state of a JSFunction whose script errored out during bytecode
|
||||
// compilation. Such JSFunctions are only reachable via GC iteration and
|
||||
// not from script.
|
||||
bool hasUncompiledScript() const {
|
||||
MOZ_ASSERT(hasScript());
|
||||
MOZ_ASSERT(u.i.s.script_);
|
||||
return !u.i.s.script_;
|
||||
}
|
||||
|
||||
JSScript* nonLazyScript() const {
|
||||
MOZ_ASSERT(!hasUncompiledScript());
|
||||
return u.i.s.script_;
|
||||
}
|
||||
|
||||
|
@ -3911,7 +3911,7 @@ LazyScript::hasUncompiledEnclosingScript() const
|
||||
return false;
|
||||
|
||||
JSFunction& fun = enclosingScope()->as<JSFunction>();
|
||||
return fun.isInterpreted() && (!fun.hasScript() || !fun.nonLazyScript()->code());
|
||||
return !fun.hasScript() || fun.hasUncompiledScript() || !fun.nonLazyScript()->code();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
|
@ -1,4 +1,4 @@
|
||||
// |reftest| skip-if(xulRuntime.OS=="Darwin"&&isDebugBuild) -- this takes too long to over-recurse.
|
||||
// |reftest| skip-if((xulRuntime.OS=="Darwin"||Android)&&isDebugBuild) -- this takes too long to over-recurse.
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user