зеркало из https://github.com/mozilla/gecko-dev.git
Bug 906019: Implemented non-blocking GetDefaultAdapterPathInternal, r=echou,gyeh
GetDefaultAdapterPathInternal used two blocking DBus operations, namely 'DefaultAdapter' and 'GetProperties'. The latter one depends on the result of the former one. The be non-blocking, GetDefaultAdapterPathInternal first make a non-blocking 'DefaultAdapter' call. Once received, the reply handler non-blockingly calls 'GetProperties' with the values received for 'DefaultAdapter', and put itself in place as this call's reply handler. For this second reply, it finally schedules the Bluetooth reply runnable. --HG-- extra : rebase_source : aa0872a5db69c928ca25723952fe2928ef52d107
This commit is contained in:
Родитель
482dd7c30b
Коммит
88b10d29d8
|
@ -1789,46 +1789,119 @@ BluetoothDBusService::IsEnabledInternal()
|
|||
return mEnabled;
|
||||
}
|
||||
|
||||
class DefaultAdapterPropertiesRunnable : public nsRunnable
|
||||
class DefaultAdapterPathReplyHandler : public DBusReplyHandler
|
||||
{
|
||||
public:
|
||||
DefaultAdapterPropertiesRunnable(BluetoothReplyRunnable* aRunnable)
|
||||
: mRunnable(dont_AddRef(aRunnable))
|
||||
DefaultAdapterPathReplyHandler(BluetoothReplyRunnable* aRunnable)
|
||||
: mRunnable(aRunnable)
|
||||
{
|
||||
MOZ_ASSERT(mRunnable);
|
||||
}
|
||||
|
||||
nsresult Run()
|
||||
void Handle(DBusMessage* aReply) MOZ_OVERRIDE
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_ASSERT(!NS_IsMainThread()); // DBus thread
|
||||
|
||||
BluetoothValue v;
|
||||
if (!aReply || (dbus_message_get_type(aReply) == DBUS_MESSAGE_TYPE_ERROR)) {
|
||||
const char* errStr = "Timeout in DefaultAdapterPathReplyHandler";
|
||||
if (aReply) {
|
||||
errStr = dbus_message_get_error_name(aReply);
|
||||
if (!errStr) {
|
||||
errStr = "Bluetooth DBus Error";
|
||||
}
|
||||
}
|
||||
DispatchBluetoothReply(mRunnable, BluetoothValue(),
|
||||
NS_ConvertUTF8toUTF16(errStr));
|
||||
return;
|
||||
}
|
||||
|
||||
bool success;
|
||||
nsAutoString replyError;
|
||||
if (!GetDefaultAdapterPath(v, replyError)) {
|
||||
DispatchBluetoothReply(mRunnable, v, replyError);
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (mAdapterPath.IsEmpty()) {
|
||||
success = HandleDefaultAdapterPathReply(aReply, replyError);
|
||||
} else {
|
||||
success = HandleGetPropertiesReply(aReply, replyError);
|
||||
}
|
||||
|
||||
DBusError err;
|
||||
dbus_error_init(&err);
|
||||
if (!success) {
|
||||
DispatchBluetoothReply(mRunnable, BluetoothValue(), replyError);
|
||||
}
|
||||
}
|
||||
|
||||
nsString objectPath = v.get_nsString();
|
||||
v = InfallibleTArray<BluetoothNamedValue>();
|
||||
if (!GetPropertiesInternal(objectPath, DBUS_ADAPTER_IFACE, v)) {
|
||||
NS_WARNING("Getting properties failed!");
|
||||
return NS_ERROR_FAILURE;
|
||||
protected:
|
||||
bool HandleDefaultAdapterPathReply(DBusMessage* aReply,
|
||||
nsAString& aReplyError)
|
||||
{
|
||||
BluetoothValue value;
|
||||
DBusError error;
|
||||
dbus_error_init(&error);
|
||||
|
||||
MOZ_ASSERT(!NS_IsMainThread()); // DBus thread
|
||||
|
||||
UnpackObjectPathMessage(aReply, &error, value, aReplyError);
|
||||
|
||||
if (!aReplyError.IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mAdapterPath = value.get_nsString();
|
||||
|
||||
// Acquire another reference to this reply handler
|
||||
nsRefPtr<DefaultAdapterPathReplyHandler> handler = this;
|
||||
|
||||
nsRefPtr<RawDBusConnection> threadConnection = gThreadConnection;
|
||||
|
||||
if (!threadConnection.get()) {
|
||||
aReplyError = NS_LITERAL_STRING("DBus connection has been closed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool success = dbus_func_args_async(threadConnection->GetConnection(), 1000,
|
||||
DefaultAdapterPathReplyHandler::Callback,
|
||||
handler.get(),
|
||||
NS_ConvertUTF16toUTF8(mAdapterPath).get(),
|
||||
DBUS_ADAPTER_IFACE, "GetProperties",
|
||||
DBUS_TYPE_INVALID);
|
||||
if (!success) {
|
||||
aReplyError = NS_LITERAL_STRING("dbus_func_args_async failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
handler.forget();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HandleGetPropertiesReply(DBusMessage* aReply,
|
||||
nsAutoString& aReplyError)
|
||||
{
|
||||
BluetoothValue value;
|
||||
DBusError error;
|
||||
dbus_error_init(&error);
|
||||
|
||||
MOZ_ASSERT(!NS_IsMainThread()); // DBus thread
|
||||
|
||||
bool success = UnpackPropertiesMessage(aReply, &error, value,
|
||||
DBUS_ADAPTER_IFACE);
|
||||
if (!success) {
|
||||
aReplyError = NS_ConvertUTF8toUTF16(error.message);
|
||||
return false;
|
||||
}
|
||||
|
||||
// We have to manually attach the path to the rest of the elements
|
||||
v.get_ArrayOfBluetoothNamedValue().AppendElement(
|
||||
BluetoothNamedValue(NS_LITERAL_STRING("Path"), objectPath));
|
||||
value.get_ArrayOfBluetoothNamedValue().AppendElement(
|
||||
BluetoothNamedValue(NS_LITERAL_STRING("Path"), mAdapterPath));
|
||||
|
||||
DispatchBluetoothReply(mRunnable, v, replyError);
|
||||
// Dispatch result
|
||||
DispatchBluetoothReply(mRunnable, value, aReplyError);
|
||||
|
||||
return NS_OK;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<BluetoothReplyRunnable> mRunnable;
|
||||
nsString mAdapterPath;
|
||||
};
|
||||
|
||||
nsresult
|
||||
|
@ -1843,14 +1916,18 @@ BluetoothDBusService::GetDefaultAdapterPathInternal(
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<BluetoothReplyRunnable> runnable = aRunnable;
|
||||
nsRefPtr<nsRunnable> func(new DefaultAdapterPropertiesRunnable(runnable));
|
||||
if (NS_FAILED(mBluetoothCommandThread->Dispatch(func, NS_DISPATCH_NORMAL))) {
|
||||
NS_WARNING("Cannot dispatch firmware loading task!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsRefPtr<DefaultAdapterPathReplyHandler> handler =
|
||||
new DefaultAdapterPathReplyHandler(aRunnable);
|
||||
bool success = dbus_func_args_async(mConnection, 1000,
|
||||
DefaultAdapterPathReplyHandler::Callback,
|
||||
handler.get(),
|
||||
"/",
|
||||
DBUS_MANAGER_IFACE, "DefaultAdapter",
|
||||
DBUS_TYPE_INVALID);
|
||||
NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
|
||||
|
||||
handler.forget();
|
||||
|
||||
runnable.forget();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче