зеркало из https://github.com/mozilla/gecko-dev.git
Merge b2g-inbound to m-c
This commit is contained in:
Коммит
c1b0f6e109
5
CLOBBER
5
CLOBBER
|
@ -18,7 +18,4 @@
|
|||
# Modifying this file will now automatically clobber the buildbot machines \o/
|
||||
#
|
||||
|
||||
Bug 934646 needs a clobber -- the icon resources previously copied
|
||||
into $OBJDIR/mobile/android/base/res will conflict with those in
|
||||
$BRANDING_DIRECTORY/res.
|
||||
|
||||
Bug 946047 - Windows needs a clobber for webidl changes.
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
pref("toolkit.defaultChromeURI", "chrome://browser/content/shell.html");
|
||||
pref("browser.chromeURL", "chrome://browser/content/");
|
||||
|
||||
// Bug 945235: Prevent all bars to be considered visible:
|
||||
pref("toolkit.defaultChromeFeatures", "chrome,dialog=no,close,resizable,scrollbars,extrachrome");
|
||||
|
||||
// Device pixel to CSS px ratio, in percent. Set to -1 to calculate based on display density.
|
||||
pref("browser.viewport.scaleRatio", -1);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"revision": "5bfef5faac50d14e055f642a44ed2df8483fb2fe",
|
||||
"revision": "9271d94f35a54995e4442da711e51cff0244741d",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -148,9 +148,7 @@ VideoTrackEncoder::NotifyQueuedTrackChanges(MediaStreamGraph* aGraph,
|
|||
VideoChunk chunk = *iter;
|
||||
if (!chunk.IsNull()) {
|
||||
gfxIntSize imgsize = chunk.mFrame.GetImage()->GetSize();
|
||||
int width = (imgsize.width + 1) / 2 * 2;
|
||||
int height = (imgsize.height + 1) / 2 * 2;
|
||||
nsresult rv = Init(width, height, aTrackRate);
|
||||
nsresult rv = Init(imgsize.width, imgsize.height, aTrackRate);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG("[VideoTrackEncoder]: Fail to initialize the encoder!");
|
||||
NotifyCancel();
|
||||
|
|
|
@ -41,6 +41,25 @@ using namespace mozilla;
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
class ReleaseOmxDecoderRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
ReleaseOmxDecoderRunnable(const android::sp<android::OmxDecoder>& aOmxDecoder)
|
||||
: mOmxDecoder(aOmxDecoder)
|
||||
{
|
||||
}
|
||||
|
||||
NS_METHOD Run() MOZ_OVERRIDE
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mOmxDecoder = nullptr; // release OmxDecoder
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
android::sp<android::OmxDecoder> mOmxDecoder;
|
||||
};
|
||||
|
||||
class OmxDecoderProcessCachedDataTask : public Task
|
||||
{
|
||||
public:
|
||||
|
@ -53,7 +72,13 @@ public:
|
|||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_ASSERT(mOmxDecoder.get());
|
||||
mOmxDecoder->ProcessCachedData(mOffset, false);
|
||||
int64_t rem = mOmxDecoder->ProcessCachedData(mOffset, false);
|
||||
|
||||
if (rem <= 0) {
|
||||
ReleaseOmxDecoderRunnable* r = new ReleaseOmxDecoderRunnable(mOmxDecoder);
|
||||
mOmxDecoder.clear();
|
||||
NS_DispatchToMainThread(r);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -292,6 +317,8 @@ OmxDecoder::OmxDecoder(MediaResource *aResource,
|
|||
|
||||
OmxDecoder::~OmxDecoder()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
ReleaseMediaResources();
|
||||
|
||||
// unregister AMessage handler from ALooper.
|
||||
|
@ -398,7 +425,7 @@ bool OmxDecoder::TryLoad() {
|
|||
// Feed MP3 parser with cached data. Local files will be fully
|
||||
// cached already, network streams will update with sucessive
|
||||
// calls to NotifyDataArrived.
|
||||
if (ProcessCachedData(0, true)) {
|
||||
if (ProcessCachedData(0, true) >= 0) {
|
||||
durationUs = mMP3FrameParser.GetDuration();
|
||||
if (durationUs > totalDurationUs) {
|
||||
totalDurationUs = durationUs;
|
||||
|
@ -1017,7 +1044,7 @@ void OmxDecoder::ReleaseAllPendingVideoBuffersLocked()
|
|||
releasingVideoBuffers.clear();
|
||||
}
|
||||
|
||||
bool OmxDecoder::ProcessCachedData(int64_t aOffset, bool aWaitForCompletion)
|
||||
int64_t OmxDecoder::ProcessCachedData(int64_t aOffset, bool aWaitForCompletion)
|
||||
{
|
||||
// We read data in chunks of 32 KiB. We can reduce this
|
||||
// value if media, such as sdcards, is too slow.
|
||||
|
@ -1030,10 +1057,10 @@ bool OmxDecoder::ProcessCachedData(int64_t aOffset, bool aWaitForCompletion)
|
|||
MOZ_ASSERT(mResource);
|
||||
|
||||
int64_t resourceLength = mResource->GetCachedDataEnd(0);
|
||||
NS_ENSURE_TRUE(resourceLength >= 0, false);
|
||||
NS_ENSURE_TRUE(resourceLength >= 0, -1);
|
||||
|
||||
if (aOffset >= resourceLength) {
|
||||
return true; // Cache is empty, nothing to do
|
||||
return 0; // Cache is empty, nothing to do
|
||||
}
|
||||
|
||||
int64_t bufferLength = std::min<int64_t>(resourceLength-aOffset, sReadSize);
|
||||
|
@ -1041,7 +1068,7 @@ bool OmxDecoder::ProcessCachedData(int64_t aOffset, bool aWaitForCompletion)
|
|||
nsAutoArrayPtr<char> buffer(new char[bufferLength]);
|
||||
|
||||
nsresult rv = mResource->ReadFromCache(buffer.get(), aOffset, bufferLength);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
NS_ENSURE_SUCCESS(rv, -1);
|
||||
|
||||
nsRefPtr<OmxDecoderNotifyDataArrivedRunnable> runnable(
|
||||
new OmxDecoderNotifyDataArrivedRunnable(this,
|
||||
|
@ -1051,11 +1078,11 @@ bool OmxDecoder::ProcessCachedData(int64_t aOffset, bool aWaitForCompletion)
|
|||
resourceLength));
|
||||
|
||||
rv = NS_DispatchToMainThread(runnable.get());
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
NS_ENSURE_SUCCESS(rv, -1);
|
||||
|
||||
if (aWaitForCompletion) {
|
||||
runnable->WaitForCompletion();
|
||||
}
|
||||
|
||||
return true;
|
||||
return resourceLength - aOffset - bufferLength;
|
||||
}
|
||||
|
|
|
@ -238,7 +238,7 @@ public:
|
|||
// Called on ALooper thread.
|
||||
void onMessageReceived(const sp<AMessage> &msg);
|
||||
|
||||
bool ProcessCachedData(int64_t aOffset, bool aWaitForCompletion);
|
||||
int64_t ProcessCachedData(int64_t aOffset, bool aWaitForCompletion);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -22,44 +22,5 @@ MediaDecoderStateMachine* RtspOmxDecoder::CreateStateMachine()
|
|||
mResource->IsRealTime());
|
||||
}
|
||||
|
||||
void RtspOmxDecoder::ApplyStateToStateMachine(PlayState aState)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
GetReentrantMonitor().AssertCurrentThreadIn();
|
||||
|
||||
MediaDecoder::ApplyStateToStateMachine(aState);
|
||||
|
||||
|
||||
// Send play/pause commands here through the nsIStreamingProtocolController
|
||||
// except seek command. We need to clear the decoded/un-decoded buffer data
|
||||
// before sending seek command. So the seek calling path to controller is:
|
||||
// mDecoderStateMachine::Seek-> RtspOmxReader::Seek-> RtspResource::SeekTime->
|
||||
// controller->Seek(). RtspOmxReader::Seek will clear the decoded buffer and
|
||||
// the RtspResource::SeekTime will clear the un-decoded buffer.
|
||||
|
||||
RtspMediaResource* rtspResource = mResource->GetRtspPointer();
|
||||
MOZ_ASSERT(rtspResource);
|
||||
|
||||
nsIStreamingProtocolController* controller =
|
||||
rtspResource->GetMediaStreamController();
|
||||
if (mDecoderStateMachine) {
|
||||
switch (aState) {
|
||||
case PLAY_STATE_PLAYING:
|
||||
if (controller) {
|
||||
controller->Play();
|
||||
}
|
||||
break;
|
||||
case PLAY_STATE_PAUSED:
|
||||
if (controller) {
|
||||
controller->Pause();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* No action needed */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -32,10 +32,6 @@ public:
|
|||
|
||||
virtual MediaDecoder* Clone() MOZ_OVERRIDE;
|
||||
virtual MediaDecoderStateMachine* CreateStateMachine() MOZ_OVERRIDE;
|
||||
// Called by |ChangeState|, override it to send the Rtsp play/pause commands
|
||||
// through |nsIStreamingProtocolController|.
|
||||
// Call on the main thread only and the lock must be obtained.
|
||||
virtual void ApplyStateToStateMachine(PlayState aState) MOZ_OVERRIDE;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -289,4 +289,44 @@ nsresult RtspOmxReader::Seek(int64_t aTime, int64_t aStartTime,
|
|||
return MediaOmxReader::Seek(aTime, aStartTime, aEndTime, aCurrentTime);
|
||||
}
|
||||
|
||||
void RtspOmxReader::OnDecodeThreadStart() {
|
||||
// Start RTSP streaming right after starting the decoding thread in
|
||||
// MediaDecoderStateMachine and before starting OMXCodec decoding.
|
||||
if (mRtspResource) {
|
||||
nsIStreamingProtocolController* controller =
|
||||
mRtspResource->GetMediaStreamController();
|
||||
if (controller) {
|
||||
controller->Play();
|
||||
}
|
||||
}
|
||||
|
||||
// Call parent class to start OMXCodec decoding.
|
||||
MediaOmxReader::OnDecodeThreadStart();
|
||||
}
|
||||
|
||||
void RtspOmxReader::OnDecodeThreadFinish() {
|
||||
// Call parent class to pause OMXCodec decoding.
|
||||
MediaOmxReader::OnDecodeThreadFinish();
|
||||
|
||||
// Stop RTSP streaming right before destroying the decoding thread in
|
||||
// MediaDecoderStateMachine and after pausing OMXCodec decoding.
|
||||
// RTSP streaming should not be paused until OMXCodec has been paused and
|
||||
// until the decoding thread in MediaDecoderStateMachine is about to be
|
||||
// destroyed. Otherwise, RtspMediaSource::read() would block the binder
|
||||
// thread of OMXCodecObserver::onMessage() --> OMXCodec::on_message() -->
|
||||
// OMXCodec::drainInputBuffer() due to network data starvation. Because
|
||||
// OMXCodec::mLock is held by the binder thread in this case, all other
|
||||
// threads would be blocked when they try to lock this mutex. As a result, the
|
||||
// decoding thread in MediaDecoderStateMachine would be blocked forever in
|
||||
// OMXCodec::read() if there is no enough data for RtspMediaSource::read() to
|
||||
// return.
|
||||
if (mRtspResource) {
|
||||
nsIStreamingProtocolController* controller =
|
||||
mRtspResource->GetMediaStreamController();
|
||||
if (controller) {
|
||||
controller->Pause();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -71,6 +71,10 @@ public:
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
virtual void OnDecodeThreadStart() MOZ_OVERRIDE;
|
||||
|
||||
virtual void OnDecodeThreadFinish() MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
// A pointer to RtspMediaResource for calling the Rtsp specific function.
|
||||
// The lifetime of mRtspResource is controlled by MediaDecoder. MediaDecoder
|
||||
|
|
|
@ -108,6 +108,9 @@ extern bool gBluetoothDebugFlag;
|
|||
#define BLUETOOTH_ADDRESS_NONE "00:00:00:00:00:00"
|
||||
#define BLUETOOTH_ADDRESS_BYTES 6
|
||||
|
||||
// Bluetooth stack internal error, such as I/O error
|
||||
#define ERR_INTERNAL_ERROR "InternalError"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
enum BluetoothSocketType {
|
||||
|
|
|
@ -167,12 +167,6 @@ static const char* sBluetoothDBusSignals[] =
|
|||
"type='signal',interface='org.bluez.Control'"
|
||||
};
|
||||
|
||||
/**
|
||||
* DBus Connection held for the BluetoothCommandThread to use. Should never be
|
||||
* used by any other thread.
|
||||
*/
|
||||
static nsRefPtr<RawDBusConnection> gThreadConnection;
|
||||
|
||||
// Only A2DP and HID are authorized.
|
||||
static nsTArray<BluetoothServiceClass> sAuthorizedServiceClass;
|
||||
|
||||
|
@ -497,6 +491,14 @@ RunDBusCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable,
|
|||
nsAutoString replyError;
|
||||
BluetoothValue v;
|
||||
aFunc(aMsg, nullptr, v, replyError);
|
||||
|
||||
// Bug 941462. When blueZ replys 'I/O error', we treat it as 'internal error'.
|
||||
// This usually happned when the first pairing request has not yet finished,
|
||||
// the second pairing request issued immediately.
|
||||
if (replyError.EqualsLiteral("I/O error")) {
|
||||
replyError.AssignLiteral(ERR_INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
DispatchBluetoothReply(replyRunnable, v, replyError);
|
||||
}
|
||||
|
||||
|
@ -966,9 +968,9 @@ AppendDeviceName(BluetoothSignal& aSignal)
|
|||
|
||||
nsString devicePath = arr[0].value().get_nsString();
|
||||
|
||||
nsRefPtr<RawDBusConnection> threadConnection = gThreadConnection;
|
||||
RawDBusConnection* connection = GetDBusConnection();
|
||||
|
||||
if (!threadConnection.get()) {
|
||||
if (!connection) {
|
||||
BT_WARNING("%s: DBus connection has been closed.", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
@ -977,7 +979,7 @@ AppendDeviceName(BluetoothSignal& aSignal)
|
|||
new AppendDeviceNameReplyHandler(nsCString(DBUS_DEVICE_IFACE),
|
||||
devicePath, aSignal);
|
||||
|
||||
bool success = threadConnection->SendWithReply(
|
||||
bool success = connection->SendWithReply(
|
||||
AppendDeviceNameReplyHandler::Callback, handler.get(), 1000,
|
||||
NS_ConvertUTF16toUTF8(devicePath).get(), DBUS_DEVICE_IFACE,
|
||||
"GetProperties", DBUS_TYPE_INVALID);
|
||||
|
@ -1211,9 +1213,9 @@ public:
|
|||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<RawDBusConnection> threadConnection = gThreadConnection;
|
||||
RawDBusConnection* connection = GetDBusConnection();
|
||||
|
||||
if (!threadConnection.get()) {
|
||||
if (!connection) {
|
||||
BT_WARNING("%s: DBus connection has been closed.", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
@ -1221,7 +1223,7 @@ public:
|
|||
// There is no "RegisterAgent" function defined in device interface.
|
||||
// When we call "CreatePairedDevice", it will do device agent registration
|
||||
// for us. (See maemo.org/api_refs/5.0/beta/bluez/adapter.html)
|
||||
if (!dbus_connection_register_object_path(threadConnection->GetConnection(),
|
||||
if (!dbus_connection_register_object_path(connection->GetConnection(),
|
||||
KEY_REMOTE_AGENT,
|
||||
mAgentVTable,
|
||||
nullptr)) {
|
||||
|
@ -1297,9 +1299,9 @@ private:
|
|||
const char* agentPath = KEY_LOCAL_AGENT;
|
||||
const char* capabilities = B2G_AGENT_CAPABILITIES;
|
||||
|
||||
nsRefPtr<RawDBusConnection> threadConnection = gThreadConnection;
|
||||
RawDBusConnection* connection = GetDBusConnection();
|
||||
|
||||
if (!threadConnection.get()) {
|
||||
if (!connection) {
|
||||
BT_WARNING("%s: DBus connection has been closed.", __FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
|
@ -1310,7 +1312,7 @@ private:
|
|||
// signal will be passed to local agent. If we start pairing process with
|
||||
// calling CreatePairedDevice, we'll get signal which should be passed to
|
||||
// device agent.
|
||||
if (!dbus_connection_register_object_path(threadConnection->GetConnection(),
|
||||
if (!dbus_connection_register_object_path(connection->GetConnection(),
|
||||
KEY_LOCAL_AGENT,
|
||||
aAgentVTable,
|
||||
nullptr)) {
|
||||
|
@ -1324,7 +1326,7 @@ private:
|
|||
MOZ_ASSERT(handler.get());
|
||||
MOZ_ASSERT(!sAdapterPath.IsEmpty());
|
||||
|
||||
bool success = threadConnection->SendWithReply(
|
||||
bool success = connection->SendWithReply(
|
||||
RegisterAgentReplyHandler::Callback, handler.get(), -1,
|
||||
NS_ConvertUTF16toUTF8(sAdapterPath).get(),
|
||||
DBUS_ADAPTER_IFACE, "RegisterAgent",
|
||||
|
@ -1359,9 +1361,9 @@ public:
|
|||
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsRefPtr<RawDBusConnection> threadConnection = gThreadConnection;
|
||||
RawDBusConnection* connection = GetDBusConnection();
|
||||
|
||||
if (!threadConnection.get()) {
|
||||
if (!connection) {
|
||||
BT_WARNING("%s: DBus connection has been closed.", __FUNCTION__);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -1375,7 +1377,7 @@ public:
|
|||
|
||||
const dbus_uint32_t* services = sServices;
|
||||
|
||||
bool success = threadConnection->SendWithReply(
|
||||
bool success = connection->SendWithReply(
|
||||
DBusReplyHandler::Callback, handler.get(), -1,
|
||||
NS_ConvertUTF16toUTF8(sAdapterPath).get(),
|
||||
DBUS_ADAPTER_IFACE, "AddReservedServiceRecords",
|
||||
|
@ -1719,7 +1721,7 @@ OnDefaultAdapterReply(DBusMessage* aReply, void* aData)
|
|||
bool
|
||||
BluetoothDBusService::IsReady()
|
||||
{
|
||||
if (!IsEnabled() || !mConnection || !gThreadConnection || IsToggling()) {
|
||||
if (!IsEnabled() || !GetDBusConnection() || IsToggling()) {
|
||||
BT_WARNING("Bluetooth service is not ready yet!");
|
||||
return false;
|
||||
}
|
||||
|
@ -1737,25 +1739,8 @@ BluetoothDBusService::StartInternal()
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (mConnection) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mConnection = new RawDBusConnection();
|
||||
|
||||
if (NS_FAILED(mConnection->EstablishDBusConnection())) {
|
||||
BT_WARNING("Cannot start Main Thread DBus connection!");
|
||||
StopDBus();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
gThreadConnection = new RawDBusConnection();
|
||||
|
||||
if (NS_FAILED(gThreadConnection->EstablishDBusConnection())) {
|
||||
BT_WARNING("Cannot start Sync Thread DBus connection!");
|
||||
StopDBus();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
RawDBusConnection* connection = GetDBusConnection();
|
||||
MOZ_ASSERT(connection);
|
||||
|
||||
DBusError err;
|
||||
dbus_error_init(&err);
|
||||
|
@ -1765,7 +1750,7 @@ BluetoothDBusService::StartInternal()
|
|||
// signals we want, register all of them in this thread at startup.
|
||||
// The event handler will sort the destinations out as needed.
|
||||
for (uint32_t i = 0; i < ArrayLength(sBluetoothDBusSignals); ++i) {
|
||||
dbus_bus_add_match(mConnection->GetConnection(),
|
||||
dbus_bus_add_match(connection->GetConnection(),
|
||||
sBluetoothDBusSignals[i],
|
||||
&err);
|
||||
if (dbus_error_is_set(&err)) {
|
||||
|
@ -1774,7 +1759,7 @@ BluetoothDBusService::StartInternal()
|
|||
}
|
||||
|
||||
// Add a filter for all incoming messages_base
|
||||
if (!dbus_connection_add_filter(mConnection->GetConnection(),
|
||||
if (!dbus_connection_add_filter(connection->GetConnection(),
|
||||
EventFilter, nullptr, nullptr)) {
|
||||
BT_WARNING("Cannot create DBus Event Filter for DBus Thread!");
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -1792,7 +1777,7 @@ BluetoothDBusService::StartInternal()
|
|||
* explicitly here.
|
||||
*/
|
||||
if (sAdapterPath.IsEmpty()) {
|
||||
bool success = mConnection->SendWithReply(OnDefaultAdapterReply, nullptr,
|
||||
bool success = connection->SendWithReply(OnDefaultAdapterReply, nullptr,
|
||||
1000, "/",
|
||||
DBUS_MANAGER_IFACE,
|
||||
"DefaultAdapter",
|
||||
|
@ -1826,15 +1811,16 @@ BluetoothDBusService::StopInternal()
|
|||
}
|
||||
}
|
||||
|
||||
if (!mConnection) {
|
||||
StopDBus();
|
||||
RawDBusConnection* connection = GetDBusConnection();
|
||||
|
||||
if (!connection) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
DBusError err;
|
||||
dbus_error_init(&err);
|
||||
for (uint32_t i = 0; i < ArrayLength(sBluetoothDBusSignals); ++i) {
|
||||
dbus_bus_remove_match(mConnection->GetConnection(),
|
||||
dbus_bus_remove_match(connection->GetConnection(),
|
||||
sBluetoothDBusSignals[i],
|
||||
&err);
|
||||
if (dbus_error_is_set(&err)) {
|
||||
|
@ -1842,24 +1828,21 @@ BluetoothDBusService::StopInternal()
|
|||
}
|
||||
}
|
||||
|
||||
dbus_connection_remove_filter(mConnection->GetConnection(),
|
||||
dbus_connection_remove_filter(connection->GetConnection(),
|
||||
EventFilter, nullptr);
|
||||
|
||||
if (!dbus_connection_unregister_object_path(gThreadConnection->GetConnection(),
|
||||
if (!dbus_connection_unregister_object_path(connection->GetConnection(),
|
||||
KEY_LOCAL_AGENT)) {
|
||||
BT_WARNING("%s: Can't unregister object path %s for agent!",
|
||||
__FUNCTION__, KEY_LOCAL_AGENT);
|
||||
}
|
||||
|
||||
if (!dbus_connection_unregister_object_path(gThreadConnection->GetConnection(),
|
||||
if (!dbus_connection_unregister_object_path(connection->GetConnection(),
|
||||
KEY_REMOTE_AGENT)) {
|
||||
BT_WARNING("%s: Can't unregister object path %s for agent!",
|
||||
__FUNCTION__, KEY_REMOTE_AGENT);
|
||||
}
|
||||
|
||||
mConnection = nullptr;
|
||||
gThreadConnection = nullptr;
|
||||
|
||||
// unref stored DBusMessages before clear the hashtable
|
||||
sPairingReqTable->EnumerateRead(UnrefDBusMessages, nullptr);
|
||||
sPairingReqTable->Clear();
|
||||
|
@ -1943,14 +1926,14 @@ protected:
|
|||
// Acquire another reference to this reply handler
|
||||
nsRefPtr<DefaultAdapterPathReplyHandler> handler = this;
|
||||
|
||||
nsRefPtr<RawDBusConnection> threadConnection = gThreadConnection;
|
||||
RawDBusConnection* connection = GetDBusConnection();
|
||||
|
||||
if (!threadConnection.get()) {
|
||||
if (!connection) {
|
||||
aReplyError = NS_LITERAL_STRING("DBus connection has been closed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool success = threadConnection->SendWithReply(
|
||||
bool success = connection->SendWithReply(
|
||||
DefaultAdapterPathReplyHandler::Callback, handler.get(), 1000,
|
||||
NS_ConvertUTF16toUTF8(mAdapterPath).get(),
|
||||
DBUS_ADAPTER_IFACE, "GetProperties", DBUS_TYPE_INVALID);
|
||||
|
@ -2011,7 +1994,10 @@ BluetoothDBusService::GetDefaultAdapterPathInternal(
|
|||
nsRefPtr<DefaultAdapterPathReplyHandler> handler =
|
||||
new DefaultAdapterPathReplyHandler(aRunnable);
|
||||
|
||||
bool success = mConnection->SendWithReply(
|
||||
RawDBusConnection* connection = GetDBusConnection();
|
||||
MOZ_ASSERT(connection);
|
||||
|
||||
bool success = connection->SendWithReply(
|
||||
DefaultAdapterPathReplyHandler::Callback,
|
||||
handler.get(), 1000,
|
||||
"/", DBUS_MANAGER_IFACE, "DefaultAdapter",
|
||||
|
@ -2056,7 +2042,10 @@ BluetoothDBusService::SendDiscoveryMessage(const char* aMessageName,
|
|||
|
||||
nsRefPtr<BluetoothReplyRunnable> runnable(aRunnable);
|
||||
|
||||
bool success = mConnection->SendWithReply(
|
||||
RawDBusConnection* connection = GetDBusConnection();
|
||||
MOZ_ASSERT(connection);
|
||||
|
||||
bool success = connection->SendWithReply(
|
||||
OnSendDiscoveryMessageReply,
|
||||
static_cast<void*>(aRunnable), -1,
|
||||
NS_ConvertUTF16toUTF8(sAdapterPath).get(),
|
||||
|
@ -2096,13 +2085,12 @@ BluetoothDBusService::SendAsyncDBusMessage(const nsAString& aObjectPath,
|
|||
DBusReplyCallback aCallback)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mConnection);
|
||||
MOZ_ASSERT(IsEnabled());
|
||||
MOZ_ASSERT(aCallback);
|
||||
MOZ_ASSERT(!aObjectPath.IsEmpty());
|
||||
MOZ_ASSERT(aInterface);
|
||||
|
||||
NS_ENSURE_TRUE(mConnection, NS_ERROR_FAILURE);
|
||||
NS_ENSURE_TRUE(GetDBusConnection(), NS_ERROR_FAILURE);
|
||||
|
||||
nsAutoPtr<BluetoothServiceClass> serviceClass(new BluetoothServiceClass());
|
||||
if (!strcmp(aInterface, DBUS_SINK_IFACE)) {
|
||||
|
@ -2114,7 +2102,10 @@ BluetoothDBusService::SendAsyncDBusMessage(const nsAString& aObjectPath,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
bool ret = mConnection->SendWithReply(
|
||||
RawDBusConnection* connection = GetDBusConnection();
|
||||
MOZ_ASSERT(connection);
|
||||
|
||||
bool ret = connection->SendWithReply(
|
||||
aCallback, static_cast<void*>(serviceClass.forget()), -1,
|
||||
NS_ConvertUTF16toUTF8(aObjectPath).get(),
|
||||
aInterface, NS_ConvertUTF16toUTF8(aMessage).get(),
|
||||
|
@ -2259,16 +2250,16 @@ protected:
|
|||
mObjectPath = GetObjectPathFromAddress(sAdapterPath,
|
||||
mDeviceAddresses[mProcessedDeviceAddresses]);
|
||||
|
||||
nsRefPtr<RawDBusConnection> threadConnection = gThreadConnection;
|
||||
RawDBusConnection* connection = GetDBusConnection();
|
||||
|
||||
if (!threadConnection.get()) {
|
||||
if (!connection) {
|
||||
BT_WARNING("%s: DBus connection has been closed.", __FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
|
||||
nsRefPtr<BluetoothArrayOfDevicePropertiesReplyHandler> handler = this;
|
||||
|
||||
bool success = threadConnection->SendWithReply(
|
||||
bool success = connection->SendWithReply(
|
||||
BluetoothArrayOfDevicePropertiesReplyHandler::Callback,
|
||||
handler.get(), 1000,
|
||||
NS_ConvertUTF16toUTF8(mObjectPath).get(),
|
||||
|
@ -2427,8 +2418,11 @@ BluetoothDBusService::SetProperty(BluetoothObjectType aType,
|
|||
|
||||
nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
|
||||
|
||||
RawDBusConnection* connection = GetDBusConnection();
|
||||
MOZ_ASSERT(connection);
|
||||
|
||||
// msg is unref'd as part of SendWithReply
|
||||
bool success = mConnection->SendWithReply(GetVoidCallback,
|
||||
bool success = connection->SendWithReply(GetVoidCallback,
|
||||
(void*)aRunnable,
|
||||
1000, msg);
|
||||
if (!success) {
|
||||
|
@ -2468,9 +2462,12 @@ BluetoothDBusService::CreatePairedDeviceInternal(
|
|||
nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
|
||||
MOZ_ASSERT(!sAdapterPath.IsEmpty());
|
||||
|
||||
RawDBusConnection* connection = GetDBusConnection();
|
||||
MOZ_ASSERT(connection);
|
||||
|
||||
// Then send CreatePairedDevice, it will register a temp device agent then
|
||||
// unregister it after pairing process is over
|
||||
bool ret = mConnection->SendWithReply(
|
||||
bool ret = connection->SendWithReply(
|
||||
GetObjectPathCallback, (void*)runnable, aTimeout,
|
||||
NS_ConvertUTF16toUTF8(sAdapterPath).get(),
|
||||
DBUS_ADAPTER_IFACE,
|
||||
|
@ -2523,7 +2520,10 @@ BluetoothDBusService::RemoveDeviceInternal(const nsAString& aDeviceAddress,
|
|||
|
||||
nsRefPtr<BluetoothReplyRunnable> runnable(aRunnable);
|
||||
|
||||
bool success = mConnection->SendWithReply(
|
||||
RawDBusConnection* connection = GetDBusConnection();
|
||||
MOZ_ASSERT(connection);
|
||||
|
||||
bool success = connection->SendWithReply(
|
||||
OnRemoveDeviceReply, static_cast<void*>(runnable.get()), -1,
|
||||
NS_ConvertUTF16toUTF8(sAdapterPath).get(),
|
||||
DBUS_ADAPTER_IFACE, "RemoveDevice",
|
||||
|
@ -2574,7 +2574,9 @@ BluetoothDBusService::SetPinCodeInternal(const nsAString& aDeviceAddress,
|
|||
errorStr.AssignLiteral("Couldn't append arguments to dbus message.");
|
||||
result = false;
|
||||
} else {
|
||||
result = mConnection->Send(reply);
|
||||
RawDBusConnection* connection = GetDBusConnection();
|
||||
MOZ_ASSERT(connection);
|
||||
result = connection->Send(reply);
|
||||
}
|
||||
|
||||
dbus_message_unref(msg);
|
||||
|
@ -2620,7 +2622,9 @@ BluetoothDBusService::SetPasskeyInternal(const nsAString& aDeviceAddress,
|
|||
errorStr.AssignLiteral("Couldn't append arguments to dbus message.");
|
||||
result = false;
|
||||
} else {
|
||||
result = mConnection->Send(reply);
|
||||
RawDBusConnection* connection = GetDBusConnection();
|
||||
MOZ_ASSERT(connection);
|
||||
result = connection->Send(reply);
|
||||
}
|
||||
|
||||
dbus_message_unref(msg);
|
||||
|
@ -2664,7 +2668,10 @@ BluetoothDBusService::SetPairingConfirmationInternal(
|
|||
return false;
|
||||
}
|
||||
|
||||
bool result = mConnection->Send(reply);
|
||||
RawDBusConnection* connection = GetDBusConnection();
|
||||
MOZ_ASSERT(connection);
|
||||
|
||||
bool result = connection->Send(reply);
|
||||
if (!result) {
|
||||
errorStr.AssignLiteral("Can't send message!");
|
||||
}
|
||||
|
@ -2907,7 +2914,10 @@ BluetoothDBusService::GetServiceChannel(const nsAString& aDeviceAddress,
|
|||
nsRefPtr<OnGetServiceChannelReplyHandler> handler =
|
||||
new OnGetServiceChannelReplyHandler(objectPath, aServiceUUID, aManager);
|
||||
|
||||
bool success = mConnection->SendWithReply(
|
||||
RawDBusConnection* connection = GetDBusConnection();
|
||||
MOZ_ASSERT(connection);
|
||||
|
||||
bool success = connection->SendWithReply(
|
||||
OnGetServiceChannelReplyHandler::Callback, handler, -1,
|
||||
NS_ConvertUTF16toUTF8(objectPath).get(),
|
||||
DBUS_DEVICE_IFACE, "GetServiceAttributeValue",
|
||||
|
@ -2952,7 +2962,6 @@ BluetoothDBusService::UpdateSdpRecords(const nsAString& aDeviceAddress,
|
|||
MOZ_ASSERT(!aDeviceAddress.IsEmpty());
|
||||
MOZ_ASSERT(!sAdapterPath.IsEmpty());
|
||||
MOZ_ASSERT(aManager);
|
||||
MOZ_ASSERT(mConnection);
|
||||
|
||||
nsString objectPath(GetObjectPathFromAddress(sAdapterPath, aDeviceAddress));
|
||||
|
||||
|
@ -2961,7 +2970,10 @@ BluetoothDBusService::UpdateSdpRecords(const nsAString& aDeviceAddress,
|
|||
OnUpdateSdpRecordsRunnable* callbackRunnable =
|
||||
new OnUpdateSdpRecordsRunnable(objectPath, aManager);
|
||||
|
||||
return mConnection->SendWithReply(DiscoverServicesCallback,
|
||||
RawDBusConnection* connection = GetDBusConnection();
|
||||
MOZ_ASSERT(connection);
|
||||
|
||||
return connection->SendWithReply(DiscoverServicesCallback,
|
||||
(void*)callbackRunnable, -1,
|
||||
NS_ConvertUTF16toUTF8(objectPath).get(),
|
||||
DBUS_DEVICE_IFACE,
|
||||
|
@ -3144,7 +3156,10 @@ BluetoothDBusService::SendMetaData(const nsAString& aTitle,
|
|||
|
||||
nsRefPtr<BluetoothReplyRunnable> runnable(aRunnable);
|
||||
|
||||
bool ret = mConnection->SendWithReply(
|
||||
RawDBusConnection* connection = GetDBusConnection();
|
||||
MOZ_ASSERT(connection);
|
||||
|
||||
bool ret = connection->SendWithReply(
|
||||
GetVoidCallback, (void*)runnable.get(), -1,
|
||||
NS_ConvertUTF16toUTF8(objectPath).get(),
|
||||
DBUS_CTL_IFACE, "UpdateMetaData",
|
||||
|
@ -3243,7 +3258,10 @@ BluetoothDBusService::SendPlayStatus(int64_t aDuration,
|
|||
|
||||
nsRefPtr<BluetoothReplyRunnable> runnable(aRunnable);
|
||||
|
||||
bool ret = mConnection->SendWithReply(
|
||||
RawDBusConnection* connection = GetDBusConnection();
|
||||
MOZ_ASSERT(connection);
|
||||
|
||||
bool ret = connection->SendWithReply(
|
||||
GetVoidCallback, (void*)runnable.get(), -1,
|
||||
NS_ConvertUTF16toUTF8(objectPath).get(),
|
||||
DBUS_CTL_IFACE, "UpdatePlayStatus",
|
||||
|
@ -3292,7 +3310,10 @@ BluetoothDBusService::UpdatePlayStatus(uint32_t aDuration,
|
|||
|
||||
uint32_t tempPlayStatus = aPlayStatus;
|
||||
|
||||
bool ret = mConnection->SendWithReply(
|
||||
RawDBusConnection* connection = GetDBusConnection();
|
||||
MOZ_ASSERT(connection);
|
||||
|
||||
bool ret = connection->SendWithReply(
|
||||
ControlCallback, nullptr, -1,
|
||||
NS_ConvertUTF16toUTF8(objectPath).get(),
|
||||
DBUS_CTL_IFACE, "UpdatePlayStatus",
|
||||
|
@ -3322,7 +3343,10 @@ BluetoothDBusService::UpdateNotification(ControlEventId aEventId,
|
|||
GetObjectPathFromAddress(sAdapterPath, address);
|
||||
uint16_t eventId = aEventId;
|
||||
|
||||
bool ret = mConnection->SendWithReply(
|
||||
RawDBusConnection* connection = GetDBusConnection();
|
||||
MOZ_ASSERT(connection);
|
||||
|
||||
bool ret = connection->SendWithReply(
|
||||
ControlCallback, nullptr, -1,
|
||||
NS_ConvertUTF16toUTF8(objectPath).get(),
|
||||
DBUS_CTL_IFACE, "UpdateNotification",
|
||||
|
|
|
@ -194,8 +194,6 @@ private:
|
|||
const char* aInterface,
|
||||
const nsAString& aMessage,
|
||||
mozilla::ipc::DBusReplyCallback aCallback);
|
||||
|
||||
nsRefPtr<mozilla::ipc::RawDBusConnection> mConnection;
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
|
|
@ -45,10 +45,6 @@ const ContentPanning = {
|
|||
this.watchedEventsType = 'mouse';
|
||||
}
|
||||
|
||||
// If we are using an AsyncPanZoomController for the parent frame,
|
||||
// it will handle subframe scrolling too. We don't need to listen for
|
||||
// these events.
|
||||
if (!docShell.asyncPanZoomEnabled) {
|
||||
let els = Cc["@mozilla.org/eventlistenerservice;1"]
|
||||
.getService(Ci.nsIEventListenerService);
|
||||
|
||||
|
@ -59,7 +55,6 @@ const ContentPanning = {
|
|||
this.handleEvent.bind(this),
|
||||
/* useCapture = */ false);
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
addMessageListener("Viewport:Change", this._recvViewportChange.bind(this));
|
||||
addMessageListener("Gesture:DoubleTap", this._recvDoubleTap.bind(this));
|
||||
|
@ -70,6 +65,8 @@ const ContentPanning = {
|
|||
},
|
||||
|
||||
handleEvent: function cp_handleEvent(evt) {
|
||||
this._tryDelayMouseEvents();
|
||||
|
||||
if (evt.defaultPrevented || evt.multipleActionsPrevented) {
|
||||
// clean up panning state even if touchend/mouseup has been preventDefault.
|
||||
if(evt.type === 'touchend' || evt.type === 'mouseup') {
|
||||
|
@ -82,13 +79,6 @@ const ContentPanning = {
|
|||
return;
|
||||
}
|
||||
|
||||
let start = Date.now();
|
||||
let thread = Services.tm.currentThread;
|
||||
while (this._delayEvents && (Date.now() - start) < this._activeDurationMs) {
|
||||
thread.processNextEvent(true);
|
||||
}
|
||||
this._delayEvents = false;
|
||||
|
||||
switch (evt.type) {
|
||||
case 'mousedown':
|
||||
case 'touchstart':
|
||||
|
@ -189,7 +179,8 @@ const ContentPanning = {
|
|||
|
||||
// We prevent start events to avoid sending a focus event at the end of this
|
||||
// touch series. See bug 889717.
|
||||
if (this.panning || this.preventNextClick) {
|
||||
if (docShell.asyncPanZoomEnabled === false &&
|
||||
(this.panning || this.preventNextClick)) {
|
||||
evt.preventDefault();
|
||||
}
|
||||
},
|
||||
|
@ -228,7 +219,7 @@ const ContentPanning = {
|
|||
let view = target.ownerDocument ? target.ownerDocument.defaultView
|
||||
: target;
|
||||
view.addEventListener('click', this, true, true);
|
||||
} else {
|
||||
} else if (docShell.asyncPanZoomEnabled === false) {
|
||||
// We prevent end events to avoid sending a focus event. See bug 889717.
|
||||
evt.preventDefault();
|
||||
}
|
||||
|
@ -236,12 +227,7 @@ const ContentPanning = {
|
|||
this.notify(this._activationTimer);
|
||||
|
||||
this._delayEvents = true;
|
||||
let start = Date.now();
|
||||
let thread = Services.tm.currentThread;
|
||||
while (this._delayEvents && (Date.now() - start) < this._activeDurationMs) {
|
||||
thread.processNextEvent(true);
|
||||
}
|
||||
this._delayEvents = false;
|
||||
this._tryDelayMouseEvents();
|
||||
}
|
||||
|
||||
this._finishPanning();
|
||||
|
@ -278,7 +264,12 @@ const ContentPanning = {
|
|||
}
|
||||
|
||||
let isPan = KineticPanning.isPan();
|
||||
|
||||
// If the application is not managed by the AsyncPanZoomController, then
|
||||
// scroll manually.
|
||||
if (docShell.asyncPanZoomEnabled === false) {
|
||||
this.scrollCallback(delta.scale(-1));
|
||||
}
|
||||
|
||||
// If we've detected a pan gesture, cancel the active state of the
|
||||
// current target.
|
||||
|
@ -454,6 +445,15 @@ const ContentPanning = {
|
|||
return this._activeDurationMs = duration;
|
||||
},
|
||||
|
||||
_tryDelayMouseEvents: function cp_tryDelayMouseEvents() {
|
||||
let start = Date.now();
|
||||
let thread = Services.tm.currentThread;
|
||||
while (this._delayEvents && (Date.now() - start) < this._activeDurationMs) {
|
||||
thread.processNextEvent(true);
|
||||
}
|
||||
this._delayEvents = false;
|
||||
},
|
||||
|
||||
_resetActive: function cp_resetActive() {
|
||||
let elt = this.pointerDownTarget || this.target;
|
||||
let root = elt.ownerDocument || elt.document;
|
||||
|
@ -594,7 +594,9 @@ const ContentPanning = {
|
|||
delete this.primaryPointerId;
|
||||
this._activationTimer.cancel();
|
||||
|
||||
if (this.panning) {
|
||||
// If there is a scroll action but the application is not managed by
|
||||
// the AsyncPanZoom controller, let's do a manual kinetic panning action.
|
||||
if (this.panning && docShell.asyncPanZoomEnabled === false) {
|
||||
KineticPanning.start(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ const Cu = Components.utils;
|
|||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
this.EXPORTED_SYMBOLS = [];
|
||||
this.EXPORTED_SYMBOLS = ["ContactService"];
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
@ -31,7 +31,7 @@ let ContactService = {
|
|||
"child-process-shutdown", "Contacts:GetRevision",
|
||||
"Contacts:GetCount"];
|
||||
this._children = [];
|
||||
this._cursors = {};
|
||||
this._cursors = new Map();
|
||||
this._messages.forEach(function(msgName) {
|
||||
ppmm.addMessageListener(msgName, this);
|
||||
}.bind(this));
|
||||
|
@ -120,18 +120,21 @@ let ContactService = {
|
|||
if (!this.assertPermission(aMessage, "contacts-read")) {
|
||||
return null;
|
||||
}
|
||||
if (!this._cursors[mm]) {
|
||||
this._cursors[mm] = [];
|
||||
let cursorList = this._cursors.get(mm);
|
||||
if (!cursorList) {
|
||||
cursorList = [];
|
||||
this._cursors.set(mm, cursorList);
|
||||
}
|
||||
this._cursors[mm].push(msg.cursorId);
|
||||
cursorList.push(msg.cursorId);
|
||||
|
||||
this._db.getAll(
|
||||
function(aContacts) {
|
||||
try {
|
||||
mm.sendAsyncMessage("Contacts:GetAll:Next", {cursorId: msg.cursorId, contacts: aContacts});
|
||||
if (aContacts === null) {
|
||||
let index = this._cursors[mm].indexOf(msg.cursorId);
|
||||
this._cursors[mm].splice(index, 1);
|
||||
let cursorList = this._cursors.get(mm);
|
||||
let index = cursorList.indexOf(msg.cursorId);
|
||||
cursorList.splice(index, 1);
|
||||
}
|
||||
} catch (e) {
|
||||
if (DEBUG) debug("Child is dead, DB should stop sending contacts");
|
||||
|
@ -240,11 +243,12 @@ let ContactService = {
|
|||
if (DEBUG) debug("Unregister index: " + index);
|
||||
this._children.splice(index, 1);
|
||||
}
|
||||
if (this._cursors[mm]) {
|
||||
for (let id of this._cursors[mm]) {
|
||||
cursorList = this._cursors.get(mm);
|
||||
if (cursorList) {
|
||||
for (let id of cursorList) {
|
||||
this._db.clearDispatcher(id);
|
||||
}
|
||||
delete this._cursors[mm];
|
||||
this._cursors.delete(mm);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
[DEFAULT]
|
||||
|
||||
[test_contacts_shutdown.xul]
|
||||
skip-if = os == "android"
|
||||
|
||||
[test_contacts_upgrade.xul]
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
|
||||
<?xml-stylesheet type="text/css" href="/tests/SimpleTest/test.css"?>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
|
||||
<window title="Mozilla Bug 945948"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
|
||||
<script type="application/javascript;version=1.7">
|
||||
<![CDATA[
|
||||
"use strict";
|
||||
const { 'utils': Cu } = Components;
|
||||
Cu.import("resource://gre/modules/ContactService.jsm", window);
|
||||
|
||||
//
|
||||
// Mock message manager
|
||||
//
|
||||
function MockMessageManager() { }
|
||||
MockMessageManager.prototype.assertPermission = function() { return true; };
|
||||
MockMessageManager.prototype.sendAsyncMessage = function(name, data) { };
|
||||
|
||||
//
|
||||
// Mock ContactDB
|
||||
//
|
||||
function MockContactDB() { }
|
||||
MockContactDB.prototype.getAll = function(cb) {
|
||||
cb([]);
|
||||
};
|
||||
MockContactDB.prototype.clearDispatcher = function() { }
|
||||
MockContactDB.prototype.close = function() { }
|
||||
|
||||
let realContactDB = ContactService._db;
|
||||
|
||||
function before() {
|
||||
ok(true, "Install mock ContactDB object");
|
||||
ContactService._db = new MockContactDB();
|
||||
}
|
||||
|
||||
function after() {
|
||||
ok(true, "Restore real ContactDB object");
|
||||
ContactService._db = realContactDB;
|
||||
}
|
||||
|
||||
function steps() {
|
||||
let mm1 = new MockMessageManager();
|
||||
let mm2 = new MockMessageManager();
|
||||
|
||||
is(ContactService._cursors.size, 0, "Verify clean contact init");
|
||||
|
||||
ContactService.receiveMessage({
|
||||
target: mm1,
|
||||
name: "Contacts:GetAll",
|
||||
data: { cursorId: 1 },
|
||||
findOptions: {}
|
||||
});
|
||||
is(ContactService._cursors.size, 1, "Add contact cursor 1");
|
||||
|
||||
ContactService.receiveMessage({
|
||||
target: mm2,
|
||||
name: "Contacts:GetAll",
|
||||
data: { cursorId: 2 },
|
||||
findOptions: {}
|
||||
});
|
||||
is(ContactService._cursors.size, 2, "Add contact cursor 2");
|
||||
|
||||
ContactService.receiveMessage({
|
||||
target: mm1,
|
||||
name: "child-process-shutdown"
|
||||
});
|
||||
is(ContactService._cursors.size, 1, "Shutdown contact cursor 1");
|
||||
|
||||
ContactService.receiveMessage({
|
||||
target: mm2,
|
||||
name: "child-process-shutdown"
|
||||
});
|
||||
is(ContactService._cursors.size, 0, "Shutdown contact cursor 2");
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
try {
|
||||
before();
|
||||
steps();
|
||||
} finally {
|
||||
after();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
runTests();
|
||||
]]>
|
||||
</script>
|
||||
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=945948"
|
||||
target="_blank">Mozilla Bug 945948</a>
|
||||
</body>
|
||||
</window>
|
|
@ -385,7 +385,6 @@ var interfaceNamesInGlobalScope =
|
|||
"MozMobileMessageThread",
|
||||
"MozNamedAttrMap",
|
||||
{name: "MozNdefRecord", b2g: true},
|
||||
{name: "MozNfc", b2g: true},
|
||||
{name: "MozNFCPeer", b2g: true},
|
||||
{name: "MozNFCTag", b2g: true},
|
||||
{name: "MozOtaStatusEvent", b2g: true, pref: "dom.mobileconnection.enabled"},
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
/* Copyright © 2013 Deutsche Telekom, Inc. */
|
||||
|
||||
[JSImplementation="@mozilla.org/navigatorNfc;1",
|
||||
NavigatorProperty="mozNfc"]
|
||||
NavigatorProperty="mozNfc",
|
||||
Func="Navigator::HasNfcSupport"]
|
||||
interface MozNfc : EventTarget {
|
||||
MozNFCTag getNFCTag(DOMString sessionId);
|
||||
MozNFCPeer getNFCPeer(DOMString sessionId);
|
||||
|
|
|
@ -175,7 +175,8 @@ Layer::Layer(LayerManager* aManager, void* aImplData) :
|
|||
mIsFixedPosition(false),
|
||||
mMargins(0, 0, 0, 0),
|
||||
mStickyPositionData(nullptr),
|
||||
mIsScrollbar(false),
|
||||
mScrollbarTargetId(FrameMetrics::NULL_SCROLL_ID),
|
||||
mScrollbarDirection(ScrollDirection::NONE),
|
||||
mDebugColorIndex(0),
|
||||
mAnimationGeneration(0)
|
||||
{}
|
||||
|
@ -1268,12 +1269,11 @@ Layer::PrintInfo(nsACString& aTo, const char* aPrefix)
|
|||
if (GetContentFlags() & CONTENT_COMPONENT_ALPHA) {
|
||||
aTo += " [componentAlpha]";
|
||||
}
|
||||
if (GetIsScrollbar()) {
|
||||
if (GetScrollbarDirection() == VERTICAL) {
|
||||
aTo.AppendPrintf(" [vscrollbar=%lld]", GetScrollbarTargetContainerId());
|
||||
} else {
|
||||
aTo.AppendPrintf(" [hscrollbar=%lld]", GetScrollbarTargetContainerId());
|
||||
}
|
||||
if (GetScrollbarDirection() == HORIZONTAL) {
|
||||
aTo.AppendPrintf(" [hscrollbar=%lld]", GetScrollbarTargetContainerId());
|
||||
}
|
||||
if (GetIsFixedPosition()) {
|
||||
aTo.AppendPrintf(" [isFixedPosition anchor=%f,%f]", mAnchor.x, mAnchor.y);
|
||||
|
|
|
@ -967,6 +967,7 @@ public:
|
|||
}
|
||||
|
||||
enum ScrollDirection {
|
||||
NONE,
|
||||
VERTICAL,
|
||||
HORIZONTAL
|
||||
};
|
||||
|
@ -978,11 +979,9 @@ public:
|
|||
*/
|
||||
void SetScrollbarData(FrameMetrics::ViewID aScrollId, ScrollDirection aDir)
|
||||
{
|
||||
if (mIsScrollbar ||
|
||||
mScrollbarTargetId != aScrollId ||
|
||||
if (mScrollbarTargetId != aScrollId ||
|
||||
mScrollbarDirection != aDir) {
|
||||
MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) ScrollbarData", this));
|
||||
mIsScrollbar = true;
|
||||
mScrollbarTargetId = aScrollId;
|
||||
mScrollbarDirection = aDir;
|
||||
Mutated();
|
||||
|
@ -1013,7 +1012,6 @@ public:
|
|||
FrameMetrics::ViewID GetStickyScrollContainerId() { return mStickyPositionData->mScrollId; }
|
||||
const LayerRect& GetStickyScrollRangeOuter() { return mStickyPositionData->mOuter; }
|
||||
const LayerRect& GetStickyScrollRangeInner() { return mStickyPositionData->mInner; }
|
||||
bool GetIsScrollbar() { return mIsScrollbar; }
|
||||
FrameMetrics::ViewID GetScrollbarTargetContainerId() { return mScrollbarTargetId; }
|
||||
ScrollDirection GetScrollbarDirection() { return mScrollbarDirection; }
|
||||
Layer* GetMaskLayer() const { return mMaskLayer; }
|
||||
|
@ -1387,7 +1385,6 @@ protected:
|
|||
LayerRect mInner;
|
||||
};
|
||||
nsAutoPtr<StickyPositionData> mStickyPositionData;
|
||||
bool mIsScrollbar;
|
||||
FrameMetrics::ViewID mScrollbarTargetId;
|
||||
ScrollDirection mScrollbarDirection;
|
||||
DebugOnly<uint32_t> mDebugColorIndex;
|
||||
|
|
|
@ -525,7 +525,7 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(TimeStamp aCurrentFram
|
|||
appliedTransform = true;
|
||||
}
|
||||
|
||||
if (container->GetIsScrollbar()) {
|
||||
if (container->GetScrollbarDirection() != Layer::NONE) {
|
||||
ApplyAsyncTransformToScrollbar(container);
|
||||
}
|
||||
return appliedTransform;
|
||||
|
|
|
@ -1276,7 +1276,9 @@ void AsyncPanZoomController::RequestContentRepaint() {
|
|||
mFrameMetrics.mScrollOffset.x) < EPSILON &&
|
||||
fabsf(mLastPaintRequestMetrics.mScrollOffset.y -
|
||||
mFrameMetrics.mScrollOffset.y) < EPSILON &&
|
||||
mFrameMetrics.mZoom == mLastPaintRequestMetrics.mZoom) {
|
||||
mFrameMetrics.mZoom == mLastPaintRequestMetrics.mZoom &&
|
||||
fabsf(mFrameMetrics.mViewport.width - mLastPaintRequestMetrics.mViewport.width) < EPSILON &&
|
||||
fabsf(mFrameMetrics.mViewport.height - mLastPaintRequestMetrics.mViewport.height) < EPSILON) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1463,8 +1465,10 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri
|
|||
aLayerMetrics.mCompositionBounds.height == mFrameMetrics.mCompositionBounds.height) {
|
||||
// Remote content has sync'd up to the composition geometry
|
||||
// change, so we can accept the viewport it's calculated.
|
||||
if (mFrameMetrics.mViewport.width != aLayerMetrics.mViewport.width)
|
||||
if (mFrameMetrics.mViewport.width != aLayerMetrics.mViewport.width ||
|
||||
mFrameMetrics.mViewport.height != aLayerMetrics.mViewport.height) {
|
||||
needContentRepaint = true;
|
||||
}
|
||||
mFrameMetrics.mViewport = aLayerMetrics.mViewport;
|
||||
}
|
||||
|
||||
|
|
|
@ -280,10 +280,8 @@ LayerTransactionParent::RecvUpdate(const InfallibleTArray<Edit>& cset,
|
|||
common.stickyScrollRangeOuter(),
|
||||
common.stickyScrollRangeInner());
|
||||
}
|
||||
if (common.isScrollbar()) {
|
||||
layer->SetScrollbarData(common.scrollbarTargetContainerId(),
|
||||
static_cast<Layer::ScrollDirection>(common.scrollbarDirection()));
|
||||
}
|
||||
if (PLayerParent* maskLayer = common.maskLayerParent()) {
|
||||
layer->SetMaskLayer(cast(maskLayer)->AsLayer());
|
||||
} else {
|
||||
|
|
|
@ -198,7 +198,6 @@ struct CommonLayerAttributes {
|
|||
uint64_t stickyScrollContainerId;
|
||||
LayerRect stickyScrollRangeOuter;
|
||||
LayerRect stickyScrollRangeInner;
|
||||
bool isScrollbar;
|
||||
uint64_t scrollbarTargetContainerId;
|
||||
uint32_t scrollbarDirection;
|
||||
nullable PLayer maskLayer;
|
||||
|
|
|
@ -501,11 +501,8 @@ ShadowLayerForwarder::EndTransaction(InfallibleTArray<EditReply>* aReplies, bool
|
|||
common.stickyScrollRangeOuter() = mutant->GetStickyScrollRangeOuter();
|
||||
common.stickyScrollRangeInner() = mutant->GetStickyScrollRangeInner();
|
||||
}
|
||||
common.isScrollbar() = mutant->GetIsScrollbar();
|
||||
if (mutant->GetIsScrollbar()) {
|
||||
common.scrollbarTargetContainerId() = mutant->GetScrollbarTargetContainerId();
|
||||
common.scrollbarDirection() = mutant->GetScrollbarDirection();
|
||||
}
|
||||
if (Layer* maskLayer = mutant->GetMaskLayer()) {
|
||||
common.maskLayerChild() = Shadow(maskLayer->AsShadowableLayer());
|
||||
} else {
|
||||
|
|
|
@ -66,544 +66,214 @@
|
|||
#define LOG(args...) if (BTDEBUG) printf(args);
|
||||
#endif
|
||||
|
||||
#define DEFAULT_INITIAL_POLLFD_COUNT 8
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
class DBusWatcher : public RawDBusConnection
|
||||
class DBusWatcher : public MessageLoopForIO::Watcher
|
||||
{
|
||||
public:
|
||||
DBusWatcher()
|
||||
{ }
|
||||
DBusWatcher(RawDBusConnection* aConnection, DBusWatch* aWatch)
|
||||
: mConnection(aConnection),
|
||||
mWatch(aWatch)
|
||||
{
|
||||
MOZ_ASSERT(mConnection);
|
||||
MOZ_ASSERT(mWatch);
|
||||
}
|
||||
|
||||
~DBusWatcher()
|
||||
{ }
|
||||
|
||||
bool Initialize();
|
||||
void CleanUp();
|
||||
|
||||
void WakeUp();
|
||||
bool Stop();
|
||||
|
||||
bool Poll();
|
||||
|
||||
bool AddWatch(DBusWatch* aWatch);
|
||||
void RemoveWatch(DBusWatch* aWatch);
|
||||
|
||||
void HandleWatchAdd();
|
||||
void HandleWatchRemove();
|
||||
|
||||
// Information about the sockets we're polling. Socket counts
|
||||
// increase/decrease depending on how many add/remove watch signals
|
||||
// we're received via the control sockets.
|
||||
nsTArray<pollfd> mPollData;
|
||||
nsTArray<DBusWatch*> mWatchData;
|
||||
|
||||
// Sockets for receiving dbus control information (watch
|
||||
// add/removes, loop shutdown, etc...)
|
||||
ScopedClose mControlFdR;
|
||||
ScopedClose mControlFdW;
|
||||
|
||||
private:
|
||||
struct PollFdComparator {
|
||||
bool Equals(const pollfd& a, const pollfd& b) const {
|
||||
return ((a.fd == b.fd) && (a.events == b.events));
|
||||
}
|
||||
bool LessThan(const pollfd& a, const pollfd&b) const {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
enum DBusEventTypes {
|
||||
DBUS_EVENT_LOOP_EXIT = 1,
|
||||
DBUS_EVENT_LOOP_ADD = 2,
|
||||
DBUS_EVENT_LOOP_REMOVE = 3,
|
||||
DBUS_EVENT_LOOP_WAKEUP = 4
|
||||
};
|
||||
|
||||
static unsigned int UnixEventsToDBusFlags(short events);
|
||||
static short DBusFlagsToUnixEvents(unsigned int flags);
|
||||
void StartWatching();
|
||||
void StopWatching();
|
||||
|
||||
static void FreeFunction(void* aData);
|
||||
static dbus_bool_t AddWatchFunction(DBusWatch* aWatch, void* aData);
|
||||
static void RemoveWatchFunction(DBusWatch* aWatch, void* aData);
|
||||
static void ToggleWatchFunction(DBusWatch* aWatch, void* aData);
|
||||
static void DBusWakeupFunction(void* aData);
|
||||
|
||||
bool SetUp();
|
||||
RawDBusConnection* GetConnection();
|
||||
|
||||
private:
|
||||
void OnFileCanReadWithoutBlocking(int aFd);
|
||||
void OnFileCanWriteWithoutBlocking(int aFd);
|
||||
|
||||
// Read watcher for libevent. Only to be accessed on IO Thread.
|
||||
MessageLoopForIO::FileDescriptorWatcher mReadWatcher;
|
||||
|
||||
// Write watcher for libevent. Only to be accessed on IO Thread.
|
||||
MessageLoopForIO::FileDescriptorWatcher mWriteWatcher;
|
||||
|
||||
// DBus structures
|
||||
RawDBusConnection* mConnection;
|
||||
DBusWatch* mWatch;
|
||||
};
|
||||
|
||||
bool
|
||||
DBusWatcher::Initialize()
|
||||
RawDBusConnection*
|
||||
DBusWatcher::GetConnection()
|
||||
{
|
||||
if (!SetUp()) {
|
||||
CleanUp();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return mConnection;
|
||||
}
|
||||
|
||||
void
|
||||
DBusWatcher::CleanUp()
|
||||
void DBusWatcher::StartWatching()
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_ASSERT(mWatch);
|
||||
|
||||
int fd = dbus_watch_get_unix_fd(mWatch);
|
||||
|
||||
MessageLoopForIO* ioLoop = MessageLoopForIO::current();
|
||||
ioLoop->WatchFileDescriptor(fd, true, MessageLoopForIO::WATCH_READ,
|
||||
&mReadWatcher, this);
|
||||
ioLoop->WatchFileDescriptor(fd, true, MessageLoopForIO::WATCH_WRITE,
|
||||
&mWriteWatcher, this);
|
||||
}
|
||||
|
||||
void DBusWatcher::StopWatching()
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
dbus_connection_set_wakeup_main_function(mConnection, nullptr,
|
||||
nullptr, nullptr);
|
||||
dbus_bool_t success = dbus_connection_set_watch_functions(mConnection,
|
||||
nullptr, nullptr,
|
||||
nullptr, nullptr,
|
||||
nullptr);
|
||||
if (success != TRUE) {
|
||||
NS_WARNING("dbus_connection_set_watch_functions failed");
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
LOG("Removing DBus Sockets\n");
|
||||
#endif
|
||||
if (mControlFdW.get()) {
|
||||
mControlFdW.dispose();
|
||||
}
|
||||
if (mControlFdR.get()) {
|
||||
mControlFdR.dispose();
|
||||
}
|
||||
mPollData.Clear();
|
||||
|
||||
// DBusWatch pointers are maintained by DBus, so we won't leak by
|
||||
// clearing.
|
||||
mWatchData.Clear();
|
||||
}
|
||||
|
||||
void
|
||||
DBusWatcher::WakeUp()
|
||||
{
|
||||
static const char control = DBUS_EVENT_LOOP_WAKEUP;
|
||||
|
||||
struct pollfd fds = {
|
||||
mControlFdW.get(),
|
||||
POLLOUT,
|
||||
0
|
||||
};
|
||||
|
||||
int nfds = TEMP_FAILURE_RETRY(poll(&fds, 1, 0));
|
||||
NS_ENSURE_TRUE_VOID(nfds == 1);
|
||||
NS_ENSURE_TRUE_VOID(fds.revents == POLLOUT);
|
||||
|
||||
ssize_t res = TEMP_FAILURE_RETRY(
|
||||
write(mControlFdW.get(), &control, sizeof(control)));
|
||||
if (res < 0) {
|
||||
NS_WARNING("Cannot write wakeup bit to DBus controller!");
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
DBusWatcher::Stop()
|
||||
{
|
||||
static const char data = DBUS_EVENT_LOOP_EXIT;
|
||||
|
||||
ssize_t res =
|
||||
TEMP_FAILURE_RETRY(write(mControlFdW.get(), &data, sizeof(data)));
|
||||
NS_ENSURE_TRUE(res == 1, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
DBusWatcher::Poll()
|
||||
{
|
||||
int res = TEMP_FAILURE_RETRY(poll(mPollData.Elements(),
|
||||
mPollData.Length(), -1));
|
||||
NS_ENSURE_TRUE(res > 0, false);
|
||||
|
||||
bool continueThread = true;
|
||||
|
||||
nsTArray<pollfd>::size_type i = 0;
|
||||
|
||||
while (i < mPollData.Length()) {
|
||||
if (mPollData[i].revents == POLLIN) {
|
||||
if (mPollData[i].fd == mControlFdR.get()) {
|
||||
char data;
|
||||
res = TEMP_FAILURE_RETRY(read(mControlFdR.get(), &data, sizeof(data)));
|
||||
NS_ENSURE_TRUE(res > 0, false);
|
||||
|
||||
switch (data) {
|
||||
case DBUS_EVENT_LOOP_EXIT:
|
||||
continueThread = false;
|
||||
break;
|
||||
case DBUS_EVENT_LOOP_ADD:
|
||||
HandleWatchAdd();
|
||||
break;
|
||||
case DBUS_EVENT_LOOP_REMOVE:
|
||||
HandleWatchRemove();
|
||||
// don't increment i, or we'll skip one element
|
||||
continue;
|
||||
case DBUS_EVENT_LOOP_WAKEUP:
|
||||
NS_ProcessPendingEvents(NS_GetCurrentThread(),
|
||||
PR_INTERVAL_NO_TIMEOUT);
|
||||
break;
|
||||
default:
|
||||
#if DEBUG
|
||||
nsCString warning("unknown command ");
|
||||
warning.AppendInt(data);
|
||||
NS_WARNING(warning.get());
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
short events = mPollData[i].revents;
|
||||
mPollData[i].revents = 0;
|
||||
|
||||
dbus_watch_handle(mWatchData[i], UnixEventsToDBusFlags(events));
|
||||
|
||||
DBusDispatchStatus dbusDispatchStatus;
|
||||
do {
|
||||
dbusDispatchStatus = dbus_connection_dispatch(GetConnection());
|
||||
} while (dbusDispatchStatus == DBUS_DISPATCH_DATA_REMAINS);
|
||||
|
||||
// Break at this point since we don't know if the operation
|
||||
// was destructive
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
return continueThread;
|
||||
}
|
||||
|
||||
bool
|
||||
DBusWatcher::AddWatch(DBusWatch* aWatch)
|
||||
{
|
||||
static const char control = DBUS_EVENT_LOOP_ADD;
|
||||
|
||||
if (dbus_watch_get_enabled(aWatch) == FALSE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// note that we can't just send the watch and inspect it later
|
||||
// because we may get a removeWatch call before this data is reacted
|
||||
// to by our eventloop and remove this watch.. reading the add first
|
||||
// and then inspecting the recently deceased watch would be bad.
|
||||
ssize_t res =
|
||||
TEMP_FAILURE_RETRY(write(mControlFdW.get(),&control, sizeof(control)));
|
||||
if (res < 0) {
|
||||
LOG("Cannot write DBus add watch control data to socket!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
int fd = dbus_watch_get_unix_fd(aWatch);
|
||||
res = TEMP_FAILURE_RETRY(write(mControlFdW.get(), &fd, sizeof(fd)));
|
||||
if (res < 0) {
|
||||
LOG("Cannot write DBus add watch descriptor data to socket!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int flags = dbus_watch_get_flags(aWatch);
|
||||
res = TEMP_FAILURE_RETRY(write(mControlFdW.get(), &flags, sizeof(flags)));
|
||||
if (res < 0) {
|
||||
LOG("Cannot write DBus add watch flag data to socket!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
res = TEMP_FAILURE_RETRY(write(mControlFdW.get(), &aWatch, sizeof(aWatch)));
|
||||
if (res < 0) {
|
||||
LOG("Cannot write DBus add watch struct data to socket!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
DBusWatcher::RemoveWatch(DBusWatch* aWatch)
|
||||
{
|
||||
static const char control = DBUS_EVENT_LOOP_REMOVE;
|
||||
|
||||
ssize_t res =
|
||||
TEMP_FAILURE_RETRY(write(mControlFdW.get(), &control, sizeof(control)));
|
||||
if (res < 0) {
|
||||
LOG("Cannot write DBus remove watch control data to socket!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
int fd = dbus_watch_get_unix_fd(aWatch);
|
||||
res = TEMP_FAILURE_RETRY(write(mControlFdW.get(), &fd, sizeof(fd)));
|
||||
if (res < 0) {
|
||||
LOG("Cannot write DBus remove watch descriptor data to socket!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int flags = dbus_watch_get_flags(aWatch);
|
||||
res = TEMP_FAILURE_RETRY(write(mControlFdW.get(), &flags, sizeof(flags)));
|
||||
if (res < 0) {
|
||||
LOG("Cannot write DBus remove watch flag data to socket!\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DBusWatcher::HandleWatchAdd()
|
||||
{
|
||||
int fd;
|
||||
ssize_t res = TEMP_FAILURE_RETRY(read(mControlFdR.get(), &fd, sizeof(fd)));
|
||||
if (res < 0) {
|
||||
LOG("Cannot read DBus watch add descriptor data from socket!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int flags;
|
||||
res = TEMP_FAILURE_RETRY(read(mControlFdR.get(), &flags, sizeof(flags)));
|
||||
if (res < 0) {
|
||||
LOG("Cannot read DBus watch add flag data from socket!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
DBusWatch* watch;
|
||||
res = TEMP_FAILURE_RETRY(read(mControlFdR.get(), &watch, sizeof(watch)));
|
||||
if (res < 0) {
|
||||
LOG("Cannot read DBus watch add watch data from socket!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
struct pollfd p = {
|
||||
fd, // .fd
|
||||
DBusFlagsToUnixEvents(flags), // .events
|
||||
0 // .revents
|
||||
};
|
||||
if (mPollData.Contains(p, PollFdComparator())) {
|
||||
return;
|
||||
}
|
||||
mPollData.AppendElement(p);
|
||||
mWatchData.AppendElement(watch);
|
||||
}
|
||||
|
||||
void
|
||||
DBusWatcher::HandleWatchRemove()
|
||||
{
|
||||
int fd;
|
||||
ssize_t res = TEMP_FAILURE_RETRY(read(mControlFdR.get(), &fd, sizeof(fd)));
|
||||
if (res < 0) {
|
||||
LOG("Cannot read DBus watch remove descriptor data from socket!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int flags;
|
||||
res = TEMP_FAILURE_RETRY(read(mControlFdR.get(), &flags, sizeof(flags)));
|
||||
if (res < 0) {
|
||||
LOG("Cannot read DBus watch remove flag data from socket!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
struct pollfd p = {
|
||||
fd, // .fd
|
||||
DBusFlagsToUnixEvents(flags), // .events
|
||||
0 // .revents
|
||||
};
|
||||
int index = mPollData.IndexOf(p, 0, PollFdComparator());
|
||||
// There are times where removes can be requested for watches that
|
||||
// haven't been added (for example, whenever gecko comes up after
|
||||
// adapters have already been enabled), so check to make sure we're
|
||||
// using the watch in the first place
|
||||
if (index < 0) {
|
||||
LOG("DBus requested watch removal of non-existant socket, ignoring...");
|
||||
return;
|
||||
}
|
||||
mPollData.RemoveElementAt(index);
|
||||
|
||||
// DBusWatch pointers are maintained by DBus, so we won't leak by
|
||||
// removing.
|
||||
mWatchData.RemoveElementAt(index);
|
||||
}
|
||||
|
||||
// Flag conversion
|
||||
|
||||
unsigned int
|
||||
DBusWatcher::UnixEventsToDBusFlags(short events)
|
||||
{
|
||||
return (events & DBUS_WATCH_READABLE ? POLLIN : 0) |
|
||||
(events & DBUS_WATCH_WRITABLE ? POLLOUT : 0) |
|
||||
(events & DBUS_WATCH_ERROR ? POLLERR : 0) |
|
||||
(events & DBUS_WATCH_HANGUP ? POLLHUP : 0);
|
||||
}
|
||||
|
||||
short
|
||||
DBusWatcher::DBusFlagsToUnixEvents(unsigned int flags)
|
||||
{
|
||||
return (flags & POLLIN ? DBUS_WATCH_READABLE : 0) |
|
||||
(flags & POLLOUT ? DBUS_WATCH_WRITABLE : 0) |
|
||||
(flags & POLLERR ? DBUS_WATCH_ERROR : 0) |
|
||||
(flags & POLLHUP ? DBUS_WATCH_HANGUP : 0);
|
||||
mReadWatcher.StopWatchingFileDescriptor();
|
||||
mWriteWatcher.StopWatchingFileDescriptor();
|
||||
}
|
||||
|
||||
// DBus utility functions, used as function pointers in DBus setup
|
||||
|
||||
void
|
||||
DBusWatcher::FreeFunction(void* aData)
|
||||
{
|
||||
delete static_cast<DBusWatcher*>(aData);
|
||||
}
|
||||
|
||||
dbus_bool_t
|
||||
DBusWatcher::AddWatchFunction(DBusWatch* aWatch, void* aData)
|
||||
{
|
||||
MOZ_ASSERT(aData);
|
||||
DBusWatcher* dbusWatcher = static_cast<DBusWatcher*>(aData);
|
||||
return dbusWatcher->AddWatch(aWatch);
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
RawDBusConnection* connection = static_cast<RawDBusConnection*>(aData);
|
||||
|
||||
DBusWatcher* dbusWatcher = new DBusWatcher(connection, aWatch);
|
||||
dbus_watch_set_data(aWatch, dbusWatcher, DBusWatcher::FreeFunction);
|
||||
|
||||
if (dbus_watch_get_enabled(aWatch)) {
|
||||
dbusWatcher->StartWatching();
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
DBusWatcher::RemoveWatchFunction(DBusWatch* aWatch, void* aData)
|
||||
{
|
||||
MOZ_ASSERT(aData);
|
||||
DBusWatcher* dbusWatcher = static_cast<DBusWatcher*>(aData);
|
||||
dbusWatcher->RemoveWatch(aWatch);
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
DBusWatcher* dbusWatcher =
|
||||
static_cast<DBusWatcher*>(dbus_watch_get_data(aWatch));
|
||||
dbusWatcher->StopWatching();
|
||||
}
|
||||
|
||||
void
|
||||
DBusWatcher::ToggleWatchFunction(DBusWatch* aWatch, void* aData)
|
||||
{
|
||||
MOZ_ASSERT(aData);
|
||||
DBusWatcher* dbusWatcher = static_cast<DBusWatcher*>(aData);
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
DBusWatcher* dbusWatcher =
|
||||
static_cast<DBusWatcher*>(dbus_watch_get_data(aWatch));
|
||||
|
||||
if (dbus_watch_get_enabled(aWatch)) {
|
||||
dbusWatcher->AddWatch(aWatch);
|
||||
dbusWatcher->StartWatching();
|
||||
} else {
|
||||
dbusWatcher->RemoveWatch(aWatch);
|
||||
dbusWatcher->StopWatching();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DBusWatcher::DBusWakeupFunction(void* aData)
|
||||
{
|
||||
MOZ_ASSERT(aData);
|
||||
DBusWatcher* dbusWatcher = static_cast<DBusWatcher*>(aData);
|
||||
dbusWatcher->WakeUp();
|
||||
}
|
||||
|
||||
bool
|
||||
DBusWatcher::SetUp()
|
||||
DBusWatcher::OnFileCanReadWithoutBlocking(int aFd)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
// If we already have a connection, exit
|
||||
if (mConnection) {
|
||||
return false;
|
||||
}
|
||||
dbus_watch_handle(mWatch, DBUS_WATCH_READABLE);
|
||||
|
||||
// socketpair opens two sockets for the process to communicate on.
|
||||
// This is how android's implementation of the dbus event loop
|
||||
// communicates with itself in relation to IPC signals. These
|
||||
// sockets are contained sequentially in the same struct in the
|
||||
// android code, but we break them out into class members here.
|
||||
// Therefore we read into a local array and then copy.
|
||||
|
||||
int sockets[2];
|
||||
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sockets) < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mControlFdR.rwget() = sockets[0];
|
||||
mControlFdW.rwget() = sockets[1];
|
||||
|
||||
pollfd* p = mPollData.AppendElement();
|
||||
|
||||
p->fd = mControlFdR.get();
|
||||
p->events = POLLIN;
|
||||
p->revents = 0;
|
||||
|
||||
// Due to the fact that mPollData and mWatchData have to match, we
|
||||
// push a null to the front of mWatchData since it has the control
|
||||
// fd in the first slot of mPollData.
|
||||
|
||||
mWatchData.AppendElement(static_cast<DBusWatch*>(nullptr));
|
||||
|
||||
// If we can't establish a connection to dbus, nothing else will work
|
||||
nsresult rv = EstablishDBusConnection();
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Cannot create DBus Connection for DBus Thread!");
|
||||
return false;
|
||||
}
|
||||
|
||||
dbus_bool_t success =
|
||||
dbus_connection_set_watch_functions(mConnection, AddWatchFunction,
|
||||
RemoveWatchFunction,
|
||||
ToggleWatchFunction, this, nullptr);
|
||||
NS_ENSURE_TRUE(success == TRUE, false);
|
||||
|
||||
dbus_connection_set_wakeup_main_function(mConnection, DBusWakeupFunction,
|
||||
this, nullptr);
|
||||
return true;
|
||||
DBusDispatchStatus dbusDispatchStatus;
|
||||
do {
|
||||
dbusDispatchStatus =
|
||||
dbus_connection_dispatch(mConnection->GetConnection());
|
||||
} while (dbusDispatchStatus == DBUS_DISPATCH_DATA_REMAINS);
|
||||
}
|
||||
|
||||
// Main task for polling the DBus system
|
||||
void
|
||||
DBusWatcher::OnFileCanWriteWithoutBlocking(int aFd)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
class DBusPollTask : public nsRunnable
|
||||
dbus_watch_handle(mWatch, DBUS_WATCH_WRITABLE);
|
||||
}
|
||||
|
||||
class WatchDBusConnectionTask : public Task
|
||||
{
|
||||
public:
|
||||
DBusPollTask(DBusWatcher* aDBusWatcher)
|
||||
: mDBusWatcher(aDBusWatcher)
|
||||
{ }
|
||||
WatchDBusConnectionTask(RawDBusConnection* aConnection)
|
||||
: mConnection(aConnection)
|
||||
{
|
||||
MOZ_ASSERT(mConnection);
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
void Run()
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
bool continueThread;
|
||||
|
||||
do {
|
||||
continueThread = mDBusWatcher->Poll();
|
||||
} while (continueThread);
|
||||
|
||||
mDBusWatcher->CleanUp();
|
||||
|
||||
nsIThread* thread;
|
||||
nsresult rv = NS_GetCurrentThread(&thread);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsRefPtr<nsIRunnable> runnable =
|
||||
NS_NewRunnableMethod(thread, &nsIThread::Shutdown);
|
||||
rv = NS_DispatchToMainThread(runnable);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
dbus_bool_t success =
|
||||
dbus_connection_set_watch_functions(mConnection->GetConnection(),
|
||||
DBusWatcher::AddWatchFunction,
|
||||
DBusWatcher::RemoveWatchFunction,
|
||||
DBusWatcher::ToggleWatchFunction,
|
||||
mConnection, nullptr);
|
||||
NS_ENSURE_TRUE_VOID(success == TRUE);
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<DBusWatcher> mDBusWatcher;
|
||||
RawDBusConnection* mConnection;
|
||||
};
|
||||
|
||||
static StaticRefPtr<DBusWatcher> gDBusWatcher;
|
||||
static StaticRefPtr<nsIThread> gDBusServiceThread;
|
||||
class DeleteDBusConnectionTask : public Task
|
||||
{
|
||||
public:
|
||||
DeleteDBusConnectionTask(RawDBusConnection* aConnection)
|
||||
: mConnection(aConnection)
|
||||
{
|
||||
MOZ_ASSERT(mConnection);
|
||||
}
|
||||
|
||||
// Startup/Shutdown utility functions
|
||||
void Run()
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
// This command closes the DBus connection and all instances of
|
||||
// DBusWatch will be removed and free'd.
|
||||
delete mConnection;
|
||||
}
|
||||
|
||||
private:
|
||||
RawDBusConnection* mConnection;
|
||||
};
|
||||
|
||||
// Startup/Shutdown utility functions
|
||||
|
||||
static RawDBusConnection* gDBusConnection;
|
||||
|
||||
bool
|
||||
StartDBus()
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
NS_ENSURE_TRUE(!gDBusWatcher, true);
|
||||
NS_ENSURE_TRUE(!gDBusConnection, true);
|
||||
|
||||
nsRefPtr<DBusWatcher> dbusWatcher(new DBusWatcher());
|
||||
|
||||
bool eventLoopStarted = dbusWatcher->Initialize();
|
||||
NS_ENSURE_TRUE(eventLoopStarted, false);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
if (!gDBusServiceThread) {
|
||||
nsIThread* dbusServiceThread;
|
||||
rv = NS_NewNamedThread("DBus Thread", &dbusServiceThread);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
gDBusServiceThread = dbusServiceThread;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
LOG("DBus Thread Starting\n");
|
||||
#endif
|
||||
|
||||
nsRefPtr<nsIRunnable> pollTask(new DBusPollTask(dbusWatcher));
|
||||
NS_ENSURE_TRUE(pollTask, false);
|
||||
|
||||
rv = gDBusServiceThread->Dispatch(pollTask, NS_DISPATCH_NORMAL);
|
||||
RawDBusConnection* connection = new RawDBusConnection();
|
||||
nsresult rv = connection->EstablishDBusConnection();
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
gDBusWatcher = dbusWatcher;
|
||||
XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
|
||||
new WatchDBusConnectionTask(connection));
|
||||
|
||||
gDBusConnection = connection;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -612,36 +282,32 @@ bool
|
|||
StopDBus()
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
NS_ENSURE_TRUE(gDBusServiceThread, true);
|
||||
NS_ENSURE_TRUE(gDBusConnection, true);
|
||||
|
||||
nsRefPtr<DBusWatcher> dbusWatcher(gDBusWatcher);
|
||||
gDBusWatcher = nullptr;
|
||||
RawDBusConnection* connection = gDBusConnection;
|
||||
gDBusConnection = nullptr;
|
||||
|
||||
if (dbusWatcher && !dbusWatcher->Stop()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
gDBusServiceThread = nullptr;
|
||||
XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
|
||||
new DeleteDBusConnectionTask(connection));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
nsresult
|
||||
DispatchToDBusThread(nsIRunnable* event)
|
||||
DispatchToDBusThread(Task* task)
|
||||
{
|
||||
nsRefPtr<nsIThread> dbusServiceThread(gDBusServiceThread);
|
||||
nsRefPtr<DBusWatcher> dbusWatcher(gDBusWatcher);
|
||||
|
||||
NS_ENSURE_TRUE(dbusServiceThread.get() && dbusWatcher.get(),
|
||||
NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
nsresult rv = dbusServiceThread->Dispatch(event, NS_DISPATCH_NORMAL);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
dbusWatcher->WakeUp();
|
||||
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, task);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
RawDBusConnection*
|
||||
GetDBusConnection()
|
||||
{
|
||||
NS_ENSURE_TRUE(gDBusConnection, nullptr);
|
||||
|
||||
return gDBusConnection;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,11 +9,13 @@
|
|||
|
||||
#include "nscore.h"
|
||||
|
||||
class nsIRunnable;
|
||||
class Task;
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
class RawDBusConnection;
|
||||
|
||||
/**
|
||||
* Starts the DBus thread, which handles returning signals to objects
|
||||
* that call asynchronous functions. This should be called from the
|
||||
|
@ -32,13 +34,21 @@ bool StartDBus();
|
|||
bool StopDBus();
|
||||
|
||||
/**
|
||||
* Dispatch an event to the DBus thread
|
||||
* Dispatch a task to the DBus I/O thread
|
||||
*
|
||||
* @param event An nsIRunnable to run in the DBus thread
|
||||
* @param task A task to run on the DBus I/O thread
|
||||
* @return NS_OK on success, or an error code otherwise
|
||||
*/
|
||||
nsresult
|
||||
DispatchToDBusThread(nsIRunnable* event);
|
||||
DispatchToDBusThread(Task* task);
|
||||
|
||||
/**
|
||||
* Returns the connection to the DBus server
|
||||
*
|
||||
* @return The DBus connection on success, or nullptr otherwise
|
||||
*/
|
||||
RawDBusConnection*
|
||||
GetDBusConnection(void);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <dbus/dbus.h>
|
||||
#include "base/message_loop.h"
|
||||
#include "mozilla/Monitor.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "DBusThread.h"
|
||||
|
@ -34,10 +35,14 @@ using namespace mozilla::ipc;
|
|||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
class DBusConnectionSendRunnableBase : public nsRunnable
|
||||
class DBusConnectionSendTaskBase : public Task
|
||||
{
|
||||
public:
|
||||
virtual ~DBusConnectionSendTaskBase()
|
||||
{ }
|
||||
|
||||
protected:
|
||||
DBusConnectionSendRunnableBase(DBusConnection* aConnection,
|
||||
DBusConnectionSendTaskBase(DBusConnection* aConnection,
|
||||
DBusMessage* aMessage)
|
||||
: mConnection(aConnection),
|
||||
mMessage(aMessage)
|
||||
|
@ -46,9 +51,6 @@ protected:
|
|||
MOZ_ASSERT(mMessage);
|
||||
}
|
||||
|
||||
virtual ~DBusConnectionSendRunnableBase()
|
||||
{ }
|
||||
|
||||
DBusConnection* mConnection;
|
||||
DBusMessageRefPtr mMessage;
|
||||
};
|
||||
|
@ -57,35 +59,33 @@ protected:
|
|||
// Sends a message and returns the message's serial number to the
|
||||
// disaptching thread. Only run it in DBus thread.
|
||||
//
|
||||
class DBusConnectionSendRunnable : public DBusConnectionSendRunnableBase
|
||||
class DBusConnectionSendTask : public DBusConnectionSendTaskBase
|
||||
{
|
||||
public:
|
||||
DBusConnectionSendRunnable(DBusConnection* aConnection,
|
||||
DBusConnectionSendTask(DBusConnection* aConnection,
|
||||
DBusMessage* aMessage)
|
||||
: DBusConnectionSendRunnableBase(aConnection, aMessage)
|
||||
: DBusConnectionSendTaskBase(aConnection, aMessage)
|
||||
{ }
|
||||
|
||||
NS_IMETHOD Run()
|
||||
virtual ~DBusConnectionSendTask()
|
||||
{ }
|
||||
|
||||
void Run() MOZ_OVERRIDE
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_ASSERT(MessageLoop::current());
|
||||
|
||||
dbus_bool_t success = dbus_connection_send(mConnection, mMessage, nullptr);
|
||||
|
||||
NS_ENSURE_TRUE(success == TRUE, NS_ERROR_FAILURE);
|
||||
|
||||
return NS_OK;
|
||||
dbus_bool_t success = dbus_connection_send(mConnection,
|
||||
mMessage,
|
||||
nullptr);
|
||||
NS_ENSURE_TRUE_VOID(success == TRUE);
|
||||
}
|
||||
|
||||
protected:
|
||||
~DBusConnectionSendRunnable()
|
||||
{ }
|
||||
};
|
||||
|
||||
//
|
||||
// Sends a message and executes a callback function for the reply. Only
|
||||
// run it in DBus thread.
|
||||
//
|
||||
class DBusConnectionSendWithReplyRunnable : public DBusConnectionSendRunnableBase
|
||||
class DBusConnectionSendWithReplyTask : public DBusConnectionSendTaskBase
|
||||
{
|
||||
private:
|
||||
class NotifyData
|
||||
|
@ -130,24 +130,27 @@ private:
|
|||
}
|
||||
|
||||
public:
|
||||
DBusConnectionSendWithReplyRunnable(DBusConnection* aConnection,
|
||||
DBusConnectionSendWithReplyTask(DBusConnection* aConnection,
|
||||
DBusMessage* aMessage,
|
||||
int aTimeout,
|
||||
DBusReplyCallback aCallback,
|
||||
void* aData)
|
||||
: DBusConnectionSendRunnableBase(aConnection, aMessage),
|
||||
: DBusConnectionSendTaskBase(aConnection, aMessage),
|
||||
mCallback(aCallback),
|
||||
mData(aData),
|
||||
mTimeout(aTimeout)
|
||||
{ }
|
||||
|
||||
NS_IMETHOD Run()
|
||||
virtual ~DBusConnectionSendWithReplyTask()
|
||||
{ }
|
||||
|
||||
void Run() MOZ_OVERRIDE
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_ASSERT(MessageLoop::current());
|
||||
|
||||
// Freed at end of Notify
|
||||
nsAutoPtr<NotifyData> data(new NotifyData(mCallback, mData));
|
||||
NS_ENSURE_TRUE(data, NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_TRUE_VOID(data);
|
||||
|
||||
DBusPendingCall* call;
|
||||
|
||||
|
@ -155,21 +158,15 @@ public:
|
|||
mMessage,
|
||||
&call,
|
||||
mTimeout);
|
||||
NS_ENSURE_TRUE(success == TRUE, NS_ERROR_FAILURE);
|
||||
NS_ENSURE_TRUE_VOID(success == TRUE);
|
||||
|
||||
success = dbus_pending_call_set_notify(call, Notify, data, nullptr);
|
||||
NS_ENSURE_TRUE(success == TRUE, NS_ERROR_FAILURE);
|
||||
NS_ENSURE_TRUE_VOID(success == TRUE);
|
||||
|
||||
data.forget();
|
||||
dbus_message_unref(mMessage);
|
||||
|
||||
return NS_OK;
|
||||
};
|
||||
|
||||
protected:
|
||||
~DBusConnectionSendWithReplyRunnable()
|
||||
{ }
|
||||
|
||||
private:
|
||||
DBusReplyCallback mCallback;
|
||||
void* mData;
|
||||
|
@ -202,7 +199,7 @@ nsresult RawDBusConnection::EstablishDBusConnection()
|
|||
}
|
||||
DBusError err;
|
||||
dbus_error_init(&err);
|
||||
mConnection = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
|
||||
mConnection = dbus_bus_get_private(DBUS_BUS_SYSTEM, &err);
|
||||
if (dbus_error_is_set(&err)) {
|
||||
dbus_error_free(&err);
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -214,14 +211,15 @@ nsresult RawDBusConnection::EstablishDBusConnection()
|
|||
void RawDBusConnection::ScopedDBusConnectionPtrTraits::release(DBusConnection* ptr)
|
||||
{
|
||||
if (ptr) {
|
||||
dbus_connection_close(ptr);
|
||||
dbus_connection_unref(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
bool RawDBusConnection::Send(DBusMessage* aMessage)
|
||||
{
|
||||
nsRefPtr<DBusConnectionSendRunnable> t(
|
||||
new DBusConnectionSendRunnable(mConnection, aMessage));
|
||||
DBusConnectionSendTask* t =
|
||||
new DBusConnectionSendTask(mConnection, aMessage);
|
||||
MOZ_ASSERT(t);
|
||||
|
||||
nsresult rv = DispatchToDBusThread(t);
|
||||
|
@ -241,9 +239,9 @@ bool RawDBusConnection::SendWithReply(DBusReplyCallback aCallback,
|
|||
int aTimeout,
|
||||
DBusMessage* aMessage)
|
||||
{
|
||||
nsRefPtr<nsIRunnable> t(
|
||||
new DBusConnectionSendWithReplyRunnable(mConnection, aMessage,
|
||||
aTimeout, aCallback, aData));
|
||||
DBusConnectionSendWithReplyTask* t =
|
||||
new DBusConnectionSendWithReplyTask(mConnection, aMessage, aTimeout,
|
||||
aCallback, aData);
|
||||
MOZ_ASSERT(t);
|
||||
|
||||
nsresult rv = DispatchToDBusThread(t);
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include <string>
|
||||
#include "nscore.h"
|
||||
#include "mozilla/Scoped.h"
|
||||
#include <mozilla/RefPtr.h>
|
||||
#include <mozilla/Mutex.h>
|
||||
|
||||
struct DBusConnection;
|
||||
|
@ -26,7 +25,7 @@ namespace ipc {
|
|||
|
||||
typedef void (*DBusReplyCallback)(DBusMessage*, void*);
|
||||
|
||||
class RawDBusConnection : public AtomicRefCounted<RawDBusConnection>
|
||||
class RawDBusConnection
|
||||
{
|
||||
struct ScopedDBusConnectionPtrTraits : ScopedFreePtrTraits<DBusConnection>
|
||||
{
|
||||
|
|
|
@ -215,4 +215,41 @@ nsFrame::PrintDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
PrintDisplayListTo(aBuilder, aList, aFile, aDumpHtml);
|
||||
}
|
||||
|
||||
static void
|
||||
PrintDisplayListSetItem(nsDisplayListBuilder* aBuilder,
|
||||
const char* aItemName,
|
||||
const nsDisplayList& aList,
|
||||
FILE* aFile,
|
||||
bool aDumpHtml)
|
||||
{
|
||||
if (aDumpHtml) {
|
||||
fprintf_stderr(aFile, "<li>");
|
||||
}
|
||||
fprintf_stderr(aFile, "%s", aItemName);
|
||||
PrintDisplayListTo(aBuilder, aList, aFile, aDumpHtml);
|
||||
if (aDumpHtml) {
|
||||
fprintf_stderr(aFile, "</li>");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsFrame::PrintDisplayListSet(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayListSet& aSet,
|
||||
FILE *aFile,
|
||||
bool aDumpHtml)
|
||||
{
|
||||
if (aDumpHtml) {
|
||||
fprintf_stderr(aFile, "<ul>");
|
||||
}
|
||||
PrintDisplayListSetItem(aBuilder, "[BorderBackground]", *(aSet.BorderBackground()), aFile, aDumpHtml);
|
||||
PrintDisplayListSetItem(aBuilder, "[BlockBorderBackgrounds]", *(aSet.BlockBorderBackgrounds()), aFile, aDumpHtml);
|
||||
PrintDisplayListSetItem(aBuilder, "[Floats]", *(aSet.Floats()), aFile, aDumpHtml);
|
||||
PrintDisplayListSetItem(aBuilder, "[PositionedDescendants]", *(aSet.PositionedDescendants()), aFile, aDumpHtml);
|
||||
PrintDisplayListSetItem(aBuilder, "[Outlines]", *(aSet.Outlines()), aFile, aDumpHtml);
|
||||
PrintDisplayListSetItem(aBuilder, "[Content]", *(aSet.Content()), aFile, aDumpHtml);
|
||||
if (aDumpHtml) {
|
||||
fprintf_stderr(aFile, "</ul>");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -713,6 +713,10 @@ public:
|
|||
const nsDisplayList& aList,
|
||||
FILE* aFile = stdout,
|
||||
bool aDumpHtml = false);
|
||||
static void PrintDisplayListSet(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayListSet& aList,
|
||||
FILE* aFile = stdout,
|
||||
bool aDumpHtml = false);
|
||||
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
[include:dom/mobilemessage/tests/xpcshell.ini]
|
||||
[include:dom/network/tests/unit_stats/xpcshell.ini]
|
||||
[include:dom/system/gonk/tests/xpcshell.ini]
|
||||
[include:dom/wappush/tests/xpcshell.ini]
|
||||
[include:toolkit/devtools/apps/tests/unit/xpcshell.ini]
|
||||
[include:toolkit/devtools/debugger/tests/unit/xpcshell.ini]
|
||||
[include:toolkit/devtools/sourcemap/tests/unit/xpcshell.ini]
|
||||
|
|
|
@ -64,6 +64,7 @@ HwcComposer2D::HwcComposer2D()
|
|||
, mColorFill(false)
|
||||
, mRBSwapSupport(false)
|
||||
, mPrevRetireFence(-1)
|
||||
, mPrepared(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -451,7 +452,6 @@ HwcComposer2D::TryHwComposition()
|
|||
|
||||
if (!(fbsurface && fbsurface->lastHandle)) {
|
||||
LOGD("H/W Composition failed. FBSurface not initialized.");
|
||||
mList->numHwLayers = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -460,7 +460,6 @@ HwcComposer2D::TryHwComposition()
|
|||
if (idx >= mMaxLayerCount) {
|
||||
if (!ReallocLayerList() || idx >= mMaxLayerCount) {
|
||||
LOGE("TryHwComposition failed! Could not add FB layer");
|
||||
mList->numHwLayers = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -495,7 +494,6 @@ HwcComposer2D::TryHwComposition()
|
|||
|
||||
// No composition on FB layer, so closing releaseFenceFd
|
||||
close(mList->hwLayers[idx].releaseFenceFd);
|
||||
mList->numHwLayers = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -515,7 +513,7 @@ HwcComposer2D::Render(EGLDisplay dpy, EGLSurface sur)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (mList->numHwLayers != 0) {
|
||||
if (mPrepared) {
|
||||
// No mHwc prepare, if already prepared in current draw cycle
|
||||
mList->hwLayers[mList->numHwLayers - 1].handle = fbsurface->lastHandle;
|
||||
mList->hwLayers[mList->numHwLayers - 1].acquireFenceFd = fbsurface->lastFenceFD;
|
||||
|
@ -535,7 +533,6 @@ HwcComposer2D::Render(EGLDisplay dpy, EGLSurface sur)
|
|||
Commit();
|
||||
|
||||
GetGonkDisplay()->SetFBReleaseFd(mList->hwLayers[mList->numHwLayers - 1].releaseFenceFd);
|
||||
mList->numHwLayers = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -566,7 +563,11 @@ HwcComposer2D::Prepare(buffer_handle_t fbHandle, int fence)
|
|||
mList->hwLayers[idx].releaseFenceFd = -1;
|
||||
mList->hwLayers[idx].planeAlpha = 0xFF;
|
||||
|
||||
if (mPrepared) {
|
||||
LOGE("Multiple hwc prepare calls!");
|
||||
}
|
||||
mHwc->prepare(mHwc, HWC_NUM_DISPLAY_TYPES, displays);
|
||||
mPrepared = true;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -609,8 +610,19 @@ HwcComposer2D::Commit()
|
|||
}
|
||||
}
|
||||
|
||||
mPrepared = false;
|
||||
return !err;
|
||||
}
|
||||
|
||||
void
|
||||
HwcComposer2D::Reset()
|
||||
{
|
||||
LOGD("hwcomposer is already prepared, reset with null set");
|
||||
hwc_display_contents_1_t *displays[HWC_NUM_DISPLAY_TYPES] = { nullptr };
|
||||
displays[HWC_DISPLAY_PRIMARY] = nullptr;
|
||||
mHwc->set(mHwc, HWC_DISPLAY_PRIMARY, displays);
|
||||
mPrepared = false;
|
||||
}
|
||||
#else
|
||||
bool
|
||||
HwcComposer2D::TryHwComposition()
|
||||
|
@ -623,6 +635,12 @@ HwcComposer2D::Render(EGLDisplay dpy, EGLSurface sur)
|
|||
{
|
||||
return GetGonkDisplay()->SwapBuffers(dpy, sur);
|
||||
}
|
||||
|
||||
void
|
||||
HwcComposer2D::Reset()
|
||||
{
|
||||
mPrepared = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
|
@ -640,6 +658,10 @@ HwcComposer2D::TryRender(Layer* aRoot,
|
|||
mHwcLayerMap.Clear();
|
||||
}
|
||||
|
||||
if (mPrepared) {
|
||||
Reset();
|
||||
}
|
||||
|
||||
// XXX: The clear() below means all rect vectors will be have to be
|
||||
// reallocated. We may want to avoid this if possible
|
||||
mVisibleRegions.clear();
|
||||
|
@ -651,9 +673,6 @@ HwcComposer2D::TryRender(Layer* aRoot,
|
|||
aGLWorldTransform))
|
||||
{
|
||||
LOGD("Render aborted. Nothing was drawn to the screen");
|
||||
if (mList) {
|
||||
mList->numHwLayers = 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -63,6 +63,7 @@ public:
|
|||
bool Render(EGLDisplay dpy, EGLSurface sur);
|
||||
|
||||
private:
|
||||
void Reset();
|
||||
void Prepare(buffer_handle_t fbHandle, int fence);
|
||||
bool Commit();
|
||||
bool TryHwComposition();
|
||||
|
@ -84,6 +85,7 @@ private:
|
|||
nsTArray<int> mPrevReleaseFds;
|
||||
int mPrevRetireFence;
|
||||
nsTArray<layers::LayerComposite*> mHwcLayerMap;
|
||||
bool mPrepared;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
Загрузка…
Ссылка в новой задаче