diff --git a/CLOBBER b/CLOBBER index 67876f8d1244..f3ffeadb64b7 100644 --- a/CLOBBER +++ b/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. diff --git a/b2g/app/b2g.js b/b2g/app/b2g.js index 2fd0d337d596..817da4813953 100644 --- a/b2g/app/b2g.js +++ b/b2g/app/b2g.js @@ -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); diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 073e1333333b..32baa9dd5e1b 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "5bfef5faac50d14e055f642a44ed2df8483fb2fe", + "revision": "9271d94f35a54995e4442da711e51cff0244741d", "repo_path": "/integration/gaia-central" } diff --git a/content/media/encoder/TrackEncoder.cpp b/content/media/encoder/TrackEncoder.cpp index cdfe7bb000c9..a7c1b908be89 100644 --- a/content/media/encoder/TrackEncoder.cpp +++ b/content/media/encoder/TrackEncoder.cpp @@ -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(); diff --git a/content/media/omx/OmxDecoder.cpp b/content/media/omx/OmxDecoder.cpp index 5ce86774dcb9..1d53cde4f766 100644 --- a/content/media/omx/OmxDecoder.cpp +++ b/content/media/omx/OmxDecoder.cpp @@ -41,6 +41,25 @@ using namespace mozilla; namespace mozilla { +class ReleaseOmxDecoderRunnable : public nsRunnable +{ +public: + ReleaseOmxDecoderRunnable(const android::sp& aOmxDecoder) + : mOmxDecoder(aOmxDecoder) + { + } + + NS_METHOD Run() MOZ_OVERRIDE + { + MOZ_ASSERT(NS_IsMainThread()); + mOmxDecoder = nullptr; // release OmxDecoder + return NS_OK; + } + +private: + android::sp 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(resourceLength-aOffset, sReadSize); @@ -1041,7 +1068,7 @@ bool OmxDecoder::ProcessCachedData(int64_t aOffset, bool aWaitForCompletion) nsAutoArrayPtr buffer(new char[bufferLength]); nsresult rv = mResource->ReadFromCache(buffer.get(), aOffset, bufferLength); - NS_ENSURE_SUCCESS(rv, false); + NS_ENSURE_SUCCESS(rv, -1); nsRefPtr 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; } diff --git a/content/media/omx/OmxDecoder.h b/content/media/omx/OmxDecoder.h index b0e7ce3b91cb..96b55c068cd9 100644 --- a/content/media/omx/OmxDecoder.h +++ b/content/media/omx/OmxDecoder.h @@ -238,7 +238,7 @@ public: // Called on ALooper thread. void onMessageReceived(const sp &msg); - bool ProcessCachedData(int64_t aOffset, bool aWaitForCompletion); + int64_t ProcessCachedData(int64_t aOffset, bool aWaitForCompletion); }; } diff --git a/content/media/omx/RtspOmxDecoder.cpp b/content/media/omx/RtspOmxDecoder.cpp index 4844efad0cac..7e3e2ffb2e96 100644 --- a/content/media/omx/RtspOmxDecoder.cpp +++ b/content/media/omx/RtspOmxDecoder.cpp @@ -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 diff --git a/content/media/omx/RtspOmxDecoder.h b/content/media/omx/RtspOmxDecoder.h index 515d575bb4e9..20b757469c61 100644 --- a/content/media/omx/RtspOmxDecoder.h +++ b/content/media/omx/RtspOmxDecoder.h @@ -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 diff --git a/content/media/omx/RtspOmxReader.cpp b/content/media/omx/RtspOmxReader.cpp index d19d6800a9ad..7ee1922bc5d2 100644 --- a/content/media/omx/RtspOmxReader.cpp +++ b/content/media/omx/RtspOmxReader.cpp @@ -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 diff --git a/content/media/omx/RtspOmxReader.h b/content/media/omx/RtspOmxReader.h index 399ab74bf6a4..f616ce7d0cc8 100644 --- a/content/media/omx/RtspOmxReader.h +++ b/content/media/omx/RtspOmxReader.h @@ -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 diff --git a/dom/bluetooth/BluetoothCommon.h b/dom/bluetooth/BluetoothCommon.h index 2cf6d41eaa25..ac3e488b6f35 100644 --- a/dom/bluetooth/BluetoothCommon.h +++ b/dom/bluetooth/BluetoothCommon.h @@ -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 { diff --git a/dom/bluetooth/bluez/linux/BluetoothDBusService.cpp b/dom/bluetooth/bluez/linux/BluetoothDBusService.cpp index 7dbbc202b6aa..c6bfb8c5487f 100644 --- a/dom/bluetooth/bluez/linux/BluetoothDBusService.cpp +++ b/dom/bluetooth/bluez/linux/BluetoothDBusService.cpp @@ -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 gThreadConnection; - // Only A2DP and HID are authorized. static nsTArray 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 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 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 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 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,11 +1777,11 @@ BluetoothDBusService::StartInternal() * explicitly here. */ if (sAdapterPath.IsEmpty()) { - bool success = mConnection->SendWithReply(OnDefaultAdapterReply, nullptr, - 1000, "/", - DBUS_MANAGER_IFACE, - "DefaultAdapter", - DBUS_TYPE_INVALID); + bool success = connection->SendWithReply(OnDefaultAdapterReply, nullptr, + 1000, "/", + DBUS_MANAGER_IFACE, + "DefaultAdapter", + DBUS_TYPE_INVALID); if (!success) { BT_WARNING("Failed to query default adapter!"); } @@ -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 handler = this; - nsRefPtr 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 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 runnable(aRunnable); - bool success = mConnection->SendWithReply( + RawDBusConnection* connection = GetDBusConnection(); + MOZ_ASSERT(connection); + + bool success = connection->SendWithReply( OnSendDiscoveryMessageReply, static_cast(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 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(serviceClass.forget()), -1, NS_ConvertUTF16toUTF8(aObjectPath).get(), aInterface, NS_ConvertUTF16toUTF8(aMessage).get(), @@ -2259,16 +2250,16 @@ protected: mObjectPath = GetObjectPathFromAddress(sAdapterPath, mDeviceAddresses[mProcessedDeviceAddresses]); - nsRefPtr threadConnection = gThreadConnection; + RawDBusConnection* connection = GetDBusConnection(); - if (!threadConnection.get()) { + if (!connection) { BT_WARNING("%s: DBus connection has been closed.", __FUNCTION__); return false; } nsRefPtr handler = this; - bool success = threadConnection->SendWithReply( + bool success = connection->SendWithReply( BluetoothArrayOfDevicePropertiesReplyHandler::Callback, handler.get(), 1000, NS_ConvertUTF16toUTF8(mObjectPath).get(), @@ -2427,10 +2418,13 @@ BluetoothDBusService::SetProperty(BluetoothObjectType aType, nsRefPtr runnable = aRunnable; + RawDBusConnection* connection = GetDBusConnection(); + MOZ_ASSERT(connection); + // msg is unref'd as part of SendWithReply - bool success = mConnection->SendWithReply(GetVoidCallback, - (void*)aRunnable, - 1000, msg); + bool success = connection->SendWithReply(GetVoidCallback, + (void*)aRunnable, + 1000, msg); if (!success) { BT_WARNING("SendWithReply failed"); return NS_ERROR_FAILURE; @@ -2468,9 +2462,12 @@ BluetoothDBusService::CreatePairedDeviceInternal( nsRefPtr 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 runnable(aRunnable); - bool success = mConnection->SendWithReply( + RawDBusConnection* connection = GetDBusConnection(); + MOZ_ASSERT(connection); + + bool success = connection->SendWithReply( OnRemoveDeviceReply, static_cast(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 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,13 +2970,16 @@ BluetoothDBusService::UpdateSdpRecords(const nsAString& aDeviceAddress, OnUpdateSdpRecordsRunnable* callbackRunnable = new OnUpdateSdpRecordsRunnable(objectPath, aManager); - return mConnection->SendWithReply(DiscoverServicesCallback, - (void*)callbackRunnable, -1, - NS_ConvertUTF16toUTF8(objectPath).get(), - DBUS_DEVICE_IFACE, - "DiscoverServices", - DBUS_TYPE_STRING, &EmptyCString(), - DBUS_TYPE_INVALID); + RawDBusConnection* connection = GetDBusConnection(); + MOZ_ASSERT(connection); + + return connection->SendWithReply(DiscoverServicesCallback, + (void*)callbackRunnable, -1, + NS_ConvertUTF16toUTF8(objectPath).get(), + DBUS_DEVICE_IFACE, + "DiscoverServices", + DBUS_TYPE_STRING, &EmptyCString(), + DBUS_TYPE_INVALID); } void @@ -3144,7 +3156,10 @@ BluetoothDBusService::SendMetaData(const nsAString& aTitle, nsRefPtr 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 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", diff --git a/dom/bluetooth/bluez/linux/BluetoothDBusService.h b/dom/bluetooth/bluez/linux/BluetoothDBusService.h index 251efd2982f0..0d939da9da3d 100644 --- a/dom/bluetooth/bluez/linux/BluetoothDBusService.h +++ b/dom/bluetooth/bluez/linux/BluetoothDBusService.h @@ -194,8 +194,6 @@ private: const char* aInterface, const nsAString& aMessage, mozilla::ipc::DBusReplyCallback aCallback); - - nsRefPtr mConnection; }; END_BLUETOOTH_NAMESPACE diff --git a/dom/browser-element/BrowserElementPanning.js b/dom/browser-element/BrowserElementPanning.js index af22e553e5f7..e2a4b58eb683 100644 --- a/dom/browser-element/BrowserElementPanning.js +++ b/dom/browser-element/BrowserElementPanning.js @@ -45,21 +45,16 @@ 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); + let els = Cc["@mozilla.org/eventlistenerservice;1"] + .getService(Ci.nsIEventListenerService); - events.forEach(function(type) { - // Using the system group for mouse/touch events to avoid - // missing events if .stopPropagation() has been called. - els.addSystemEventListener(global, type, - this.handleEvent.bind(this), - /* useCapture = */ false); - }.bind(this)); - } + events.forEach(function(type) { + // Using the system group for mouse/touch events to avoid + // missing events if .stopPropagation() has been called. + els.addSystemEventListener(global, type, + 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(); - 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 // 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); } } diff --git a/dom/contacts/fallback/ContactService.jsm b/dom/contacts/fallback/ContactService.jsm index fc6abc06af93..5ac0e7a6d251 100644 --- a/dom/contacts/fallback/ContactService.jsm +++ b/dom/contacts/fallback/ContactService.jsm @@ -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: diff --git a/dom/contacts/tests/chrome.ini b/dom/contacts/tests/chrome.ini index 073b9ace36b1..17662e3a2f5e 100644 --- a/dom/contacts/tests/chrome.ini +++ b/dom/contacts/tests/chrome.ini @@ -1,3 +1,6 @@ [DEFAULT] +[test_contacts_shutdown.xul] +skip-if = os == "android" + [test_contacts_upgrade.xul] diff --git a/dom/contacts/tests/test_contacts_shutdown.xul b/dom/contacts/tests/test_contacts_shutdown.xul new file mode 100644 index 000000000000..50cc06c97021 --- /dev/null +++ b/dom/contacts/tests/test_contacts_shutdown.xul @@ -0,0 +1,103 @@ + + + + + + + + + + Mozilla Bug 945948 + + diff --git a/dom/tests/mochitest/general/test_interfaces.html b/dom/tests/mochitest/general/test_interfaces.html index a55b12916683..c744dea8c430 100644 --- a/dom/tests/mochitest/general/test_interfaces.html +++ b/dom/tests/mochitest/general/test_interfaces.html @@ -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"}, diff --git a/dom/webidl/MozNfc.webidl b/dom/webidl/MozNfc.webidl index d903ed588bd8..0560cc0c5741 100644 --- a/dom/webidl/MozNfc.webidl +++ b/dom/webidl/MozNfc.webidl @@ -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); diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp index 1aa0a3b90e17..f59f9abd44a8 100644 --- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -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() == VERTICAL) { + aTo.AppendPrintf(" [vscrollbar=%lld]", GetScrollbarTargetContainerId()); + } + if (GetScrollbarDirection() == HORIZONTAL) { + aTo.AppendPrintf(" [hscrollbar=%lld]", GetScrollbarTargetContainerId()); } if (GetIsFixedPosition()) { aTo.AppendPrintf(" [isFixedPosition anchor=%f,%f]", mAnchor.x, mAnchor.y); diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index a98f023e4c7c..b560e5fce2dc 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -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 mStickyPositionData; - bool mIsScrollbar; FrameMetrics::ViewID mScrollbarTargetId; ScrollDirection mScrollbarDirection; DebugOnly mDebugColorIndex; diff --git a/gfx/layers/composite/AsyncCompositionManager.cpp b/gfx/layers/composite/AsyncCompositionManager.cpp index 1d38bc15dd5c..d92a08f2eb46 100644 --- a/gfx/layers/composite/AsyncCompositionManager.cpp +++ b/gfx/layers/composite/AsyncCompositionManager.cpp @@ -525,7 +525,7 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(TimeStamp aCurrentFram appliedTransform = true; } - if (container->GetIsScrollbar()) { + if (container->GetScrollbarDirection() != Layer::NONE) { ApplyAsyncTransformToScrollbar(container); } return appliedTransform; diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp index 14c16ffc77b9..a1a034ffa564 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -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; } diff --git a/gfx/layers/ipc/LayerTransactionParent.cpp b/gfx/layers/ipc/LayerTransactionParent.cpp index efc338941755..6793eb711d5b 100644 --- a/gfx/layers/ipc/LayerTransactionParent.cpp +++ b/gfx/layers/ipc/LayerTransactionParent.cpp @@ -280,10 +280,8 @@ LayerTransactionParent::RecvUpdate(const InfallibleTArray& cset, common.stickyScrollRangeOuter(), common.stickyScrollRangeInner()); } - if (common.isScrollbar()) { - layer->SetScrollbarData(common.scrollbarTargetContainerId(), - static_cast(common.scrollbarDirection())); - } + layer->SetScrollbarData(common.scrollbarTargetContainerId(), + static_cast(common.scrollbarDirection())); if (PLayerParent* maskLayer = common.maskLayerParent()) { layer->SetMaskLayer(cast(maskLayer)->AsLayer()); } else { diff --git a/gfx/layers/ipc/LayersMessages.ipdlh b/gfx/layers/ipc/LayersMessages.ipdlh index 61b3a32806ce..98b5f2e9ef18 100644 --- a/gfx/layers/ipc/LayersMessages.ipdlh +++ b/gfx/layers/ipc/LayersMessages.ipdlh @@ -198,7 +198,6 @@ struct CommonLayerAttributes { uint64_t stickyScrollContainerId; LayerRect stickyScrollRangeOuter; LayerRect stickyScrollRangeInner; - bool isScrollbar; uint64_t scrollbarTargetContainerId; uint32_t scrollbarDirection; nullable PLayer maskLayer; diff --git a/gfx/layers/ipc/ShadowLayers.cpp b/gfx/layers/ipc/ShadowLayers.cpp index 56e02775af34..ae00a6093bac 100644 --- a/gfx/layers/ipc/ShadowLayers.cpp +++ b/gfx/layers/ipc/ShadowLayers.cpp @@ -501,11 +501,8 @@ ShadowLayerForwarder::EndTransaction(InfallibleTArray* 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(); - } + common.scrollbarTargetContainerId() = mutant->GetScrollbarTargetContainerId(); + common.scrollbarDirection() = mutant->GetScrollbarDirection(); if (Layer* maskLayer = mutant->GetMaskLayer()) { common.maskLayerChild() = Shadow(maskLayer->AsShadowableLayer()); } else { diff --git a/ipc/dbus/DBusThread.cpp b/ipc/dbus/DBusThread.cpp index 346815ad5da1..53b635468220 100644 --- a/ipc/dbus/DBusThread.cpp +++ b/ipc/dbus/DBusThread.cpp @@ -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 mPollData; - nsTArray 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::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(aData); +} + dbus_bool_t DBusWatcher::AddWatchFunction(DBusWatch* aWatch, void* aData) { - MOZ_ASSERT(aData); - DBusWatcher* dbusWatcher = static_cast(aData); - return dbusWatcher->AddWatch(aWatch); + MOZ_ASSERT(!NS_IsMainThread()); + + RawDBusConnection* connection = static_cast(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(aData); - dbusWatcher->RemoveWatch(aWatch); + MOZ_ASSERT(!NS_IsMainThread()); + + DBusWatcher* dbusWatcher = + static_cast(dbus_watch_get_data(aWatch)); + dbusWatcher->StopWatching(); } void DBusWatcher::ToggleWatchFunction(DBusWatch* aWatch, void* aData) { - MOZ_ASSERT(aData); - DBusWatcher* dbusWatcher = static_cast(aData); + MOZ_ASSERT(!NS_IsMainThread()); + + DBusWatcher* dbusWatcher = + static_cast(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(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(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 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 mDBusWatcher; + RawDBusConnection* mConnection; }; -static StaticRefPtr gDBusWatcher; -static StaticRefPtr 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(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 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(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 dbusServiceThread(gDBusServiceThread); - nsRefPtr 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; +} + } } diff --git a/ipc/dbus/DBusThread.h b/ipc/dbus/DBusThread.h index fdce20afce8b..e688b1555935 100644 --- a/ipc/dbus/DBusThread.h +++ b/ipc/dbus/DBusThread.h @@ -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); } } diff --git a/ipc/dbus/RawDBusConnection.cpp b/ipc/dbus/RawDBusConnection.cpp index bc13d2e83b68..588bd8e82dd4 100644 --- a/ipc/dbus/RawDBusConnection.cpp +++ b/ipc/dbus/RawDBusConnection.cpp @@ -5,6 +5,7 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include +#include "base/message_loop.h" #include "mozilla/Monitor.h" #include "nsThreadUtils.h" #include "DBusThread.h" @@ -34,11 +35,15 @@ using namespace mozilla::ipc; namespace mozilla { namespace ipc { -class DBusConnectionSendRunnableBase : public nsRunnable +class DBusConnectionSendTaskBase : public Task { +public: + virtual ~DBusConnectionSendTaskBase() + { } + protected: - DBusConnectionSendRunnableBase(DBusConnection* aConnection, - DBusMessage* aMessage) + 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, - DBusMessage* aMessage) - : DBusConnectionSendRunnableBase(aConnection, aMessage) + DBusConnectionSendTask(DBusConnection* aConnection, + DBusMessage* 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, - DBusMessage* aMessage, - int aTimeout, - DBusReplyCallback aCallback, - void* aData) - : DBusConnectionSendRunnableBase(aConnection, aMessage), + DBusConnectionSendWithReplyTask(DBusConnection* aConnection, + DBusMessage* aMessage, + int aTimeout, + DBusReplyCallback aCallback, + void* aData) + : 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 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 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 t( - new DBusConnectionSendWithReplyRunnable(mConnection, aMessage, - aTimeout, aCallback, aData)); + DBusConnectionSendWithReplyTask* t = + new DBusConnectionSendWithReplyTask(mConnection, aMessage, aTimeout, + aCallback, aData); MOZ_ASSERT(t); nsresult rv = DispatchToDBusThread(t); diff --git a/ipc/dbus/RawDBusConnection.h b/ipc/dbus/RawDBusConnection.h index 616a964b3e2a..06329b7a1006 100644 --- a/ipc/dbus/RawDBusConnection.h +++ b/ipc/dbus/RawDBusConnection.h @@ -14,7 +14,6 @@ #include #include "nscore.h" #include "mozilla/Scoped.h" -#include #include struct DBusConnection; @@ -26,7 +25,7 @@ namespace ipc { typedef void (*DBusReplyCallback)(DBusMessage*, void*); -class RawDBusConnection : public AtomicRefCounted +class RawDBusConnection { struct ScopedDBusConnectionPtrTraits : ScopedFreePtrTraits { diff --git a/layout/base/nsLayoutDebugger.cpp b/layout/base/nsLayoutDebugger.cpp index 5948333193ef..59b955f32385 100644 --- a/layout/base/nsLayoutDebugger.cpp +++ b/layout/base/nsLayoutDebugger.cpp @@ -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, "
  • "); + } + fprintf_stderr(aFile, "%s", aItemName); + PrintDisplayListTo(aBuilder, aList, aFile, aDumpHtml); + if (aDumpHtml) { + fprintf_stderr(aFile, "
  • "); + } +} + +void +nsFrame::PrintDisplayListSet(nsDisplayListBuilder* aBuilder, + const nsDisplayListSet& aSet, + FILE *aFile, + bool aDumpHtml) +{ + if (aDumpHtml) { + fprintf_stderr(aFile, "
      "); + } + 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, "
    "); + } +} + #endif diff --git a/layout/generic/nsFrame.h b/layout/generic/nsFrame.h index deabc6bbd569..c8a89c88d0eb 100644 --- a/layout/generic/nsFrame.h +++ b/layout/generic/nsFrame.h @@ -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 }; diff --git a/testing/xpcshell/xpcshell_b2g.ini b/testing/xpcshell/xpcshell_b2g.ini index 60948a7f0039..025417e3c43e 100644 --- a/testing/xpcshell/xpcshell_b2g.ini +++ b/testing/xpcshell/xpcshell_b2g.ini @@ -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] diff --git a/widget/gonk/HwcComposer2D.cpp b/widget/gonk/HwcComposer2D.cpp index 97556f77f5b0..15c047aefaee 100644 --- a/widget/gonk/HwcComposer2D.cpp +++ b/widget/gonk/HwcComposer2D.cpp @@ -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; } diff --git a/widget/gonk/HwcComposer2D.h b/widget/gonk/HwcComposer2D.h index 2ca4defa0f38..06fa1eddba68 100644 --- a/widget/gonk/HwcComposer2D.h +++ b/widget/gonk/HwcComposer2D.h @@ -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 mPrevReleaseFds; int mPrevRetireFence; nsTArray mHwcLayerMap; + bool mPrepared; }; } // namespace mozilla