This commit is contained in:
Ryan VanderMeulen 2013-11-19 13:36:41 -05:00
Родитель 6eb7c563bb fd6e2f3e22
Коммит d54f78e830
27 изменённых файлов: 1186 добавлений и 1581 удалений

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

@ -191,21 +191,22 @@ let PaymentProvider = {
},
#ifdef MOZ_B2G_RIL
// Until bug 814629 is done, we only have support for a single SIM, so we
// can only provide information for a single ICC. However, we return an array
// so the payment provider facing API won't need to change once we support
// multiple SIMs.
// Bug 938993. Support Multi-SIM for Payments.
get iccInfo() {
delete this.iccInfo;
return this.iccInfo = iccProvider.getIccInfo(0);
},
get iccIds() {
return [iccProvider.iccInfo.iccid];
return [this.iccInfo.iccid];
},
get mcc() {
return [iccProvider.iccInfo.mcc];
return [this.iccInfo.mcc];
},
get mnc() {
return [iccProvider.iccInfo.mnc];
return [this.iccInfo.mnc];
},
_silentNumbers: null,

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

@ -1,4 +1,4 @@
{
"revision": "8ef103bc368f8309e42cffb648fa73ab756b2599",
"revision": "4e8959a60a4ee1373e71fe31229ba5bd7575c02c",
"repo_path": "/integration/gaia-central"
}

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

@ -961,7 +961,7 @@ MediaDecoder::GetStatistics()
double MediaDecoder::ComputePlaybackRate(bool* aReliable)
{
GetReentrantMonitor().AssertCurrentThreadIn();
MOZ_ASSERT(NS_IsMainThread() || OnStateMachineThread());
MOZ_ASSERT(NS_IsMainThread() || OnStateMachineThread() || OnDecodeThread());
int64_t length = mResource ? mResource->GetLength() : -1;
if (mDuration >= 0 && length >= 0) {

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

@ -1829,52 +1829,44 @@ bool MediaDecoderStateMachine::HasLowDecodedData(int64_t aAudioUsecs) const
AssertCurrentThreadInMonitor();
// We consider ourselves low on decoded data if we're low on audio,
// provided we've not decoded to the end of the audio stream, or
// if we're only playing video and we're low on video frames, provided
// if we're low on video frames, provided
// we've not decoded to the end of the video stream.
return ((HasAudio() &&
!mReader->AudioQueue().IsFinished() &&
AudioDecodedUsecs() < aAudioUsecs)
||
(!HasAudio() &&
HasVideo() &&
(HasVideo() &&
!mReader->VideoQueue().IsFinished() &&
static_cast<uint32_t>(mReader->VideoQueue().GetSize()) < LOW_VIDEO_FRAMES));
}
bool MediaDecoderStateMachine::HasLowUndecodedData() const
{
return GetUndecodedData() < mLowDataThresholdUsecs;
return HasLowUndecodedData(mLowDataThresholdUsecs);
}
int64_t MediaDecoderStateMachine::GetUndecodedData() const
bool MediaDecoderStateMachine::HasLowUndecodedData(double aUsecs) const
{
AssertCurrentThreadInMonitor();
NS_ASSERTION(mState > DECODER_STATE_DECODING_METADATA,
"Must have loaded metadata for GetBuffered() to work");
TimeRanges buffered;
nsresult res = mDecoder->GetBuffered(&buffered);
NS_ENSURE_SUCCESS(res, 0);
double currentTime = GetCurrentTime();
nsIDOMTimeRanges* r = static_cast<nsIDOMTimeRanges*>(&buffered);
uint32_t length = 0;
res = r->GetLength(&length);
NS_ENSURE_SUCCESS(res, 0);
for (uint32_t index = 0; index < length; ++index) {
double start, end;
res = r->Start(index, &start);
NS_ENSURE_SUCCESS(res, 0);
res = r->End(index, &end);
NS_ENSURE_SUCCESS(res, 0);
if (start <= currentTime && end >= currentTime) {
return static_cast<int64_t>((end - currentTime) * USECS_PER_S);
}
bool reliable;
double bytesPerSecond = mDecoder->ComputePlaybackRate(&reliable);
if (!reliable) {
// Default to assuming we have enough
return false;
}
return 0;
MediaResource* stream = mDecoder->GetResource();
int64_t currentPos = stream->Tell();
int64_t requiredPos = currentPos + int64_t((aUsecs/1000000.0)*bytesPerSecond);
int64_t length = stream->GetLength();
if (length >= 0) {
requiredPos = std::min(requiredPos, length);
}
return stream->GetCachedDataEnd(currentPos) < requiredPos;
}
void MediaDecoderStateMachine::SetFrameBufferLength(uint32_t aLength)
@ -2282,14 +2274,13 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
if ((isLiveStream || !mDecoder->CanPlayThrough()) &&
elapsed < TimeDuration::FromSeconds(mBufferingWait * mPlaybackRate) &&
(mQuickBuffering ? HasLowDecodedData(QUICK_BUFFERING_LOW_DATA_USECS)
: (GetUndecodedData() < mBufferingWait * mPlaybackRate * USECS_PER_S)) &&
: HasLowUndecodedData(mBufferingWait * USECS_PER_S)) &&
!mDecoder->IsDataCachedToEndOfResource() &&
!resource->IsSuspended())
{
LOG(PR_LOG_DEBUG,
("%p Buffering: %.3lfs/%ds, timeout in %.3lfs %s",
("%p Buffering: wait %ds, timeout in %.3lfs %s",
mDecoder.get(),
GetUndecodedData() / static_cast<double>(USECS_PER_S),
mBufferingWait,
mBufferingWait - elapsed.ToSeconds(),
(mQuickBuffering ? "(quick exit)" : "")));
@ -2528,15 +2519,15 @@ void MediaDecoderStateMachine::AdvanceFrame()
mDecoder->GetState() == MediaDecoder::PLAY_STATE_PLAYING &&
HasLowDecodedData(remainingTime + EXHAUSTED_DATA_MARGIN_USECS) &&
!mDecoder->IsDataCachedToEndOfResource() &&
!resource->IsSuspended() &&
(JustExitedQuickBuffering() || HasLowUndecodedData()))
{
if (currentFrame) {
mReader->VideoQueue().PushFront(currentFrame.forget());
!resource->IsSuspended()) {
if (JustExitedQuickBuffering() || HasLowUndecodedData()) {
if (currentFrame) {
mReader->VideoQueue().PushFront(currentFrame.forget());
}
StartBuffering();
ScheduleStateMachine();
return;
}
StartBuffering();
ScheduleStateMachine();
return;
}
// We've got enough data to keep playing until at least the next frame.

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

@ -394,9 +394,8 @@ private:
// The decoder monitor must be held.
bool HasLowUndecodedData() const;
// Returns the number of microseconds of undecoded data available for
// decoding. The decoder monitor must be held.
int64_t GetUndecodedData() const;
// Returns true if we have less than aUsecs of undecoded data available.
bool HasLowUndecodedData(double aUsecs) const;
// Returns the number of unplayed usecs of audio we've got decoded and/or
// pushed to the hardware waiting to play. This is how much audio we can

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

@ -82,7 +82,6 @@ public:
v.get_ArrayOfBluetoothNamedValue();
nsTArray<nsRefPtr<BluetoothDevice> > devices;
JSObject* JsDevices;
for (uint32_t i = 0; i < values.Length(); i++) {
const BluetoothValue properties = values[i].value();
if (properties.type() != BluetoothValue::TArrayOfBluetoothNamedValue) {
@ -106,6 +105,7 @@ public:
}
AutoPushJSContext cx(sc->GetNativeContext());
JSObject* JsDevices = nullptr;
rv = nsTArrayToJSArray(cx, devices, &JsDevices);
if (!JsDevices) {
BT_WARNING("Cannot create JS array!");

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -7,11 +7,12 @@
#ifndef mozilla_dom_bluetooth_bluetoothhfpmanager_h__
#define mozilla_dom_bluetooth_bluetoothhfpmanager_h__
#include <hardware/bluetooth.h>
#include <hardware/bt_hf.h>
#include "BluetoothCommon.h"
#include "BluetoothProfileManagerBase.h"
#ifdef MOZ_B2G_RIL
#include "BluetoothRilListener.h"
#endif
#include "BluetoothSocketObserver.h"
#include "mozilla/ipc/UnixSocket.h"
#include "mozilla/Hal.h"
@ -20,8 +21,6 @@ BEGIN_BLUETOOTH_NAMESPACE
class BluetoothReplyRunnable;
class BluetoothSocket;
#ifdef MOZ_B2G_RIL
class Call;
/**
@ -67,14 +66,12 @@ public:
bool IsActive();
uint16_t mState;
bool mDirection; // true: incoming call; false: outgoing call
nsString mNumber;
int mType;
bthf_call_direction_t mDirection; // 0: outgoing call; 1: incoming call
bthf_call_addrtype_t mType;
};
#endif // MOZ_B2G_RIL
class BluetoothHfpManager : public BluetoothSocketObserver
, public BluetoothProfileManagerBase
class BluetoothHfpManager : public BluetoothProfileManagerBase
, public BatteryObserver
{
public:
@ -89,21 +86,10 @@ public:
static BluetoothHfpManager* Get();
~BluetoothHfpManager();
// The following functions are inherited from BluetoothSocketObserver
virtual void ReceiveSocketData(
BluetoothSocket* aSocket,
nsAutoPtr<mozilla::ipc::UnixSocketRawData>& aMessage) MOZ_OVERRIDE;
virtual void OnSocketConnectSuccess(BluetoothSocket* aSocket) MOZ_OVERRIDE;
virtual void OnSocketConnectError(BluetoothSocket* aSocket) MOZ_OVERRIDE;
virtual void OnSocketDisconnect(BluetoothSocket* aSocket) MOZ_OVERRIDE;
bool Listen();
bool ConnectSco(BluetoothReplyRunnable* aRunnable = nullptr);
bool ConnectSco();
bool DisconnectSco();
bool ListenSco();
bool IsScoConnected();
#ifdef MOZ_B2G_RIL
/**
* @param aSend A boolean indicates whether we need to notify headset or not
*/
@ -113,106 +99,89 @@ public:
void HandleIccInfoChanged();
void HandleVoiceConnectionChanged();
// Bluedroid hfp callback handlers
void ProcessConnectionState(bthf_connection_state_t aState, bt_bdaddr_t* aBdAddress);
void ProcessAudioState(bthf_audio_state_t aState, bt_bdaddr_t* aBdAddress);
void ProcessAnswerCall();
void ProcessHangupCall();
void ProcessVolumeControl(bthf_volume_type_t aType, int aVolume);
void ProcessDialCall(char *aNumber);
void ProcessDtmfCmd(char aDtmf);
void ProcessAtChld(bthf_chld_type_t aChld);
void ProcessAtCnum();
void ProcessAtCind();
void ProcessAtCops();
void ProcessAtClcc();
void ProcessUnknownAt(char *aAtString);
// CDMA-specific functions
void UpdateSecondNumber(const nsAString& aNumber);
void AnswerWaitingCall();
void IgnoreWaitingCall();
void ToggleCalls();
#endif
private:
class CloseScoTask;
class GetVolumeTask;
#ifdef MOZ_B2G_RIL
class CloseScoTask;
class RespondToBLDNTask;
class SendRingIndicatorTask;
#endif
class MainThreadTask;
friend class CloseScoTask;
friend class GetVolumeTask;
#ifdef MOZ_B2G_RIL
friend class RespondToBLDNTask;
friend class SendRingIndicatorTask;
#endif
friend class BluetoothHfpManagerObserver;
friend class GetVolumeTask;
friend class CloseScoTask;
friend class RespondToBLDNTask;
friend class MainThreadTask;
BluetoothHfpManager();
bool Init();
bool InitHfpInterface();
void DeinitHfpInterface();
void Reset();
void HandleShutdown();
void HandleVolumeChanged(const nsAString& aData);
bool Init();
void Notify(const hal::BatteryInformation& aBatteryInfo);
void Reset();
#ifdef MOZ_B2G_RIL
void NotifyConnectionStateChanged(const nsAString& aType);
void NotifyDialer(const nsAString& aCommand);
PhoneType GetPhoneType(const nsAString& aType);
void ResetCallArray();
uint32_t FindFirstCall(uint16_t aState);
uint32_t GetNumberOfCalls(uint16_t aState);
PhoneType GetPhoneType(const nsAString& aType);
#endif
bthf_call_state_t ConvertToBthfCallState(int aCallState);
void NotifyConnectionStatusChanged(const nsAString& aType);
void NotifyDialer(const nsAString& aCommand);
void UpdatePhoneCIND(uint32_t aCallIndex, bool aSend = true);
void UpdateDeviceCIND();
void SendCLCC(Call& aCall, int aIndex);
void SendLine(const char* aMessage);
void SendResponse(bthf_at_response_t aResponseCode);
#ifdef MOZ_B2G_RIL
void SendCCWA(const nsAString& aNumber, int aType);
bool SendCLCC(const Call& aCall, int aIndex);
#endif
bool SendCommand(const char* aCommand, uint32_t aValue = 0);
bool SendLine(const char* aMessage);
#ifdef MOZ_B2G_RIL
void UpdateCIND(uint8_t aType, uint8_t aValue, bool aSend = true);
#endif
void OnScoConnectSuccess();
void OnScoConnectError();
void OnScoDisconnect();
int mConnectionState;
int mAudioState;
// Phone CIND
int mCallSetupState;
// Device CIND
int mBattChg;
int mService;
int mRoam;
int mSignal;
int mCurrentVgs;
int mCurrentVgm;
#ifdef MOZ_B2G_RIL
bool mBSIR;
bool mCCWA;
bool mCLIP;
#endif
bool mCMEE;
bool mCMER;
#ifdef MOZ_B2G_RIL
bool mFirstCKPD;
int mNetworkSelectionMode;
PhoneType mPhoneType;
#endif
bool mReceiveVgsFlag;
#ifdef MOZ_B2G_RIL
bool mDialingRequestProcessed;
#endif
PhoneType mPhoneType;
nsString mDeviceAddress;
#ifdef MOZ_B2G_RIL
nsString mMsisdn;
nsString mOperatorName;
nsTArray<Call> mCurrentCallArray;
nsAutoPtr<BluetoothRilListener> mListener;
#endif
nsRefPtr<BluetoothProfileController> mController;
nsRefPtr<BluetoothReplyRunnable> mScoRunnable;
// If a connection has been established, mSocket will be the socket
// communicating with the remote socket. We maintain the invariant that if
// mSocket is non-null, mHandsfreeSocket and mHeadsetSocket must be null (and
// vice versa).
nsRefPtr<BluetoothSocket> mSocket;
// Server sockets. Once an inbound connection is established, it will hand
// over the ownership to mSocket, and get a new server socket while Listen()
// is called.
nsRefPtr<BluetoothSocket> mHandsfreeSocket;
nsRefPtr<BluetoothSocket> mHeadsetSocket;
nsRefPtr<BluetoothSocket> mScoSocket;
SocketConnectionStatus mScoSocketStatus;
#ifdef MOZ_B2G_RIL
// CDMA-specific variable
Call mCdmaSecondCall;
#endif
};
END_BLUETOOTH_NAMESPACE

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

@ -18,7 +18,6 @@
#include "BluetoothServiceBluedroid.h"
#include <hardware/bluetooth.h>
#include <hardware/hardware.h>
#include "BluetoothProfileController.h"
@ -32,8 +31,6 @@ using namespace mozilla;
using namespace mozilla::ipc;
USING_BLUETOOTH_NAMESPACE
typedef char bdstr_t[18];
/**
* Classes only used in this file
*/
@ -159,39 +156,31 @@ ClassToIcon(uint32_t aClass, nsAString& aRetIcon)
}
}
static void
AdapterStateChangeCallback(bt_state_t aStatus)
static bool
IsReady()
{
MOZ_ASSERT(!NS_IsMainThread());
BT_LOGD("%s, BT_STATE:%d", __FUNCTION__, aStatus);
nsAutoString signalName;
if (aStatus == BT_STATE_ON) {
sIsBtEnabled = true;
signalName = NS_LITERAL_STRING("AdapterAdded");
// by default bluetooth scan mode is NONE
bt_property_t prop;
prop.type = BT_PROPERTY_ADAPTER_SCAN_MODE;
bt_scan_mode_t mode = BT_SCAN_MODE_CONNECTABLE;
prop.val = (void*) &mode;
prop.len = sizeof(mode);
if (sBtInterface) {
int ret = sBtInterface->set_adapter_property(&prop);
if (ret != BT_STATUS_SUCCESS) {
BT_LOGR("Warning! Fail to set property to BT_SCAN_MODE_CONNECTABLE");
}
}
} else {
sIsBtEnabled = false;
signalName = NS_LITERAL_STRING("Disabled");
if (!sBtInterface || !sIsBtEnabled) {
BT_LOGR("Warning! Bluetooth Service is not ready");
return false;
}
return true;
}
BluetoothSignal signal(signalName, NS_LITERAL_STRING(KEY_MANAGER),
BluetoothValue(true));
nsRefPtr<DistributeBluetoothSignalTask>
t = new DistributeBluetoothSignalTask(signal);
if (NS_FAILED(NS_DispatchToMainThread(t))) {
NS_WARNING("Failed to dispatch to main thread!");
const bt_interface_t*
GetBluetoothInterface()
{
return (IsReady()) ? sBtInterface : nullptr;
}
void
StringToBdAddressType(const nsAString& aBdAddress,
bt_bdaddr_t *aRetBdAddressType)
{
const char* str = NS_ConvertUTF16toUTF8(aBdAddress).get();
for (int i = 0; i < 6; i++) {
aRetBdAddressType->address[i] = (uint8_t) strtoul(str, (char **)&str, 16);
str++;
}
}
@ -208,25 +197,47 @@ BdAddressTypeToString(bt_bdaddr_t* aBdAddressType, nsAString& aRetBdAddress)
aRetBdAddress = NS_ConvertUTF8toUTF16((char*)bdstr);
}
static bool
IsReady()
static void
Setup()
{
if (!sBtInterface || !sIsBtEnabled) {
BT_LOGR("Warning! Bluetooth Service is not ready");
return false;
// Bluetooth scan mode is NONE by default
bt_scan_mode_t mode = BT_SCAN_MODE_CONNECTABLE;
bt_property_t prop;
prop.type = BT_PROPERTY_ADAPTER_SCAN_MODE;
prop.val = (void*)&mode;
prop.len = sizeof(mode);
NS_ENSURE_TRUE_VOID(sBtInterface);
int ret = sBtInterface->set_adapter_property(&prop);
if (ret != BT_STATUS_SUCCESS) {
BT_LOGR("%s: Fail to set: BT_SCAN_MODE_CONNECTABLE", __FUNCTION__);
}
return true;
}
static void
StringToBdAddressType(const nsAString& aBdAddress,
bt_bdaddr_t *aRetBdAddressType)
AdapterStateChangeCallback(bt_state_t aStatus)
{
const char* str = NS_ConvertUTF16toUTF8(aBdAddress).get();
MOZ_ASSERT(!NS_IsMainThread());
for (int i = 0; i < 6; i++) {
aRetBdAddressType->address[i] = (uint8_t) strtoul(str, (char **)&str, 16);
str++;
BT_LOGR("%s, BT_STATE:%d", __FUNCTION__, aStatus);
nsAutoString signalName;
if (aStatus == BT_STATE_ON) {
Setup();
sIsBtEnabled = true;
signalName = NS_LITERAL_STRING("AdapterAdded");
} else {
sIsBtEnabled = false;
signalName = NS_LITERAL_STRING("Disabled");
}
BluetoothSignal signal(signalName, NS_LITERAL_STRING(KEY_MANAGER),
BluetoothValue(true));
nsRefPtr<DistributeBluetoothSignalTask>
t = new DistributeBluetoothSignalTask(signal);
if (NS_FAILED(NS_DispatchToMainThread(t))) {
NS_WARNING("Failed to dispatch to main thread!");
}
}
@ -525,12 +536,13 @@ BondStateChangedCallback(bt_status_t aStatus, bt_bdaddr_t* aRemoteBdAddress,
nsAutoString remoteAddress;
BdAddressTypeToString(aRemoteBdAddress, remoteAddress);
bool bonded;
if (aState == BT_BOND_STATE_BONDING) {
// We don't need to handle bonding state
return;
} else if (aState == BT_BOND_STATE_NONE) {
// We don't need to handle bonding state
NS_ENSURE_TRUE_VOID(aState != BT_BOND_STATE_BONDING);
NS_ENSURE_FALSE_VOID(aState == BT_BOND_STATE_BONDED &&
sAdapterBondedAddressArray.Contains(remoteAddress));
bool bonded;
if (aState == BT_BOND_STATE_NONE) {
bonded = false;
sAdapterBondedAddressArray.RemoveElement(remoteAddress);
} else if (aState == BT_BOND_STATE_BONDED) {
@ -731,9 +743,21 @@ BluetoothServiceBluedroid::GetDefaultAdapterPathInternal(
nsRefPtr<BluetoothReplyRunnable> runnable(aRunnable);
BluetoothValue v = InfallibleTArray<BluetoothNamedValue>();
v.get_ArrayOfBluetoothNamedValue().AppendElement(
BluetoothNamedValue(NS_LITERAL_STRING("Address"), sAdapterBdAddress));
v.get_ArrayOfBluetoothNamedValue().AppendElement(
BluetoothNamedValue(NS_LITERAL_STRING("Name"), sAdapterBdName));
v.get_ArrayOfBluetoothNamedValue().AppendElement(
BluetoothNamedValue(NS_LITERAL_STRING("Discoverable"),
sAdapterDiscoverable));
v.get_ArrayOfBluetoothNamedValue().AppendElement(
BluetoothNamedValue(NS_LITERAL_STRING("DiscoverableTimeout"),
sAdapterDiscoverableTimeout));
v.get_ArrayOfBluetoothNamedValue().AppendElement(
BluetoothNamedValue(NS_LITERAL_STRING("Devices"),
sAdapterBondedAddressArray));

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

@ -7,9 +7,20 @@
#ifndef mozilla_dom_bluetooth_bluetoothservicebluedroid_h__
#define mozilla_dom_bluetooth_bluetoothservicebluedroid_h__
#include <hardware/bluetooth.h>
#include "BluetoothCommon.h"
#include "BluetoothService.h"
typedef char bdstr_t[18];
const bt_interface_t*
GetBluetoothInterface();
void
StringToBdAddressType(const nsAString& aBdAddress,
bt_bdaddr_t *aRetBdAddressType);
class DBusMessage;
BEGIN_BLUETOOTH_NAMESPACE

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

@ -174,6 +174,7 @@ static nsRefPtr<RawDBusConnection> gThreadConnection;
static nsDataHashtable<nsStringHashKey, DBusMessage* >* sPairingReqTable;
static nsTArray<uint32_t> sAuthorizedServiceClass;
static nsString sAdapterPath;
static bool sAdapterNameIsReady = false;
static Atomic<int32_t> sIsPairing(0);
static int sConnectedDeviceCount = 0;
static StaticAutoPtr<Monitor> sStopBluetoothMonitor;
@ -700,6 +701,20 @@ GetProperty(DBusMessageIter aIter, Properties* aPropertyTypes,
nsString& data = propertyValue.get_ArrayOfnsString()[i];
data = GetAddressFromObjectPath(data);
}
} else if (!sAdapterNameIsReady &&
aPropertyTypes == sAdapterProperties &&
propertyName.EqualsLiteral("Name")) {
MOZ_ASSERT(propertyValue.type() == BluetoothValue::TnsString);
// Notify BluetoothManager whenever adapter name is ready.
if (!propertyValue.get_nsString().IsEmpty()) {
sAdapterNameIsReady = true;
BluetoothSignal signal(NS_LITERAL_STRING("AdapterAdded"),
NS_LITERAL_STRING(KEY_MANAGER), sAdapterPath);
nsRefPtr<DistributeBluetoothSignalTask> task =
new DistributeBluetoothSignalTask(signal);
NS_DispatchToMainThread(task);
}
}
aProperties.AppendElement(BluetoothNamedValue(propertyName, propertyValue));
@ -1534,6 +1549,13 @@ EventFilter(DBusConnection* aConn, DBusMessage* aMsg, void* aData)
} else {
v = NS_ConvertUTF8toUTF16(str);
NS_DispatchToMainThread(new PrepareAdapterRunnable(v.get_nsString()));
/**
* The adapter name isn't ready for the time being. Wait for the upcoming
* signal PropertyChanged of adapter name, and then propagate signal
* AdapterAdded to BluetoothManager.
*/
return DBUS_HANDLER_RESULT_HANDLED;
}
} else if (dbus_message_is_signal(aMsg, DBUS_MANAGER_IFACE,
"PropertyChanged")) {
@ -1773,6 +1795,8 @@ BluetoothDBusService::StopInternal()
sAuthorizedServiceClass.Clear();
sControllerArray.Clear();
sAdapterNameIsReady = false;
StopDBus();
return NS_OK;
}

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

@ -10,11 +10,28 @@
USING_INDEXEDDB_NAMESPACE
namespace {
class CleanupFileRunnable MOZ_FINAL : public nsIRunnable
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIRUNNABLE
CleanupFileRunnable(FileManager* aFileManager, int64_t aFileId);
private:
nsRefPtr<FileManager> mFileManager;
int64_t mFileId;
};
} // anonymous namespace
// static
FileInfo*
FileInfo::Create(FileManager* aFileManager, int64_t aId)
{
NS_ASSERTION(aId > 0, "Wrong id!");
MOZ_ASSERT(aId > 0, "Wrong id!");
if (aId <= INT16_MAX) {
return new FileInfo16(aFileManager, aId);
@ -98,16 +115,40 @@ FileInfo::UpdateReferences(mozilla::ThreadSafeAutoRefCnt& aRefCount,
void
FileInfo::Cleanup()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
nsRefPtr<CleanupFileRunnable> cleaner =
new CleanupFileRunnable(mFileManager, Id());
if (quota::QuotaManager::IsShuttingDown()) {
// IndexedDatabaseManager is main-thread only.
if (!NS_IsMainThread()) {
NS_DispatchToMainThread(cleaner);
return;
}
nsRefPtr<IndexedDatabaseManager> mgr = IndexedDatabaseManager::Get();
NS_ASSERTION(mgr, "Shouldn't be null!");
cleaner->Run();
}
if (NS_FAILED(mgr->AsyncDeleteFile(mFileManager, Id()))) {
CleanupFileRunnable::CleanupFileRunnable(FileManager* aFileManager,
int64_t aFileId)
: mFileManager(aFileManager), mFileId(aFileId)
{
}
NS_IMPL_ISUPPORTS1(CleanupFileRunnable,
nsIRunnable)
NS_IMETHODIMP
CleanupFileRunnable::Run()
{
if (mozilla::dom::quota::QuotaManager::IsShuttingDown()) {
return NS_OK;
}
nsRefPtr<IndexedDatabaseManager> mgr = IndexedDatabaseManager::Get();
MOZ_ASSERT(mgr);
if (NS_FAILED(mgr->AsyncDeleteFile(mFileManager, mFileId))) {
NS_WARNING("Failed to delete file asynchronously!");
}
return NS_OK;
}

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

@ -344,7 +344,6 @@ IndexedDBDatabaseChild::EnsureDatabase(
void
IndexedDBDatabaseChild::ActorDestroy(ActorDestroyReason aWhy)
{
MOZ_ASSERT(!mStrongDatabase);
if (mDatabase) {
mDatabase->SetActor(static_cast<IndexedDBDatabaseChild*>(NULL));
#ifdef DEBUG

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

@ -0,0 +1,98 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>Indexed Database Test</title>
<script type="text/javascript">
function report(result) {
var message = { source: "iframe" };
message.result = result;
window.parent.postMessage(message, "*");
}
function runIndexedDBTest() {
var db = null;
// Create the data-store
function createDatastore() {
try {
var request = indexedDB.open(window.location.pathname, 1);
request.onupgradeneeded = function(event) {
event.target.result.createObjectStore("foo");
}
request.onsuccess = function(event) {
db = event.target.result;
createAndStoreBlob();
}
}
catch (e) {
dump("EXCEPTION IN CREATION: " + e + "\n " + e.stack + "\n");
report(false);
}
}
function createAndStoreBlob() {
const BLOB_DATA = ["fun ", "times ", "all ", "around!"];
var blob = new Blob(BLOB_DATA, { type: "text/plain" });
var objectStore = db.transaction("foo", "readwrite").objectStore("foo");
objectStore.add({ blob: blob }, 42).onsuccess = refetchBlob;
}
function refetchBlob() {
var foo = db.transaction("foo").objectStore("foo");
foo.get(42).onsuccess = fetchedBlobCreateWorkerAndSendBlob;
}
function fetchedBlobCreateWorkerAndSendBlob(event) {
var idbBlob = event.target.result.blob;
var compositeBlob = new Blob(['I like the following blob: ', idbBlob],
{ type: "text/fancy" });
function workerScript() {
onmessage = function(event) {
// Save the Blob to the worker's global scope.
self.holdOntoBlob = event.data;
// Send any message so we can serialize and keep our runtime behaviour
// consistent.
postMessage('kung fu death grip established');
}
}
var url =
URL.createObjectURL(new Blob(["(", workerScript.toSource(), ")()"]));
// Keep a reference to the worker on the window.
var worker = window.worker = new Worker(url);
worker.postMessage(compositeBlob);
worker.onmessage = workerLatchedBlobDeleteFromDB;
}
function workerLatchedBlobDeleteFromDB() {
// Delete the reference to the Blob from the database leaving the worker
// thread reference as the only live reference once a GC has cleaned
// out our references that we sent to the worker. The page that owns
// us triggers a GC just for that reason.
var objectStore = db.transaction("foo", "readwrite").objectStore("foo");
objectStore.delete(42).onsuccess = closeDBTellOwningThread;
}
function closeDBTellOwningThread(event) {
// Now that worker has latched the blob, clean up the database.
db.close();
db = null;
report('ready');
}
createDatastore();
}
</script>
</head>
<body onload="runIndexedDBTest();">
</body>
</html>

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

@ -2,6 +2,7 @@
support-files =
bfcache_iframe1.html
bfcache_iframe2.html
blob_worker_crash_iframe.html
error_events_abort_transactions_iframe.html
event_propagation_iframe.html
exceptions_in_events_iframe.html
@ -26,6 +27,7 @@ support-files =
[test_bfcache.html]
[test_blob_archive.html]
[test_blob_simple.html]
[test_blob_worker_crash.html]
[test_clear.html]
[test_complex_keyPaths.html]
[test_count.html]

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

@ -0,0 +1,62 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html>
<head>
<title>Indexed Database Blob Worker Crash Test</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript;version=1.7">
/*
* This tests ensures that if the last live reference to a Blob is on the
* worker and the database has already been shutdown, that there is no crash
* when the owning page gets cleaned up which causes the termination of the
* worker which in turn garbage collects during its shutdown.
*
* We do the IndexedDB stuff in the iframe so we can kill it as part of our
* test. Doing it out here is no good.
*/
function testSteps()
{
info("Open iframe, wait for it to do its IndexedDB stuff.");
let iframe = document.getElementById("iframe1");
window.addEventListener("message", grabEventAndContinueHandler, false);
// Put it in a different origin to be safe
//allowUnlimitedQuota("http://example.org/");
iframe.src = //"http://example.org" +
window.location.pathname.replace(
"test_blob_worker_crash.html",
"blob_worker_crash_iframe.html");
let event = yield unexpectedSuccessHandler;
is(event.data.result, "ready", "worker initialized correctly");
info("Trigger a GC to clean-up the iframe's main-thread IndexedDB");
scheduleGC();
yield undefined;
info("Kill the iframe, forget about it, trigger a GC.");
iframe.parentNode.removeChild(iframe);
iframe = null;
scheduleGC();
yield undefined;
info("If we are still alive, then we win!");
ok('Did not crash / trigger an assert!');
finishTest();
yield undefined;
}
</script>
<script type="text/javascript;version=1.7" src="helpers.js"></script>
</head>
<body onload="runTest();"></body>
<iframe id="iframe1"></iframe>
</html>

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

@ -206,24 +206,38 @@ MobileMessageManager::Send(const JS::Value& aNumber_,
JS::Rooted<JSObject*> numbers(aCx, &aNumber.toObject());
uint32_t size;
JS_ALWAYS_TRUE(JS_GetArrayLength(aCx, numbers, &size));
if (!JS_GetArrayLength(aCx, numbers, &size)) {
return NS_ERROR_FAILURE;
}
JS::Value* requests = new JS::Value[size];
JS::AutoValueVector requests(aCx);
if (!requests.resize(size)) {
return NS_ERROR_FAILURE;
}
JS::Rooted<JS::Value> number(aCx);
JS::Rooted<JSString*> str(aCx);
for (uint32_t i = 0; i < size; ++i) {
if (!JS_GetElement(aCx, numbers, i, &number)) {
return NS_ERROR_INVALID_ARG;
}
JS::Rooted<JSString*> str(aCx, number.toString());
str = JS::ToString(aCx, number);
if (!str) {
return NS_ERROR_FAILURE;
}
nsresult rv = Send(aCx, global, serviceId, str, aMessage, &requests[i]);
NS_ENSURE_SUCCESS(rv, rv);
}
aReturn->setObjectOrNull(JS_NewArrayObject(aCx, size, requests));
NS_ENSURE_TRUE(aReturn->isObject(), NS_ERROR_FAILURE);
JS::Rooted<JSObject*> obj(aCx);
obj = JS_NewArrayObject(aCx, requests.length(), requests.begin());
if (!obj) {
return NS_ERROR_FAILURE;
}
aReturn->setObject(*obj);
return NS_OK;
}

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

@ -353,7 +353,7 @@ TelephonyProvider.prototype = {
this._getClient(aClientId).sendWorkerMessage("enumerateCalls", null,
(function(response) {
for (let call of response.calls) {
call.clienId = aClientId;
call.clientId = aClientId;
call.state = this._convertRILCallState(call.state);
call.isActive = this._matchActiveCall(call);

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

@ -86,6 +86,11 @@
#include <limits>
#ifdef MOZ_WIDGET_GONK
#include "nsINetworkManager.h"
#include "nsThreadUtils.h" // for NS_IsMainThread
#endif
#ifdef MOZILLA_INTERNAL_API
#include "nsReadableUtils.h"
@ -2360,4 +2365,28 @@ NS_IsSrcdocChannel(nsIChannel *aChannel)
return false;
}
// The following members are used for network per-app metering.
const static uint64_t NETWORK_STATS_THRESHOLD = 65536;
#ifdef MOZ_WIDGET_GONK
inline nsresult
NS_GetActiveNetworkInterface(nsCOMPtr<nsINetworkInterface> &aNetworkInterface)
{
MOZ_ASSERT(NS_IsMainThread());
nsresult rv;
nsCOMPtr<nsINetworkManager> networkManager =
do_GetService("@mozilla.org/network/manager;1", &rv);
if (NS_FAILED(rv) || !networkManager) {
aNetworkInterface = nullptr;
return rv;
}
networkManager->GetActive(getter_AddRefs(aNetworkInterface));
return NS_OK;
}
#endif
#endif // !nsNetUtil_h__

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

@ -1691,6 +1691,10 @@ nsFtpState::Init(nsFtpChannel *channel)
// initialize counter for network metering
mCountRecv = 0;
#ifdef MOZ_WIDGET_GONK
NS_GetActiveNetworkInterface(mActiveNetwork);
#endif
mKeepRunning = true;
mSuppliedEntityID = channel->EntityID();
@ -2199,22 +2203,6 @@ nsresult
nsFtpState::SaveNetworkStats(bool enforce)
{
#ifdef MOZ_WIDGET_GONK
MOZ_ASSERT(NS_IsMainThread());
// Obtain active network
nsresult rv;
if (!mActiveNetwork) {
nsCOMPtr<nsINetworkManager> networkManager =
do_GetService("@mozilla.org/network/manager;1", &rv);
if (NS_FAILED(rv) || !networkManager) {
mActiveNetwork = nullptr;
return rv;
}
networkManager->GetActive(getter_AddRefs(mActiveNetwork));
}
// Obtain app id
uint32_t appId;
bool isInBrowser;
@ -2237,6 +2225,7 @@ nsFtpState::SaveNetworkStats(bool enforce)
return NS_OK;
}
nsresult rv;
nsCOMPtr<nsINetworkStatsServiceProxy> networkStatsServiceProxy =
do_GetService("@mozilla.org/networkstatsServiceProxy;1", &rv);
if (NS_FAILED(rv)) {

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

@ -262,10 +262,6 @@ private:
// These members are used for network per-app metering (bug 855948)
// Currently, they are only available on gonk.
public:
const static uint64_t NETWORK_STATS_THRESHOLD = 65536;
private:
uint64_t mCountRecv;
#ifdef MOZ_WIDGET_GONK
nsCOMPtr<nsINetworkInterface> mActiveNetwork;

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

@ -230,17 +230,20 @@ nsHttpTransaction::Init(uint32_t caps,
mActivityDistributor = nullptr;
}
// obtain app info
bool isInBrowser;
nsCOMPtr<nsIChannel> channel = do_QueryInterface(eventsink);
if (channel) {
bool isInBrowser;
NS_GetAppInfo(channel, &mAppId, &isInBrowser);
}
// obtain active connection type
#ifdef MOZ_WIDGET_GONK
if (mAppId != NECKO_NO_APP_ID) {
GetActiveNetwork();
nsCOMPtr<nsINetworkInterface> activeNetwork;
NS_GetActiveNetworkInterface(activeNetwork);
mActiveNetwork =
new nsMainThreadPtrHolder<nsINetworkInterface>(activeNetwork);
}
#endif
// create transport event sink proxy. it coalesces all events if and only
// if the activity observer is not active. when the observer is active
@ -707,28 +710,6 @@ nsHttpTransaction::WriteSegments(nsAHttpSegmentWriter *writer,
return rv;
}
void
nsHttpTransaction::GetActiveNetwork()
{
#ifdef MOZ_WIDGET_GONK
MOZ_ASSERT(NS_IsMainThread());
nsresult rv;
nsCOMPtr<nsINetworkManager> networkManager =
do_GetService("@mozilla.org/network/manager;1", &rv);
if (NS_FAILED(rv) || !networkManager) {
mActiveNetwork = nullptr;
return;
}
nsCOMPtr<nsINetworkInterface> activeNetwork;
networkManager->GetActive(getter_AddRefs(activeNetwork));
mActiveNetwork =
new nsMainThreadPtrHolder<nsINetworkInterface>(activeNetwork);
#endif
}
//-----------------------------------------------------------------------------
// nsHttpTransaction save network statistics event
//-----------------------------------------------------------------------------

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

@ -340,10 +340,6 @@ private:
// These members are used for network per-app metering (bug 746073)
// Currently, they are only available on gonk.
public:
const static uint64_t NETWORK_STATS_THRESHOLD = 65536;
private:
uint64_t mCountRecv;
uint64_t mCountSent;
uint32_t mAppId;
@ -351,7 +347,6 @@ private:
nsMainThreadPtrHandle<nsINetworkInterface> mActiveNetwork;
#endif
nsresult SaveNetworkStats(bool);
void GetActiveNetwork();
void CountRecvBytes(uint64_t recvBytes)
{
mCountRecv += recvBytes;

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

@ -965,8 +965,7 @@ WebSocketChannel::WebSocketChannel() :
mConnectionLogService(nullptr),
mCountRecv(0),
mCountSent(0),
mAppId(0),
mIsInBrowser(false)
mAppId(NECKO_NO_APP_ID)
{
NS_ABORT_IF_FALSE(NS_IsMainThread(), "not main thread");
@ -1075,15 +1074,16 @@ WebSocketChannel::BeginOpen()
return;
}
// obtain app info
if (localChannel) {
NS_GetAppInfo(localChannel, &mAppId, &mIsInBrowser);
bool isInBrowser;
NS_GetAppInfo(localChannel, &mAppId, &isInBrowser);
}
// obtain active network
#ifdef MOZ_WIDGET_GONK
if (mAppId != NECKO_NO_APP_ID) {
GetActiveNetwork();
NS_GetActiveNetworkInterface(mActiveNetwork);
}
#endif
rv = localChannel->AsyncOpen(this, mHttpChannel);
if (NS_FAILED(rv)) {
@ -3271,28 +3271,6 @@ WebSocketChannel::OnDataAvailable(nsIRequest *aRequest,
return NS_OK;
}
nsresult
WebSocketChannel::GetActiveNetwork()
{
#ifdef MOZ_WIDGET_GONK
MOZ_ASSERT(NS_IsMainThread());
nsresult result;
nsCOMPtr<nsINetworkManager> networkManager = do_GetService("@mozilla.org/network/manager;1", &result);
if (NS_FAILED(result) || !networkManager) {
mActiveNetwork = nullptr;
return NS_ERROR_UNEXPECTED;
}
result = networkManager->GetActive(getter_AddRefs(mActiveNetwork));
return NS_OK;
#else
return NS_ERROR_NOT_IMPLEMENTED;
#endif
}
nsresult
WebSocketChannel::SaveNetworkStats(bool enforce)
{

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

@ -257,18 +257,12 @@ private:
// These members are used for network per-app metering (bug 855949)
// Currently, they are only available on gonk.
public:
const static uint64_t NETWORK_STATS_THRESHOLD = 65536;
private:
uint64_t mCountRecv;
uint64_t mCountSent;
uint32_t mAppId;
bool mIsInBrowser;
#ifdef MOZ_WIDGET_GONK
nsCOMPtr<nsINetworkInterface> mActiveNetwork;
#endif
nsresult GetActiveNetwork();
nsresult SaveNetworkStats(bool);
void CountRecvBytes(uint64_t recvBytes)
{

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

@ -504,6 +504,7 @@
"dom/indexedDB/test/test_autoIncrement_indexes.html": "Bug 931116, b2g desktop specific, initial triage",
"dom/indexedDB/test/test_bfcache.html": "Bug 931116, b2g desktop specific, initial triage",
"dom/indexedDB/test/test_blob_archive.html": "Bug 931116, b2g desktop specific, initial triage",
"dom/indexedDB/test/test_blob_worker_crash.html": "Bug 931116, b2g desktop specific, bug 927889 still present",
"dom/indexedDB/test/test_blob_simple.html": "Bug 931116, b2g desktop specific, initial triage",
"dom/indexedDB/test/test_clear.html": "Bug 931116, b2g desktop specific, initial triage",
"dom/indexedDB/test/test_complex_keyPaths.html": "Bug 931116, b2g desktop specific, initial triage",

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

@ -104,6 +104,13 @@ SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf()
// no associated phdrs
if (strcmp(name, "/dev/ashmem/dalvik-jit-code-cache") != 0)
continue;
#else
if (strcmp(perm, "r-xp") != 0) {
// Ignore entries that are writable and/or shared.
// At least one graphics driver uses short-lived "rwxs" mappings
// (see bug 926734 comment 5), so just checking for 'x' isn't enough.
continue;
}
#endif
SharedLibrary shlib(start, end, offset, "", name);
info.AddSharedLibrary(shlib);