This commit is contained in:
Wes Kocher 2013-12-12 18:02:54 -08:00
Родитель c172b7092a 2316157f59
Коммит c1b0f6e109
35 изменённых файлов: 654 добавлений и 760 удалений

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

@ -18,7 +18,4 @@
# Modifying this file will now automatically clobber the buildbot machines \o/ # Modifying this file will now automatically clobber the buildbot machines \o/
# #
Bug 934646 needs a clobber -- the icon resources previously copied Bug 946047 - Windows needs a clobber for webidl changes.
into $OBJDIR/mobile/android/base/res will conflict with those in
$BRANDING_DIRECTORY/res.

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

@ -7,6 +7,9 @@
pref("toolkit.defaultChromeURI", "chrome://browser/content/shell.html"); pref("toolkit.defaultChromeURI", "chrome://browser/content/shell.html");
pref("browser.chromeURL", "chrome://browser/content/"); 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. // Device pixel to CSS px ratio, in percent. Set to -1 to calculate based on display density.
pref("browser.viewport.scaleRatio", -1); pref("browser.viewport.scaleRatio", -1);

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

@ -1,4 +1,4 @@
{ {
"revision": "5bfef5faac50d14e055f642a44ed2df8483fb2fe", "revision": "9271d94f35a54995e4442da711e51cff0244741d",
"repo_path": "/integration/gaia-central" "repo_path": "/integration/gaia-central"
} }

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

@ -148,9 +148,7 @@ VideoTrackEncoder::NotifyQueuedTrackChanges(MediaStreamGraph* aGraph,
VideoChunk chunk = *iter; VideoChunk chunk = *iter;
if (!chunk.IsNull()) { if (!chunk.IsNull()) {
gfxIntSize imgsize = chunk.mFrame.GetImage()->GetSize(); gfxIntSize imgsize = chunk.mFrame.GetImage()->GetSize();
int width = (imgsize.width + 1) / 2 * 2; nsresult rv = Init(imgsize.width, imgsize.height, aTrackRate);
int height = (imgsize.height + 1) / 2 * 2;
nsresult rv = Init(width, height, aTrackRate);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
LOG("[VideoTrackEncoder]: Fail to initialize the encoder!"); LOG("[VideoTrackEncoder]: Fail to initialize the encoder!");
NotifyCancel(); NotifyCancel();

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

@ -41,6 +41,25 @@ using namespace mozilla;
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 class OmxDecoderProcessCachedDataTask : public Task
{ {
public: public:
@ -53,7 +72,13 @@ public:
{ {
MOZ_ASSERT(!NS_IsMainThread()); MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(mOmxDecoder.get()); 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: private:
@ -292,6 +317,8 @@ OmxDecoder::OmxDecoder(MediaResource *aResource,
OmxDecoder::~OmxDecoder() OmxDecoder::~OmxDecoder()
{ {
MOZ_ASSERT(NS_IsMainThread());
ReleaseMediaResources(); ReleaseMediaResources();
// unregister AMessage handler from ALooper. // unregister AMessage handler from ALooper.
@ -398,7 +425,7 @@ bool OmxDecoder::TryLoad() {
// Feed MP3 parser with cached data. Local files will be fully // Feed MP3 parser with cached data. Local files will be fully
// cached already, network streams will update with sucessive // cached already, network streams will update with sucessive
// calls to NotifyDataArrived. // calls to NotifyDataArrived.
if (ProcessCachedData(0, true)) { if (ProcessCachedData(0, true) >= 0) {
durationUs = mMP3FrameParser.GetDuration(); durationUs = mMP3FrameParser.GetDuration();
if (durationUs > totalDurationUs) { if (durationUs > totalDurationUs) {
totalDurationUs = durationUs; totalDurationUs = durationUs;
@ -1017,7 +1044,7 @@ void OmxDecoder::ReleaseAllPendingVideoBuffersLocked()
releasingVideoBuffers.clear(); 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 // We read data in chunks of 32 KiB. We can reduce this
// value if media, such as sdcards, is too slow. // value if media, such as sdcards, is too slow.
@ -1030,10 +1057,10 @@ bool OmxDecoder::ProcessCachedData(int64_t aOffset, bool aWaitForCompletion)
MOZ_ASSERT(mResource); MOZ_ASSERT(mResource);
int64_t resourceLength = mResource->GetCachedDataEnd(0); int64_t resourceLength = mResource->GetCachedDataEnd(0);
NS_ENSURE_TRUE(resourceLength >= 0, false); NS_ENSURE_TRUE(resourceLength >= 0, -1);
if (aOffset >= resourceLength) { 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); 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]); nsAutoArrayPtr<char> buffer(new char[bufferLength]);
nsresult rv = mResource->ReadFromCache(buffer.get(), aOffset, bufferLength); nsresult rv = mResource->ReadFromCache(buffer.get(), aOffset, bufferLength);
NS_ENSURE_SUCCESS(rv, false); NS_ENSURE_SUCCESS(rv, -1);
nsRefPtr<OmxDecoderNotifyDataArrivedRunnable> runnable( nsRefPtr<OmxDecoderNotifyDataArrivedRunnable> runnable(
new OmxDecoderNotifyDataArrivedRunnable(this, new OmxDecoderNotifyDataArrivedRunnable(this,
@ -1051,11 +1078,11 @@ bool OmxDecoder::ProcessCachedData(int64_t aOffset, bool aWaitForCompletion)
resourceLength)); resourceLength));
rv = NS_DispatchToMainThread(runnable.get()); rv = NS_DispatchToMainThread(runnable.get());
NS_ENSURE_SUCCESS(rv, false); NS_ENSURE_SUCCESS(rv, -1);
if (aWaitForCompletion) { if (aWaitForCompletion) {
runnable->WaitForCompletion(); runnable->WaitForCompletion();
} }
return true; return resourceLength - aOffset - bufferLength;
} }

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

@ -238,7 +238,7 @@ public:
// Called on ALooper thread. // Called on ALooper thread.
void onMessageReceived(const sp<AMessage> &msg); 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()); 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 } // namespace mozilla

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

@ -32,10 +32,6 @@ public:
virtual MediaDecoder* Clone() MOZ_OVERRIDE; virtual MediaDecoder* Clone() MOZ_OVERRIDE;
virtual MediaDecoderStateMachine* CreateStateMachine() 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 } // namespace mozilla

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

@ -289,4 +289,44 @@ nsresult RtspOmxReader::Seek(int64_t aTime, int64_t aStartTime,
return MediaOmxReader::Seek(aTime, aStartTime, aEndTime, aCurrentTime); 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 } // namespace mozilla

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

@ -71,6 +71,10 @@ public:
return nullptr; return nullptr;
} }
virtual void OnDecodeThreadStart() MOZ_OVERRIDE;
virtual void OnDecodeThreadFinish() MOZ_OVERRIDE;
private: private:
// A pointer to RtspMediaResource for calling the Rtsp specific function. // A pointer to RtspMediaResource for calling the Rtsp specific function.
// The lifetime of mRtspResource is controlled by MediaDecoder. MediaDecoder // 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_NONE "00:00:00:00:00:00"
#define BLUETOOTH_ADDRESS_BYTES 6 #define BLUETOOTH_ADDRESS_BYTES 6
// Bluetooth stack internal error, such as I/O error
#define ERR_INTERNAL_ERROR "InternalError"
BEGIN_BLUETOOTH_NAMESPACE BEGIN_BLUETOOTH_NAMESPACE
enum BluetoothSocketType { enum BluetoothSocketType {

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

@ -167,12 +167,6 @@ static const char* sBluetoothDBusSignals[] =
"type='signal',interface='org.bluez.Control'" "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. // Only A2DP and HID are authorized.
static nsTArray<BluetoothServiceClass> sAuthorizedServiceClass; static nsTArray<BluetoothServiceClass> sAuthorizedServiceClass;
@ -497,6 +491,14 @@ RunDBusCallback(DBusMessage* aMsg, void* aBluetoothReplyRunnable,
nsAutoString replyError; nsAutoString replyError;
BluetoothValue v; BluetoothValue v;
aFunc(aMsg, nullptr, v, replyError); 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); DispatchBluetoothReply(replyRunnable, v, replyError);
} }
@ -966,9 +968,9 @@ AppendDeviceName(BluetoothSignal& aSignal)
nsString devicePath = arr[0].value().get_nsString(); 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__); BT_WARNING("%s: DBus connection has been closed.", __FUNCTION__);
return; return;
} }
@ -977,7 +979,7 @@ AppendDeviceName(BluetoothSignal& aSignal)
new AppendDeviceNameReplyHandler(nsCString(DBUS_DEVICE_IFACE), new AppendDeviceNameReplyHandler(nsCString(DBUS_DEVICE_IFACE),
devicePath, aSignal); devicePath, aSignal);
bool success = threadConnection->SendWithReply( bool success = connection->SendWithReply(
AppendDeviceNameReplyHandler::Callback, handler.get(), 1000, AppendDeviceNameReplyHandler::Callback, handler.get(), 1000,
NS_ConvertUTF16toUTF8(devicePath).get(), DBUS_DEVICE_IFACE, NS_ConvertUTF16toUTF8(devicePath).get(), DBUS_DEVICE_IFACE,
"GetProperties", DBUS_TYPE_INVALID); "GetProperties", DBUS_TYPE_INVALID);
@ -1211,9 +1213,9 @@ public:
return; return;
} }
nsRefPtr<RawDBusConnection> threadConnection = gThreadConnection; RawDBusConnection* connection = GetDBusConnection();
if (!threadConnection.get()) { if (!connection) {
BT_WARNING("%s: DBus connection has been closed.", __FUNCTION__); BT_WARNING("%s: DBus connection has been closed.", __FUNCTION__);
return; return;
} }
@ -1221,7 +1223,7 @@ public:
// There is no "RegisterAgent" function defined in device interface. // There is no "RegisterAgent" function defined in device interface.
// When we call "CreatePairedDevice", it will do device agent registration // When we call "CreatePairedDevice", it will do device agent registration
// for us. (See maemo.org/api_refs/5.0/beta/bluez/adapter.html) // 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, KEY_REMOTE_AGENT,
mAgentVTable, mAgentVTable,
nullptr)) { nullptr)) {
@ -1297,9 +1299,9 @@ private:
const char* agentPath = KEY_LOCAL_AGENT; const char* agentPath = KEY_LOCAL_AGENT;
const char* capabilities = B2G_AGENT_CAPABILITIES; 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__); BT_WARNING("%s: DBus connection has been closed.", __FUNCTION__);
return false; return false;
} }
@ -1310,7 +1312,7 @@ private:
// signal will be passed to local agent. If we start pairing process with // signal will be passed to local agent. If we start pairing process with
// calling CreatePairedDevice, we'll get signal which should be passed to // calling CreatePairedDevice, we'll get signal which should be passed to
// device agent. // device agent.
if (!dbus_connection_register_object_path(threadConnection->GetConnection(), if (!dbus_connection_register_object_path(connection->GetConnection(),
KEY_LOCAL_AGENT, KEY_LOCAL_AGENT,
aAgentVTable, aAgentVTable,
nullptr)) { nullptr)) {
@ -1324,7 +1326,7 @@ private:
MOZ_ASSERT(handler.get()); MOZ_ASSERT(handler.get());
MOZ_ASSERT(!sAdapterPath.IsEmpty()); MOZ_ASSERT(!sAdapterPath.IsEmpty());
bool success = threadConnection->SendWithReply( bool success = connection->SendWithReply(
RegisterAgentReplyHandler::Callback, handler.get(), -1, RegisterAgentReplyHandler::Callback, handler.get(), -1,
NS_ConvertUTF16toUTF8(sAdapterPath).get(), NS_ConvertUTF16toUTF8(sAdapterPath).get(),
DBUS_ADAPTER_IFACE, "RegisterAgent", DBUS_ADAPTER_IFACE, "RegisterAgent",
@ -1359,9 +1361,9 @@ public:
MOZ_ASSERT(NS_IsMainThread()); 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__); BT_WARNING("%s: DBus connection has been closed.", __FUNCTION__);
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
@ -1375,7 +1377,7 @@ public:
const dbus_uint32_t* services = sServices; const dbus_uint32_t* services = sServices;
bool success = threadConnection->SendWithReply( bool success = connection->SendWithReply(
DBusReplyHandler::Callback, handler.get(), -1, DBusReplyHandler::Callback, handler.get(), -1,
NS_ConvertUTF16toUTF8(sAdapterPath).get(), NS_ConvertUTF16toUTF8(sAdapterPath).get(),
DBUS_ADAPTER_IFACE, "AddReservedServiceRecords", DBUS_ADAPTER_IFACE, "AddReservedServiceRecords",
@ -1719,7 +1721,7 @@ OnDefaultAdapterReply(DBusMessage* aReply, void* aData)
bool bool
BluetoothDBusService::IsReady() BluetoothDBusService::IsReady()
{ {
if (!IsEnabled() || !mConnection || !gThreadConnection || IsToggling()) { if (!IsEnabled() || !GetDBusConnection() || IsToggling()) {
BT_WARNING("Bluetooth service is not ready yet!"); BT_WARNING("Bluetooth service is not ready yet!");
return false; return false;
} }
@ -1737,25 +1739,8 @@ BluetoothDBusService::StartInternal()
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
if (mConnection) { RawDBusConnection* connection = GetDBusConnection();
return NS_OK; MOZ_ASSERT(connection);
}
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;
}
DBusError err; DBusError err;
dbus_error_init(&err); dbus_error_init(&err);
@ -1765,7 +1750,7 @@ BluetoothDBusService::StartInternal()
// signals we want, register all of them in this thread at startup. // signals we want, register all of them in this thread at startup.
// The event handler will sort the destinations out as needed. // The event handler will sort the destinations out as needed.
for (uint32_t i = 0; i < ArrayLength(sBluetoothDBusSignals); ++i) { for (uint32_t i = 0; i < ArrayLength(sBluetoothDBusSignals); ++i) {
dbus_bus_add_match(mConnection->GetConnection(), dbus_bus_add_match(connection->GetConnection(),
sBluetoothDBusSignals[i], sBluetoothDBusSignals[i],
&err); &err);
if (dbus_error_is_set(&err)) { if (dbus_error_is_set(&err)) {
@ -1774,7 +1759,7 @@ BluetoothDBusService::StartInternal()
} }
// Add a filter for all incoming messages_base // 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)) { EventFilter, nullptr, nullptr)) {
BT_WARNING("Cannot create DBus Event Filter for DBus Thread!"); BT_WARNING("Cannot create DBus Event Filter for DBus Thread!");
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
@ -1792,11 +1777,11 @@ BluetoothDBusService::StartInternal()
* explicitly here. * explicitly here.
*/ */
if (sAdapterPath.IsEmpty()) { if (sAdapterPath.IsEmpty()) {
bool success = mConnection->SendWithReply(OnDefaultAdapterReply, nullptr, bool success = connection->SendWithReply(OnDefaultAdapterReply, nullptr,
1000, "/", 1000, "/",
DBUS_MANAGER_IFACE, DBUS_MANAGER_IFACE,
"DefaultAdapter", "DefaultAdapter",
DBUS_TYPE_INVALID); DBUS_TYPE_INVALID);
if (!success) { if (!success) {
BT_WARNING("Failed to query default adapter!"); BT_WARNING("Failed to query default adapter!");
} }
@ -1826,15 +1811,16 @@ BluetoothDBusService::StopInternal()
} }
} }
if (!mConnection) { RawDBusConnection* connection = GetDBusConnection();
StopDBus();
if (!connection) {
return NS_OK; return NS_OK;
} }
DBusError err; DBusError err;
dbus_error_init(&err); dbus_error_init(&err);
for (uint32_t i = 0; i < ArrayLength(sBluetoothDBusSignals); ++i) { for (uint32_t i = 0; i < ArrayLength(sBluetoothDBusSignals); ++i) {
dbus_bus_remove_match(mConnection->GetConnection(), dbus_bus_remove_match(connection->GetConnection(),
sBluetoothDBusSignals[i], sBluetoothDBusSignals[i],
&err); &err);
if (dbus_error_is_set(&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); EventFilter, nullptr);
if (!dbus_connection_unregister_object_path(gThreadConnection->GetConnection(), if (!dbus_connection_unregister_object_path(connection->GetConnection(),
KEY_LOCAL_AGENT)) { KEY_LOCAL_AGENT)) {
BT_WARNING("%s: Can't unregister object path %s for agent!", BT_WARNING("%s: Can't unregister object path %s for agent!",
__FUNCTION__, KEY_LOCAL_AGENT); __FUNCTION__, KEY_LOCAL_AGENT);
} }
if (!dbus_connection_unregister_object_path(gThreadConnection->GetConnection(), if (!dbus_connection_unregister_object_path(connection->GetConnection(),
KEY_REMOTE_AGENT)) { KEY_REMOTE_AGENT)) {
BT_WARNING("%s: Can't unregister object path %s for agent!", BT_WARNING("%s: Can't unregister object path %s for agent!",
__FUNCTION__, KEY_REMOTE_AGENT); __FUNCTION__, KEY_REMOTE_AGENT);
} }
mConnection = nullptr;
gThreadConnection = nullptr;
// unref stored DBusMessages before clear the hashtable // unref stored DBusMessages before clear the hashtable
sPairingReqTable->EnumerateRead(UnrefDBusMessages, nullptr); sPairingReqTable->EnumerateRead(UnrefDBusMessages, nullptr);
sPairingReqTable->Clear(); sPairingReqTable->Clear();
@ -1943,14 +1926,14 @@ protected:
// Acquire another reference to this reply handler // Acquire another reference to this reply handler
nsRefPtr<DefaultAdapterPathReplyHandler> handler = this; 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."); aReplyError = NS_LITERAL_STRING("DBus connection has been closed.");
return false; return false;
} }
bool success = threadConnection->SendWithReply( bool success = connection->SendWithReply(
DefaultAdapterPathReplyHandler::Callback, handler.get(), 1000, DefaultAdapterPathReplyHandler::Callback, handler.get(), 1000,
NS_ConvertUTF16toUTF8(mAdapterPath).get(), NS_ConvertUTF16toUTF8(mAdapterPath).get(),
DBUS_ADAPTER_IFACE, "GetProperties", DBUS_TYPE_INVALID); DBUS_ADAPTER_IFACE, "GetProperties", DBUS_TYPE_INVALID);
@ -2011,7 +1994,10 @@ BluetoothDBusService::GetDefaultAdapterPathInternal(
nsRefPtr<DefaultAdapterPathReplyHandler> handler = nsRefPtr<DefaultAdapterPathReplyHandler> handler =
new DefaultAdapterPathReplyHandler(aRunnable); new DefaultAdapterPathReplyHandler(aRunnable);
bool success = mConnection->SendWithReply( RawDBusConnection* connection = GetDBusConnection();
MOZ_ASSERT(connection);
bool success = connection->SendWithReply(
DefaultAdapterPathReplyHandler::Callback, DefaultAdapterPathReplyHandler::Callback,
handler.get(), 1000, handler.get(), 1000,
"/", DBUS_MANAGER_IFACE, "DefaultAdapter", "/", DBUS_MANAGER_IFACE, "DefaultAdapter",
@ -2056,7 +2042,10 @@ BluetoothDBusService::SendDiscoveryMessage(const char* aMessageName,
nsRefPtr<BluetoothReplyRunnable> runnable(aRunnable); nsRefPtr<BluetoothReplyRunnable> runnable(aRunnable);
bool success = mConnection->SendWithReply( RawDBusConnection* connection = GetDBusConnection();
MOZ_ASSERT(connection);
bool success = connection->SendWithReply(
OnSendDiscoveryMessageReply, OnSendDiscoveryMessageReply,
static_cast<void*>(aRunnable), -1, static_cast<void*>(aRunnable), -1,
NS_ConvertUTF16toUTF8(sAdapterPath).get(), NS_ConvertUTF16toUTF8(sAdapterPath).get(),
@ -2096,13 +2085,12 @@ BluetoothDBusService::SendAsyncDBusMessage(const nsAString& aObjectPath,
DBusReplyCallback aCallback) DBusReplyCallback aCallback)
{ {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mConnection);
MOZ_ASSERT(IsEnabled()); MOZ_ASSERT(IsEnabled());
MOZ_ASSERT(aCallback); MOZ_ASSERT(aCallback);
MOZ_ASSERT(!aObjectPath.IsEmpty()); MOZ_ASSERT(!aObjectPath.IsEmpty());
MOZ_ASSERT(aInterface); MOZ_ASSERT(aInterface);
NS_ENSURE_TRUE(mConnection, NS_ERROR_FAILURE); NS_ENSURE_TRUE(GetDBusConnection(), NS_ERROR_FAILURE);
nsAutoPtr<BluetoothServiceClass> serviceClass(new BluetoothServiceClass()); nsAutoPtr<BluetoothServiceClass> serviceClass(new BluetoothServiceClass());
if (!strcmp(aInterface, DBUS_SINK_IFACE)) { if (!strcmp(aInterface, DBUS_SINK_IFACE)) {
@ -2114,7 +2102,10 @@ BluetoothDBusService::SendAsyncDBusMessage(const nsAString& aObjectPath,
return NS_ERROR_FAILURE; 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, aCallback, static_cast<void*>(serviceClass.forget()), -1,
NS_ConvertUTF16toUTF8(aObjectPath).get(), NS_ConvertUTF16toUTF8(aObjectPath).get(),
aInterface, NS_ConvertUTF16toUTF8(aMessage).get(), aInterface, NS_ConvertUTF16toUTF8(aMessage).get(),
@ -2259,16 +2250,16 @@ protected:
mObjectPath = GetObjectPathFromAddress(sAdapterPath, mObjectPath = GetObjectPathFromAddress(sAdapterPath,
mDeviceAddresses[mProcessedDeviceAddresses]); mDeviceAddresses[mProcessedDeviceAddresses]);
nsRefPtr<RawDBusConnection> threadConnection = gThreadConnection; RawDBusConnection* connection = GetDBusConnection();
if (!threadConnection.get()) { if (!connection) {
BT_WARNING("%s: DBus connection has been closed.", __FUNCTION__); BT_WARNING("%s: DBus connection has been closed.", __FUNCTION__);
return false; return false;
} }
nsRefPtr<BluetoothArrayOfDevicePropertiesReplyHandler> handler = this; nsRefPtr<BluetoothArrayOfDevicePropertiesReplyHandler> handler = this;
bool success = threadConnection->SendWithReply( bool success = connection->SendWithReply(
BluetoothArrayOfDevicePropertiesReplyHandler::Callback, BluetoothArrayOfDevicePropertiesReplyHandler::Callback,
handler.get(), 1000, handler.get(), 1000,
NS_ConvertUTF16toUTF8(mObjectPath).get(), NS_ConvertUTF16toUTF8(mObjectPath).get(),
@ -2427,10 +2418,13 @@ BluetoothDBusService::SetProperty(BluetoothObjectType aType,
nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable; nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
RawDBusConnection* connection = GetDBusConnection();
MOZ_ASSERT(connection);
// msg is unref'd as part of SendWithReply // msg is unref'd as part of SendWithReply
bool success = mConnection->SendWithReply(GetVoidCallback, bool success = connection->SendWithReply(GetVoidCallback,
(void*)aRunnable, (void*)aRunnable,
1000, msg); 1000, msg);
if (!success) { if (!success) {
BT_WARNING("SendWithReply failed"); BT_WARNING("SendWithReply failed");
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
@ -2468,9 +2462,12 @@ BluetoothDBusService::CreatePairedDeviceInternal(
nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable; nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
MOZ_ASSERT(!sAdapterPath.IsEmpty()); MOZ_ASSERT(!sAdapterPath.IsEmpty());
RawDBusConnection* connection = GetDBusConnection();
MOZ_ASSERT(connection);
// Then send CreatePairedDevice, it will register a temp device agent then // Then send CreatePairedDevice, it will register a temp device agent then
// unregister it after pairing process is over // unregister it after pairing process is over
bool ret = mConnection->SendWithReply( bool ret = connection->SendWithReply(
GetObjectPathCallback, (void*)runnable, aTimeout, GetObjectPathCallback, (void*)runnable, aTimeout,
NS_ConvertUTF16toUTF8(sAdapterPath).get(), NS_ConvertUTF16toUTF8(sAdapterPath).get(),
DBUS_ADAPTER_IFACE, DBUS_ADAPTER_IFACE,
@ -2523,7 +2520,10 @@ BluetoothDBusService::RemoveDeviceInternal(const nsAString& aDeviceAddress,
nsRefPtr<BluetoothReplyRunnable> runnable(aRunnable); 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, OnRemoveDeviceReply, static_cast<void*>(runnable.get()), -1,
NS_ConvertUTF16toUTF8(sAdapterPath).get(), NS_ConvertUTF16toUTF8(sAdapterPath).get(),
DBUS_ADAPTER_IFACE, "RemoveDevice", DBUS_ADAPTER_IFACE, "RemoveDevice",
@ -2574,7 +2574,9 @@ BluetoothDBusService::SetPinCodeInternal(const nsAString& aDeviceAddress,
errorStr.AssignLiteral("Couldn't append arguments to dbus message."); errorStr.AssignLiteral("Couldn't append arguments to dbus message.");
result = false; result = false;
} else { } else {
result = mConnection->Send(reply); RawDBusConnection* connection = GetDBusConnection();
MOZ_ASSERT(connection);
result = connection->Send(reply);
} }
dbus_message_unref(msg); dbus_message_unref(msg);
@ -2620,7 +2622,9 @@ BluetoothDBusService::SetPasskeyInternal(const nsAString& aDeviceAddress,
errorStr.AssignLiteral("Couldn't append arguments to dbus message."); errorStr.AssignLiteral("Couldn't append arguments to dbus message.");
result = false; result = false;
} else { } else {
result = mConnection->Send(reply); RawDBusConnection* connection = GetDBusConnection();
MOZ_ASSERT(connection);
result = connection->Send(reply);
} }
dbus_message_unref(msg); dbus_message_unref(msg);
@ -2664,7 +2668,10 @@ BluetoothDBusService::SetPairingConfirmationInternal(
return false; return false;
} }
bool result = mConnection->Send(reply); RawDBusConnection* connection = GetDBusConnection();
MOZ_ASSERT(connection);
bool result = connection->Send(reply);
if (!result) { if (!result) {
errorStr.AssignLiteral("Can't send message!"); errorStr.AssignLiteral("Can't send message!");
} }
@ -2907,7 +2914,10 @@ BluetoothDBusService::GetServiceChannel(const nsAString& aDeviceAddress,
nsRefPtr<OnGetServiceChannelReplyHandler> handler = nsRefPtr<OnGetServiceChannelReplyHandler> handler =
new OnGetServiceChannelReplyHandler(objectPath, aServiceUUID, aManager); new OnGetServiceChannelReplyHandler(objectPath, aServiceUUID, aManager);
bool success = mConnection->SendWithReply( RawDBusConnection* connection = GetDBusConnection();
MOZ_ASSERT(connection);
bool success = connection->SendWithReply(
OnGetServiceChannelReplyHandler::Callback, handler, -1, OnGetServiceChannelReplyHandler::Callback, handler, -1,
NS_ConvertUTF16toUTF8(objectPath).get(), NS_ConvertUTF16toUTF8(objectPath).get(),
DBUS_DEVICE_IFACE, "GetServiceAttributeValue", DBUS_DEVICE_IFACE, "GetServiceAttributeValue",
@ -2952,7 +2962,6 @@ BluetoothDBusService::UpdateSdpRecords(const nsAString& aDeviceAddress,
MOZ_ASSERT(!aDeviceAddress.IsEmpty()); MOZ_ASSERT(!aDeviceAddress.IsEmpty());
MOZ_ASSERT(!sAdapterPath.IsEmpty()); MOZ_ASSERT(!sAdapterPath.IsEmpty());
MOZ_ASSERT(aManager); MOZ_ASSERT(aManager);
MOZ_ASSERT(mConnection);
nsString objectPath(GetObjectPathFromAddress(sAdapterPath, aDeviceAddress)); nsString objectPath(GetObjectPathFromAddress(sAdapterPath, aDeviceAddress));
@ -2961,13 +2970,16 @@ BluetoothDBusService::UpdateSdpRecords(const nsAString& aDeviceAddress,
OnUpdateSdpRecordsRunnable* callbackRunnable = OnUpdateSdpRecordsRunnable* callbackRunnable =
new OnUpdateSdpRecordsRunnable(objectPath, aManager); new OnUpdateSdpRecordsRunnable(objectPath, aManager);
return mConnection->SendWithReply(DiscoverServicesCallback, RawDBusConnection* connection = GetDBusConnection();
(void*)callbackRunnable, -1, MOZ_ASSERT(connection);
NS_ConvertUTF16toUTF8(objectPath).get(),
DBUS_DEVICE_IFACE, return connection->SendWithReply(DiscoverServicesCallback,
"DiscoverServices", (void*)callbackRunnable, -1,
DBUS_TYPE_STRING, &EmptyCString(), NS_ConvertUTF16toUTF8(objectPath).get(),
DBUS_TYPE_INVALID); DBUS_DEVICE_IFACE,
"DiscoverServices",
DBUS_TYPE_STRING, &EmptyCString(),
DBUS_TYPE_INVALID);
} }
void void
@ -3144,7 +3156,10 @@ BluetoothDBusService::SendMetaData(const nsAString& aTitle,
nsRefPtr<BluetoothReplyRunnable> runnable(aRunnable); nsRefPtr<BluetoothReplyRunnable> runnable(aRunnable);
bool ret = mConnection->SendWithReply( RawDBusConnection* connection = GetDBusConnection();
MOZ_ASSERT(connection);
bool ret = connection->SendWithReply(
GetVoidCallback, (void*)runnable.get(), -1, GetVoidCallback, (void*)runnable.get(), -1,
NS_ConvertUTF16toUTF8(objectPath).get(), NS_ConvertUTF16toUTF8(objectPath).get(),
DBUS_CTL_IFACE, "UpdateMetaData", DBUS_CTL_IFACE, "UpdateMetaData",
@ -3243,7 +3258,10 @@ BluetoothDBusService::SendPlayStatus(int64_t aDuration,
nsRefPtr<BluetoothReplyRunnable> runnable(aRunnable); nsRefPtr<BluetoothReplyRunnable> runnable(aRunnable);
bool ret = mConnection->SendWithReply( RawDBusConnection* connection = GetDBusConnection();
MOZ_ASSERT(connection);
bool ret = connection->SendWithReply(
GetVoidCallback, (void*)runnable.get(), -1, GetVoidCallback, (void*)runnable.get(), -1,
NS_ConvertUTF16toUTF8(objectPath).get(), NS_ConvertUTF16toUTF8(objectPath).get(),
DBUS_CTL_IFACE, "UpdatePlayStatus", DBUS_CTL_IFACE, "UpdatePlayStatus",
@ -3292,7 +3310,10 @@ BluetoothDBusService::UpdatePlayStatus(uint32_t aDuration,
uint32_t tempPlayStatus = aPlayStatus; uint32_t tempPlayStatus = aPlayStatus;
bool ret = mConnection->SendWithReply( RawDBusConnection* connection = GetDBusConnection();
MOZ_ASSERT(connection);
bool ret = connection->SendWithReply(
ControlCallback, nullptr, -1, ControlCallback, nullptr, -1,
NS_ConvertUTF16toUTF8(objectPath).get(), NS_ConvertUTF16toUTF8(objectPath).get(),
DBUS_CTL_IFACE, "UpdatePlayStatus", DBUS_CTL_IFACE, "UpdatePlayStatus",
@ -3322,7 +3343,10 @@ BluetoothDBusService::UpdateNotification(ControlEventId aEventId,
GetObjectPathFromAddress(sAdapterPath, address); GetObjectPathFromAddress(sAdapterPath, address);
uint16_t eventId = aEventId; uint16_t eventId = aEventId;
bool ret = mConnection->SendWithReply( RawDBusConnection* connection = GetDBusConnection();
MOZ_ASSERT(connection);
bool ret = connection->SendWithReply(
ControlCallback, nullptr, -1, ControlCallback, nullptr, -1,
NS_ConvertUTF16toUTF8(objectPath).get(), NS_ConvertUTF16toUTF8(objectPath).get(),
DBUS_CTL_IFACE, "UpdateNotification", DBUS_CTL_IFACE, "UpdateNotification",

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

@ -194,8 +194,6 @@ private:
const char* aInterface, const char* aInterface,
const nsAString& aMessage, const nsAString& aMessage,
mozilla::ipc::DBusReplyCallback aCallback); mozilla::ipc::DBusReplyCallback aCallback);
nsRefPtr<mozilla::ipc::RawDBusConnection> mConnection;
}; };
END_BLUETOOTH_NAMESPACE END_BLUETOOTH_NAMESPACE

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

@ -45,21 +45,16 @@ const ContentPanning = {
this.watchedEventsType = 'mouse'; this.watchedEventsType = 'mouse';
} }
// If we are using an AsyncPanZoomController for the parent frame, let els = Cc["@mozilla.org/eventlistenerservice;1"]
// it will handle subframe scrolling too. We don't need to listen for .getService(Ci.nsIEventListenerService);
// these events.
if (!docShell.asyncPanZoomEnabled) {
let els = Cc["@mozilla.org/eventlistenerservice;1"]
.getService(Ci.nsIEventListenerService);
events.forEach(function(type) { events.forEach(function(type) {
// Using the system group for mouse/touch events to avoid // Using the system group for mouse/touch events to avoid
// missing events if .stopPropagation() has been called. // missing events if .stopPropagation() has been called.
els.addSystemEventListener(global, type, els.addSystemEventListener(global, type,
this.handleEvent.bind(this), this.handleEvent.bind(this),
/* useCapture = */ false); /* useCapture = */ false);
}.bind(this)); }.bind(this));
}
addMessageListener("Viewport:Change", this._recvViewportChange.bind(this)); addMessageListener("Viewport:Change", this._recvViewportChange.bind(this));
addMessageListener("Gesture:DoubleTap", this._recvDoubleTap.bind(this)); addMessageListener("Gesture:DoubleTap", this._recvDoubleTap.bind(this));
@ -70,6 +65,8 @@ const ContentPanning = {
}, },
handleEvent: function cp_handleEvent(evt) { handleEvent: function cp_handleEvent(evt) {
this._tryDelayMouseEvents();
if (evt.defaultPrevented || evt.multipleActionsPrevented) { if (evt.defaultPrevented || evt.multipleActionsPrevented) {
// clean up panning state even if touchend/mouseup has been preventDefault. // clean up panning state even if touchend/mouseup has been preventDefault.
if(evt.type === 'touchend' || evt.type === 'mouseup') { if(evt.type === 'touchend' || evt.type === 'mouseup') {
@ -82,13 +79,6 @@ const ContentPanning = {
return; 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) { switch (evt.type) {
case 'mousedown': case 'mousedown':
case 'touchstart': case 'touchstart':
@ -189,7 +179,8 @@ const ContentPanning = {
// We prevent start events to avoid sending a focus event at the end of this // We prevent start events to avoid sending a focus event at the end of this
// touch series. See bug 889717. // touch series. See bug 889717.
if (this.panning || this.preventNextClick) { if (docShell.asyncPanZoomEnabled === false &&
(this.panning || this.preventNextClick)) {
evt.preventDefault(); evt.preventDefault();
} }
}, },
@ -228,7 +219,7 @@ const ContentPanning = {
let view = target.ownerDocument ? target.ownerDocument.defaultView let view = target.ownerDocument ? target.ownerDocument.defaultView
: target; : target;
view.addEventListener('click', this, true, true); 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. // We prevent end events to avoid sending a focus event. See bug 889717.
evt.preventDefault(); evt.preventDefault();
} }
@ -236,12 +227,7 @@ const ContentPanning = {
this.notify(this._activationTimer); this.notify(this._activationTimer);
this._delayEvents = true; this._delayEvents = true;
let start = Date.now(); this._tryDelayMouseEvents();
let thread = Services.tm.currentThread;
while (this._delayEvents && (Date.now() - start) < this._activeDurationMs) {
thread.processNextEvent(true);
}
this._delayEvents = false;
} }
this._finishPanning(); this._finishPanning();
@ -278,7 +264,12 @@ const ContentPanning = {
} }
let isPan = KineticPanning.isPan(); let isPan = KineticPanning.isPan();
this.scrollCallback(delta.scale(-1));
// 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 // If we've detected a pan gesture, cancel the active state of the
// current target. // current target.
@ -454,6 +445,15 @@ const ContentPanning = {
return this._activeDurationMs = duration; 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() { _resetActive: function cp_resetActive() {
let elt = this.pointerDownTarget || this.target; let elt = this.pointerDownTarget || this.target;
let root = elt.ownerDocument || elt.document; let root = elt.ownerDocument || elt.document;
@ -594,7 +594,9 @@ const ContentPanning = {
delete this.primaryPointerId; delete this.primaryPointerId;
this._activationTimer.cancel(); 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); KineticPanning.start(this);
} }
} }

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

@ -11,7 +11,7 @@ const Cu = Components.utils;
const Cc = Components.classes; const Cc = Components.classes;
const Ci = Components.interfaces; const Ci = Components.interfaces;
this.EXPORTED_SYMBOLS = []; this.EXPORTED_SYMBOLS = ["ContactService"];
Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/Services.jsm");
@ -31,7 +31,7 @@ let ContactService = {
"child-process-shutdown", "Contacts:GetRevision", "child-process-shutdown", "Contacts:GetRevision",
"Contacts:GetCount"]; "Contacts:GetCount"];
this._children = []; this._children = [];
this._cursors = {}; this._cursors = new Map();
this._messages.forEach(function(msgName) { this._messages.forEach(function(msgName) {
ppmm.addMessageListener(msgName, this); ppmm.addMessageListener(msgName, this);
}.bind(this)); }.bind(this));
@ -120,18 +120,21 @@ let ContactService = {
if (!this.assertPermission(aMessage, "contacts-read")) { if (!this.assertPermission(aMessage, "contacts-read")) {
return null; return null;
} }
if (!this._cursors[mm]) { let cursorList = this._cursors.get(mm);
this._cursors[mm] = []; if (!cursorList) {
cursorList = [];
this._cursors.set(mm, cursorList);
} }
this._cursors[mm].push(msg.cursorId); cursorList.push(msg.cursorId);
this._db.getAll( this._db.getAll(
function(aContacts) { function(aContacts) {
try { try {
mm.sendAsyncMessage("Contacts:GetAll:Next", {cursorId: msg.cursorId, contacts: aContacts}); mm.sendAsyncMessage("Contacts:GetAll:Next", {cursorId: msg.cursorId, contacts: aContacts});
if (aContacts === null) { if (aContacts === null) {
let index = this._cursors[mm].indexOf(msg.cursorId); let cursorList = this._cursors.get(mm);
this._cursors[mm].splice(index, 1); let index = cursorList.indexOf(msg.cursorId);
cursorList.splice(index, 1);
} }
} catch (e) { } catch (e) {
if (DEBUG) debug("Child is dead, DB should stop sending contacts"); if (DEBUG) debug("Child is dead, DB should stop sending contacts");
@ -240,11 +243,12 @@ let ContactService = {
if (DEBUG) debug("Unregister index: " + index); if (DEBUG) debug("Unregister index: " + index);
this._children.splice(index, 1); this._children.splice(index, 1);
} }
if (this._cursors[mm]) { cursorList = this._cursors.get(mm);
for (let id of this._cursors[mm]) { if (cursorList) {
for (let id of cursorList) {
this._db.clearDispatcher(id); this._db.clearDispatcher(id);
} }
delete this._cursors[mm]; this._cursors.delete(mm);
} }
break; break;
default: default:

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

@ -1,3 +1,6 @@
[DEFAULT] [DEFAULT]
[test_contacts_shutdown.xul]
skip-if = os == "android"
[test_contacts_upgrade.xul] [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", "MozMobileMessageThread",
"MozNamedAttrMap", "MozNamedAttrMap",
{name: "MozNdefRecord", b2g: true}, {name: "MozNdefRecord", b2g: true},
{name: "MozNfc", b2g: true},
{name: "MozNFCPeer", b2g: true}, {name: "MozNFCPeer", b2g: true},
{name: "MozNFCTag", b2g: true}, {name: "MozNFCTag", b2g: true},
{name: "MozOtaStatusEvent", b2g: true, pref: "dom.mobileconnection.enabled"}, {name: "MozOtaStatusEvent", b2g: true, pref: "dom.mobileconnection.enabled"},

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

@ -5,7 +5,8 @@
/* Copyright © 2013 Deutsche Telekom, Inc. */ /* Copyright © 2013 Deutsche Telekom, Inc. */
[JSImplementation="@mozilla.org/navigatorNfc;1", [JSImplementation="@mozilla.org/navigatorNfc;1",
NavigatorProperty="mozNfc"] NavigatorProperty="mozNfc",
Func="Navigator::HasNfcSupport"]
interface MozNfc : EventTarget { interface MozNfc : EventTarget {
MozNFCTag getNFCTag(DOMString sessionId); MozNFCTag getNFCTag(DOMString sessionId);
MozNFCPeer getNFCPeer(DOMString sessionId); MozNFCPeer getNFCPeer(DOMString sessionId);

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

@ -175,7 +175,8 @@ Layer::Layer(LayerManager* aManager, void* aImplData) :
mIsFixedPosition(false), mIsFixedPosition(false),
mMargins(0, 0, 0, 0), mMargins(0, 0, 0, 0),
mStickyPositionData(nullptr), mStickyPositionData(nullptr),
mIsScrollbar(false), mScrollbarTargetId(FrameMetrics::NULL_SCROLL_ID),
mScrollbarDirection(ScrollDirection::NONE),
mDebugColorIndex(0), mDebugColorIndex(0),
mAnimationGeneration(0) mAnimationGeneration(0)
{} {}
@ -1268,12 +1269,11 @@ Layer::PrintInfo(nsACString& aTo, const char* aPrefix)
if (GetContentFlags() & CONTENT_COMPONENT_ALPHA) { if (GetContentFlags() & CONTENT_COMPONENT_ALPHA) {
aTo += " [componentAlpha]"; aTo += " [componentAlpha]";
} }
if (GetIsScrollbar()) { if (GetScrollbarDirection() == VERTICAL) {
if (GetScrollbarDirection() == VERTICAL) { aTo.AppendPrintf(" [vscrollbar=%lld]", GetScrollbarTargetContainerId());
aTo.AppendPrintf(" [vscrollbar=%lld]", GetScrollbarTargetContainerId()); }
} else { if (GetScrollbarDirection() == HORIZONTAL) {
aTo.AppendPrintf(" [hscrollbar=%lld]", GetScrollbarTargetContainerId()); aTo.AppendPrintf(" [hscrollbar=%lld]", GetScrollbarTargetContainerId());
}
} }
if (GetIsFixedPosition()) { if (GetIsFixedPosition()) {
aTo.AppendPrintf(" [isFixedPosition anchor=%f,%f]", mAnchor.x, mAnchor.y); aTo.AppendPrintf(" [isFixedPosition anchor=%f,%f]", mAnchor.x, mAnchor.y);

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

@ -967,6 +967,7 @@ public:
} }
enum ScrollDirection { enum ScrollDirection {
NONE,
VERTICAL, VERTICAL,
HORIZONTAL HORIZONTAL
}; };
@ -978,11 +979,9 @@ public:
*/ */
void SetScrollbarData(FrameMetrics::ViewID aScrollId, ScrollDirection aDir) void SetScrollbarData(FrameMetrics::ViewID aScrollId, ScrollDirection aDir)
{ {
if (mIsScrollbar || if (mScrollbarTargetId != aScrollId ||
mScrollbarTargetId != aScrollId ||
mScrollbarDirection != aDir) { mScrollbarDirection != aDir) {
MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) ScrollbarData", this)); MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) ScrollbarData", this));
mIsScrollbar = true;
mScrollbarTargetId = aScrollId; mScrollbarTargetId = aScrollId;
mScrollbarDirection = aDir; mScrollbarDirection = aDir;
Mutated(); Mutated();
@ -1013,7 +1012,6 @@ public:
FrameMetrics::ViewID GetStickyScrollContainerId() { return mStickyPositionData->mScrollId; } FrameMetrics::ViewID GetStickyScrollContainerId() { return mStickyPositionData->mScrollId; }
const LayerRect& GetStickyScrollRangeOuter() { return mStickyPositionData->mOuter; } const LayerRect& GetStickyScrollRangeOuter() { return mStickyPositionData->mOuter; }
const LayerRect& GetStickyScrollRangeInner() { return mStickyPositionData->mInner; } const LayerRect& GetStickyScrollRangeInner() { return mStickyPositionData->mInner; }
bool GetIsScrollbar() { return mIsScrollbar; }
FrameMetrics::ViewID GetScrollbarTargetContainerId() { return mScrollbarTargetId; } FrameMetrics::ViewID GetScrollbarTargetContainerId() { return mScrollbarTargetId; }
ScrollDirection GetScrollbarDirection() { return mScrollbarDirection; } ScrollDirection GetScrollbarDirection() { return mScrollbarDirection; }
Layer* GetMaskLayer() const { return mMaskLayer; } Layer* GetMaskLayer() const { return mMaskLayer; }
@ -1387,7 +1385,6 @@ protected:
LayerRect mInner; LayerRect mInner;
}; };
nsAutoPtr<StickyPositionData> mStickyPositionData; nsAutoPtr<StickyPositionData> mStickyPositionData;
bool mIsScrollbar;
FrameMetrics::ViewID mScrollbarTargetId; FrameMetrics::ViewID mScrollbarTargetId;
ScrollDirection mScrollbarDirection; ScrollDirection mScrollbarDirection;
DebugOnly<uint32_t> mDebugColorIndex; DebugOnly<uint32_t> mDebugColorIndex;

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

@ -525,7 +525,7 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(TimeStamp aCurrentFram
appliedTransform = true; appliedTransform = true;
} }
if (container->GetIsScrollbar()) { if (container->GetScrollbarDirection() != Layer::NONE) {
ApplyAsyncTransformToScrollbar(container); ApplyAsyncTransformToScrollbar(container);
} }
return appliedTransform; return appliedTransform;

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

@ -1276,7 +1276,9 @@ void AsyncPanZoomController::RequestContentRepaint() {
mFrameMetrics.mScrollOffset.x) < EPSILON && mFrameMetrics.mScrollOffset.x) < EPSILON &&
fabsf(mLastPaintRequestMetrics.mScrollOffset.y - fabsf(mLastPaintRequestMetrics.mScrollOffset.y -
mFrameMetrics.mScrollOffset.y) < EPSILON && 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; return;
} }
@ -1463,8 +1465,10 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri
aLayerMetrics.mCompositionBounds.height == mFrameMetrics.mCompositionBounds.height) { aLayerMetrics.mCompositionBounds.height == mFrameMetrics.mCompositionBounds.height) {
// Remote content has sync'd up to the composition geometry // Remote content has sync'd up to the composition geometry
// change, so we can accept the viewport it's calculated. // 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; needContentRepaint = true;
}
mFrameMetrics.mViewport = aLayerMetrics.mViewport; mFrameMetrics.mViewport = aLayerMetrics.mViewport;
} }

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

@ -280,10 +280,8 @@ LayerTransactionParent::RecvUpdate(const InfallibleTArray<Edit>& cset,
common.stickyScrollRangeOuter(), common.stickyScrollRangeOuter(),
common.stickyScrollRangeInner()); common.stickyScrollRangeInner());
} }
if (common.isScrollbar()) { layer->SetScrollbarData(common.scrollbarTargetContainerId(),
layer->SetScrollbarData(common.scrollbarTargetContainerId(), static_cast<Layer::ScrollDirection>(common.scrollbarDirection()));
static_cast<Layer::ScrollDirection>(common.scrollbarDirection()));
}
if (PLayerParent* maskLayer = common.maskLayerParent()) { if (PLayerParent* maskLayer = common.maskLayerParent()) {
layer->SetMaskLayer(cast(maskLayer)->AsLayer()); layer->SetMaskLayer(cast(maskLayer)->AsLayer());
} else { } else {

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

@ -198,7 +198,6 @@ struct CommonLayerAttributes {
uint64_t stickyScrollContainerId; uint64_t stickyScrollContainerId;
LayerRect stickyScrollRangeOuter; LayerRect stickyScrollRangeOuter;
LayerRect stickyScrollRangeInner; LayerRect stickyScrollRangeInner;
bool isScrollbar;
uint64_t scrollbarTargetContainerId; uint64_t scrollbarTargetContainerId;
uint32_t scrollbarDirection; uint32_t scrollbarDirection;
nullable PLayer maskLayer; nullable PLayer maskLayer;

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

@ -501,11 +501,8 @@ ShadowLayerForwarder::EndTransaction(InfallibleTArray<EditReply>* aReplies, bool
common.stickyScrollRangeOuter() = mutant->GetStickyScrollRangeOuter(); common.stickyScrollRangeOuter() = mutant->GetStickyScrollRangeOuter();
common.stickyScrollRangeInner() = mutant->GetStickyScrollRangeInner(); common.stickyScrollRangeInner() = mutant->GetStickyScrollRangeInner();
} }
common.isScrollbar() = mutant->GetIsScrollbar(); common.scrollbarTargetContainerId() = mutant->GetScrollbarTargetContainerId();
if (mutant->GetIsScrollbar()) { common.scrollbarDirection() = mutant->GetScrollbarDirection();
common.scrollbarTargetContainerId() = mutant->GetScrollbarTargetContainerId();
common.scrollbarDirection() = mutant->GetScrollbarDirection();
}
if (Layer* maskLayer = mutant->GetMaskLayer()) { if (Layer* maskLayer = mutant->GetMaskLayer()) {
common.maskLayerChild() = Shadow(maskLayer->AsShadowableLayer()); common.maskLayerChild() = Shadow(maskLayer->AsShadowableLayer());
} else { } else {

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

@ -66,544 +66,214 @@
#define LOG(args...) if (BTDEBUG) printf(args); #define LOG(args...) if (BTDEBUG) printf(args);
#endif #endif
#define DEFAULT_INITIAL_POLLFD_COUNT 8
namespace mozilla { namespace mozilla {
namespace ipc { namespace ipc {
class DBusWatcher : public RawDBusConnection class DBusWatcher : public MessageLoopForIO::Watcher
{ {
public: public:
DBusWatcher() DBusWatcher(RawDBusConnection* aConnection, DBusWatch* aWatch)
{ } : mConnection(aConnection),
mWatch(aWatch)
{
MOZ_ASSERT(mConnection);
MOZ_ASSERT(mWatch);
}
~DBusWatcher() ~DBusWatcher()
{ } { }
bool Initialize(); void StartWatching();
void CleanUp(); void StopWatching();
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);
static void FreeFunction(void* aData);
static dbus_bool_t AddWatchFunction(DBusWatch* aWatch, void* aData); static dbus_bool_t AddWatchFunction(DBusWatch* aWatch, void* aData);
static void RemoveWatchFunction(DBusWatch* aWatch, void* aData); static void RemoveWatchFunction(DBusWatch* aWatch, void* aData);
static void ToggleWatchFunction(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 RawDBusConnection*
DBusWatcher::Initialize() DBusWatcher::GetConnection()
{ {
if (!SetUp()) { return mConnection;
CleanUp();
return false;
}
return true;
} }
void void DBusWatcher::StartWatching()
DBusWatcher::CleanUp() {
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()); MOZ_ASSERT(!NS_IsMainThread());
dbus_connection_set_wakeup_main_function(mConnection, nullptr, mReadWatcher.StopWatchingFileDescriptor();
nullptr, nullptr); mWriteWatcher.StopWatchingFileDescriptor();
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);
} }
// DBus utility functions, used as function pointers in DBus setup // DBus utility functions, used as function pointers in DBus setup
void
DBusWatcher::FreeFunction(void* aData)
{
delete static_cast<DBusWatcher*>(aData);
}
dbus_bool_t dbus_bool_t
DBusWatcher::AddWatchFunction(DBusWatch* aWatch, void* aData) DBusWatcher::AddWatchFunction(DBusWatch* aWatch, void* aData)
{ {
MOZ_ASSERT(aData); MOZ_ASSERT(!NS_IsMainThread());
DBusWatcher* dbusWatcher = static_cast<DBusWatcher*>(aData);
return dbusWatcher->AddWatch(aWatch); 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 void
DBusWatcher::RemoveWatchFunction(DBusWatch* aWatch, void* aData) DBusWatcher::RemoveWatchFunction(DBusWatch* aWatch, void* aData)
{ {
MOZ_ASSERT(aData); MOZ_ASSERT(!NS_IsMainThread());
DBusWatcher* dbusWatcher = static_cast<DBusWatcher*>(aData);
dbusWatcher->RemoveWatch(aWatch); DBusWatcher* dbusWatcher =
static_cast<DBusWatcher*>(dbus_watch_get_data(aWatch));
dbusWatcher->StopWatching();
} }
void void
DBusWatcher::ToggleWatchFunction(DBusWatch* aWatch, void* aData) DBusWatcher::ToggleWatchFunction(DBusWatch* aWatch, void* aData)
{ {
MOZ_ASSERT(aData); MOZ_ASSERT(!NS_IsMainThread());
DBusWatcher* dbusWatcher = static_cast<DBusWatcher*>(aData);
DBusWatcher* dbusWatcher =
static_cast<DBusWatcher*>(dbus_watch_get_data(aWatch));
if (dbus_watch_get_enabled(aWatch)) { if (dbus_watch_get_enabled(aWatch)) {
dbusWatcher->AddWatch(aWatch); dbusWatcher->StartWatching();
} else { } else {
dbusWatcher->RemoveWatch(aWatch); dbusWatcher->StopWatching();
} }
} }
void void
DBusWatcher::DBusWakeupFunction(void* aData) DBusWatcher::OnFileCanReadWithoutBlocking(int aFd)
{
MOZ_ASSERT(aData);
DBusWatcher* dbusWatcher = static_cast<DBusWatcher*>(aData);
dbusWatcher->WakeUp();
}
bool
DBusWatcher::SetUp()
{ {
MOZ_ASSERT(!NS_IsMainThread()); MOZ_ASSERT(!NS_IsMainThread());
// If we already have a connection, exit dbus_watch_handle(mWatch, DBUS_WATCH_READABLE);
if (mConnection) {
return false;
}
// socketpair opens two sockets for the process to communicate on. DBusDispatchStatus dbusDispatchStatus;
// This is how android's implementation of the dbus event loop do {
// communicates with itself in relation to IPC signals. These dbusDispatchStatus =
// sockets are contained sequentially in the same struct in the dbus_connection_dispatch(mConnection->GetConnection());
// android code, but we break them out into class members here. } while (dbusDispatchStatus == DBUS_DISPATCH_DATA_REMAINS);
// 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;
} }
// 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: public:
DBusPollTask(DBusWatcher* aDBusWatcher) WatchDBusConnectionTask(RawDBusConnection* aConnection)
: mDBusWatcher(aDBusWatcher) : mConnection(aConnection)
{ } {
MOZ_ASSERT(mConnection);
}
NS_IMETHOD Run() void Run()
{ {
MOZ_ASSERT(!NS_IsMainThread()); MOZ_ASSERT(!NS_IsMainThread());
bool continueThread; dbus_bool_t success =
dbus_connection_set_watch_functions(mConnection->GetConnection(),
do { DBusWatcher::AddWatchFunction,
continueThread = mDBusWatcher->Poll(); DBusWatcher::RemoveWatchFunction,
} while (continueThread); DBusWatcher::ToggleWatchFunction,
mConnection, nullptr);
mDBusWatcher->CleanUp(); NS_ENSURE_TRUE_VOID(success == TRUE);
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;
} }
private: private:
nsRefPtr<DBusWatcher> mDBusWatcher; RawDBusConnection* mConnection;
}; };
static StaticRefPtr<DBusWatcher> gDBusWatcher; class DeleteDBusConnectionTask : public Task
static StaticRefPtr<nsIThread> gDBusServiceThread; {
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 bool
StartDBus() StartDBus()
{ {
MOZ_ASSERT(!NS_IsMainThread()); MOZ_ASSERT(!NS_IsMainThread());
NS_ENSURE_TRUE(!gDBusWatcher, true); NS_ENSURE_TRUE(!gDBusConnection, true);
nsRefPtr<DBusWatcher> dbusWatcher(new DBusWatcher()); RawDBusConnection* connection = new RawDBusConnection();
nsresult rv = connection->EstablishDBusConnection();
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);
NS_ENSURE_SUCCESS(rv, false); NS_ENSURE_SUCCESS(rv, false);
gDBusWatcher = dbusWatcher; XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
new WatchDBusConnectionTask(connection));
gDBusConnection = connection;
return true; return true;
} }
@ -612,36 +282,32 @@ bool
StopDBus() StopDBus()
{ {
MOZ_ASSERT(!NS_IsMainThread()); MOZ_ASSERT(!NS_IsMainThread());
NS_ENSURE_TRUE(gDBusServiceThread, true); NS_ENSURE_TRUE(gDBusConnection, true);
nsRefPtr<DBusWatcher> dbusWatcher(gDBusWatcher); RawDBusConnection* connection = gDBusConnection;
gDBusWatcher = nullptr; gDBusConnection = nullptr;
if (dbusWatcher && !dbusWatcher->Stop()) { XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
return false; new DeleteDBusConnectionTask(connection));
}
gDBusServiceThread = nullptr;
return true; return true;
} }
nsresult nsresult
DispatchToDBusThread(nsIRunnable* event) DispatchToDBusThread(Task* task)
{ {
nsRefPtr<nsIThread> dbusServiceThread(gDBusServiceThread); XRE_GetIOMessageLoop()->PostTask(FROM_HERE, task);
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();
return NS_OK; return NS_OK;
} }
RawDBusConnection*
GetDBusConnection()
{
NS_ENSURE_TRUE(gDBusConnection, nullptr);
return gDBusConnection;
}
} }
} }

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

@ -9,11 +9,13 @@
#include "nscore.h" #include "nscore.h"
class nsIRunnable; class Task;
namespace mozilla { namespace mozilla {
namespace ipc { namespace ipc {
class RawDBusConnection;
/** /**
* Starts the DBus thread, which handles returning signals to objects * Starts the DBus thread, which handles returning signals to objects
* that call asynchronous functions. This should be called from the * that call asynchronous functions. This should be called from the
@ -32,13 +34,21 @@ bool StartDBus();
bool StopDBus(); 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 * @return NS_OK on success, or an error code otherwise
*/ */
nsresult 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/. */ * You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <dbus/dbus.h> #include <dbus/dbus.h>
#include "base/message_loop.h"
#include "mozilla/Monitor.h" #include "mozilla/Monitor.h"
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
#include "DBusThread.h" #include "DBusThread.h"
@ -34,11 +35,15 @@ using namespace mozilla::ipc;
namespace mozilla { namespace mozilla {
namespace ipc { namespace ipc {
class DBusConnectionSendRunnableBase : public nsRunnable class DBusConnectionSendTaskBase : public Task
{ {
public:
virtual ~DBusConnectionSendTaskBase()
{ }
protected: protected:
DBusConnectionSendRunnableBase(DBusConnection* aConnection, DBusConnectionSendTaskBase(DBusConnection* aConnection,
DBusMessage* aMessage) DBusMessage* aMessage)
: mConnection(aConnection), : mConnection(aConnection),
mMessage(aMessage) mMessage(aMessage)
{ {
@ -46,9 +51,6 @@ protected:
MOZ_ASSERT(mMessage); MOZ_ASSERT(mMessage);
} }
virtual ~DBusConnectionSendRunnableBase()
{ }
DBusConnection* mConnection; DBusConnection* mConnection;
DBusMessageRefPtr mMessage; DBusMessageRefPtr mMessage;
}; };
@ -57,35 +59,33 @@ protected:
// Sends a message and returns the message's serial number to the // Sends a message and returns the message's serial number to the
// disaptching thread. Only run it in DBus thread. // disaptching thread. Only run it in DBus thread.
// //
class DBusConnectionSendRunnable : public DBusConnectionSendRunnableBase class DBusConnectionSendTask : public DBusConnectionSendTaskBase
{ {
public: public:
DBusConnectionSendRunnable(DBusConnection* aConnection, DBusConnectionSendTask(DBusConnection* aConnection,
DBusMessage* aMessage) 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); dbus_bool_t success = dbus_connection_send(mConnection,
mMessage,
NS_ENSURE_TRUE(success == TRUE, NS_ERROR_FAILURE); nullptr);
NS_ENSURE_TRUE_VOID(success == TRUE);
return NS_OK;
} }
protected:
~DBusConnectionSendRunnable()
{ }
}; };
// //
// Sends a message and executes a callback function for the reply. Only // Sends a message and executes a callback function for the reply. Only
// run it in DBus thread. // run it in DBus thread.
// //
class DBusConnectionSendWithReplyRunnable : public DBusConnectionSendRunnableBase class DBusConnectionSendWithReplyTask : public DBusConnectionSendTaskBase
{ {
private: private:
class NotifyData class NotifyData
@ -130,24 +130,27 @@ private:
} }
public: public:
DBusConnectionSendWithReplyRunnable(DBusConnection* aConnection, DBusConnectionSendWithReplyTask(DBusConnection* aConnection,
DBusMessage* aMessage, DBusMessage* aMessage,
int aTimeout, int aTimeout,
DBusReplyCallback aCallback, DBusReplyCallback aCallback,
void* aData) void* aData)
: DBusConnectionSendRunnableBase(aConnection, aMessage), : DBusConnectionSendTaskBase(aConnection, aMessage),
mCallback(aCallback), mCallback(aCallback),
mData(aData), mData(aData),
mTimeout(aTimeout) mTimeout(aTimeout)
{ } { }
NS_IMETHOD Run() virtual ~DBusConnectionSendWithReplyTask()
{ }
void Run() MOZ_OVERRIDE
{ {
MOZ_ASSERT(!NS_IsMainThread()); MOZ_ASSERT(MessageLoop::current());
// Freed at end of Notify // Freed at end of Notify
nsAutoPtr<NotifyData> data(new NotifyData(mCallback, mData)); nsAutoPtr<NotifyData> data(new NotifyData(mCallback, mData));
NS_ENSURE_TRUE(data, NS_ERROR_OUT_OF_MEMORY); NS_ENSURE_TRUE_VOID(data);
DBusPendingCall* call; DBusPendingCall* call;
@ -155,21 +158,15 @@ public:
mMessage, mMessage,
&call, &call,
mTimeout); 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); 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(); data.forget();
dbus_message_unref(mMessage); dbus_message_unref(mMessage);
return NS_OK;
}; };
protected:
~DBusConnectionSendWithReplyRunnable()
{ }
private: private:
DBusReplyCallback mCallback; DBusReplyCallback mCallback;
void* mData; void* mData;
@ -202,7 +199,7 @@ nsresult RawDBusConnection::EstablishDBusConnection()
} }
DBusError err; DBusError err;
dbus_error_init(&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)) { if (dbus_error_is_set(&err)) {
dbus_error_free(&err); dbus_error_free(&err);
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
@ -214,14 +211,15 @@ nsresult RawDBusConnection::EstablishDBusConnection()
void RawDBusConnection::ScopedDBusConnectionPtrTraits::release(DBusConnection* ptr) void RawDBusConnection::ScopedDBusConnectionPtrTraits::release(DBusConnection* ptr)
{ {
if (ptr) { if (ptr) {
dbus_connection_close(ptr);
dbus_connection_unref(ptr); dbus_connection_unref(ptr);
} }
} }
bool RawDBusConnection::Send(DBusMessage* aMessage) bool RawDBusConnection::Send(DBusMessage* aMessage)
{ {
nsRefPtr<DBusConnectionSendRunnable> t( DBusConnectionSendTask* t =
new DBusConnectionSendRunnable(mConnection, aMessage)); new DBusConnectionSendTask(mConnection, aMessage);
MOZ_ASSERT(t); MOZ_ASSERT(t);
nsresult rv = DispatchToDBusThread(t); nsresult rv = DispatchToDBusThread(t);
@ -241,9 +239,9 @@ bool RawDBusConnection::SendWithReply(DBusReplyCallback aCallback,
int aTimeout, int aTimeout,
DBusMessage* aMessage) DBusMessage* aMessage)
{ {
nsRefPtr<nsIRunnable> t( DBusConnectionSendWithReplyTask* t =
new DBusConnectionSendWithReplyRunnable(mConnection, aMessage, new DBusConnectionSendWithReplyTask(mConnection, aMessage, aTimeout,
aTimeout, aCallback, aData)); aCallback, aData);
MOZ_ASSERT(t); MOZ_ASSERT(t);
nsresult rv = DispatchToDBusThread(t); nsresult rv = DispatchToDBusThread(t);

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

@ -14,7 +14,6 @@
#include <string> #include <string>
#include "nscore.h" #include "nscore.h"
#include "mozilla/Scoped.h" #include "mozilla/Scoped.h"
#include <mozilla/RefPtr.h>
#include <mozilla/Mutex.h> #include <mozilla/Mutex.h>
struct DBusConnection; struct DBusConnection;
@ -26,7 +25,7 @@ namespace ipc {
typedef void (*DBusReplyCallback)(DBusMessage*, void*); typedef void (*DBusReplyCallback)(DBusMessage*, void*);
class RawDBusConnection : public AtomicRefCounted<RawDBusConnection> class RawDBusConnection
{ {
struct ScopedDBusConnectionPtrTraits : ScopedFreePtrTraits<DBusConnection> struct ScopedDBusConnectionPtrTraits : ScopedFreePtrTraits<DBusConnection>
{ {

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

@ -215,4 +215,41 @@ nsFrame::PrintDisplayList(nsDisplayListBuilder* aBuilder,
PrintDisplayListTo(aBuilder, aList, aFile, aDumpHtml); 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 #endif

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

@ -713,6 +713,10 @@ public:
const nsDisplayList& aList, const nsDisplayList& aList,
FILE* aFile = stdout, FILE* aFile = stdout,
bool aDumpHtml = false); bool aDumpHtml = false);
static void PrintDisplayListSet(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aList,
FILE* aFile = stdout,
bool aDumpHtml = false);
#endif #endif
}; };

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

@ -6,6 +6,7 @@
[include:dom/mobilemessage/tests/xpcshell.ini] [include:dom/mobilemessage/tests/xpcshell.ini]
[include:dom/network/tests/unit_stats/xpcshell.ini] [include:dom/network/tests/unit_stats/xpcshell.ini]
[include:dom/system/gonk/tests/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/apps/tests/unit/xpcshell.ini]
[include:toolkit/devtools/debugger/tests/unit/xpcshell.ini] [include:toolkit/devtools/debugger/tests/unit/xpcshell.ini]
[include:toolkit/devtools/sourcemap/tests/unit/xpcshell.ini] [include:toolkit/devtools/sourcemap/tests/unit/xpcshell.ini]

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

@ -64,6 +64,7 @@ HwcComposer2D::HwcComposer2D()
, mColorFill(false) , mColorFill(false)
, mRBSwapSupport(false) , mRBSwapSupport(false)
, mPrevRetireFence(-1) , mPrevRetireFence(-1)
, mPrepared(false)
{ {
} }
@ -451,7 +452,6 @@ HwcComposer2D::TryHwComposition()
if (!(fbsurface && fbsurface->lastHandle)) { if (!(fbsurface && fbsurface->lastHandle)) {
LOGD("H/W Composition failed. FBSurface not initialized."); LOGD("H/W Composition failed. FBSurface not initialized.");
mList->numHwLayers = 0;
return false; return false;
} }
@ -460,7 +460,6 @@ HwcComposer2D::TryHwComposition()
if (idx >= mMaxLayerCount) { if (idx >= mMaxLayerCount) {
if (!ReallocLayerList() || idx >= mMaxLayerCount) { if (!ReallocLayerList() || idx >= mMaxLayerCount) {
LOGE("TryHwComposition failed! Could not add FB layer"); LOGE("TryHwComposition failed! Could not add FB layer");
mList->numHwLayers = 0;
return false; return false;
} }
} }
@ -495,7 +494,6 @@ HwcComposer2D::TryHwComposition()
// No composition on FB layer, so closing releaseFenceFd // No composition on FB layer, so closing releaseFenceFd
close(mList->hwLayers[idx].releaseFenceFd); close(mList->hwLayers[idx].releaseFenceFd);
mList->numHwLayers = 0;
return true; return true;
} }
@ -515,7 +513,7 @@ HwcComposer2D::Render(EGLDisplay dpy, EGLSurface sur)
return false; return false;
} }
if (mList->numHwLayers != 0) { if (mPrepared) {
// No mHwc prepare, if already prepared in current draw cycle // No mHwc prepare, if already prepared in current draw cycle
mList->hwLayers[mList->numHwLayers - 1].handle = fbsurface->lastHandle; mList->hwLayers[mList->numHwLayers - 1].handle = fbsurface->lastHandle;
mList->hwLayers[mList->numHwLayers - 1].acquireFenceFd = fbsurface->lastFenceFD; mList->hwLayers[mList->numHwLayers - 1].acquireFenceFd = fbsurface->lastFenceFD;
@ -535,7 +533,6 @@ HwcComposer2D::Render(EGLDisplay dpy, EGLSurface sur)
Commit(); Commit();
GetGonkDisplay()->SetFBReleaseFd(mList->hwLayers[mList->numHwLayers - 1].releaseFenceFd); GetGonkDisplay()->SetFBReleaseFd(mList->hwLayers[mList->numHwLayers - 1].releaseFenceFd);
mList->numHwLayers = 0;
return true; return true;
} }
@ -566,7 +563,11 @@ HwcComposer2D::Prepare(buffer_handle_t fbHandle, int fence)
mList->hwLayers[idx].releaseFenceFd = -1; mList->hwLayers[idx].releaseFenceFd = -1;
mList->hwLayers[idx].planeAlpha = 0xFF; mList->hwLayers[idx].planeAlpha = 0xFF;
if (mPrepared) {
LOGE("Multiple hwc prepare calls!");
}
mHwc->prepare(mHwc, HWC_NUM_DISPLAY_TYPES, displays); mHwc->prepare(mHwc, HWC_NUM_DISPLAY_TYPES, displays);
mPrepared = true;
} }
bool bool
@ -609,8 +610,19 @@ HwcComposer2D::Commit()
} }
} }
mPrepared = false;
return !err; 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 #else
bool bool
HwcComposer2D::TryHwComposition() HwcComposer2D::TryHwComposition()
@ -623,6 +635,12 @@ HwcComposer2D::Render(EGLDisplay dpy, EGLSurface sur)
{ {
return GetGonkDisplay()->SwapBuffers(dpy, sur); return GetGonkDisplay()->SwapBuffers(dpy, sur);
} }
void
HwcComposer2D::Reset()
{
mPrepared = false;
}
#endif #endif
bool bool
@ -640,6 +658,10 @@ HwcComposer2D::TryRender(Layer* aRoot,
mHwcLayerMap.Clear(); mHwcLayerMap.Clear();
} }
if (mPrepared) {
Reset();
}
// XXX: The clear() below means all rect vectors will be have to be // XXX: The clear() below means all rect vectors will be have to be
// reallocated. We may want to avoid this if possible // reallocated. We may want to avoid this if possible
mVisibleRegions.clear(); mVisibleRegions.clear();
@ -651,9 +673,6 @@ HwcComposer2D::TryRender(Layer* aRoot,
aGLWorldTransform)) aGLWorldTransform))
{ {
LOGD("Render aborted. Nothing was drawn to the screen"); LOGD("Render aborted. Nothing was drawn to the screen");
if (mList) {
mList->numHwLayers = 0;
}
return false; return false;
} }

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

@ -63,6 +63,7 @@ public:
bool Render(EGLDisplay dpy, EGLSurface sur); bool Render(EGLDisplay dpy, EGLSurface sur);
private: private:
void Reset();
void Prepare(buffer_handle_t fbHandle, int fence); void Prepare(buffer_handle_t fbHandle, int fence);
bool Commit(); bool Commit();
bool TryHwComposition(); bool TryHwComposition();
@ -84,6 +85,7 @@ private:
nsTArray<int> mPrevReleaseFds; nsTArray<int> mPrevReleaseFds;
int mPrevRetireFence; int mPrevRetireFence;
nsTArray<layers::LayerComposite*> mHwcLayerMap; nsTArray<layers::LayerComposite*> mHwcLayerMap;
bool mPrepared;
}; };
} // namespace mozilla } // namespace mozilla