summaryrefslogtreecommitdiff
path: root/chromium/dbus
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2015-06-18 14:10:49 +0200
committerOswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>2015-06-18 13:53:24 +0000
commit813fbf95af77a531c57a8c497345ad2c61d475b3 (patch)
tree821b2c8de8365f21b6c9ba17a236fb3006a1d506 /chromium/dbus
parentaf6588f8d723931a298c995fa97259bb7f7deb55 (diff)
downloadqtwebengine-chromium-813fbf95af77a531c57a8c497345ad2c61d475b3.tar.gz
BASELINE: Update chromium to 44.0.2403.47
Change-Id: Ie056fedba95cf5e5c76b30c4b2c80fca4764aa2f Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
Diffstat (limited to 'chromium/dbus')
-rw-r--r--chromium/dbus/BUILD.gn37
-rw-r--r--chromium/dbus/OWNERS1
-rw-r--r--chromium/dbus/bus.cc56
-rw-r--r--chromium/dbus/bus.h19
-rw-r--r--chromium/dbus/bus_unittest.cc28
-rw-r--r--chromium/dbus/dbus_statistics_unittest.cc8
-rw-r--r--chromium/dbus/end_to_end_async_unittest.cc54
-rw-r--r--chromium/dbus/end_to_end_sync_unittest.cc4
-rw-r--r--chromium/dbus/exported_object.cc21
-rw-r--r--chromium/dbus/exported_object.h3
-rw-r--r--chromium/dbus/file_descriptor.cc9
-rw-r--r--chromium/dbus/file_descriptor.h10
-rw-r--r--chromium/dbus/message_unittest.cc6
-rw-r--r--chromium/dbus/mock_object_proxy.h8
-rw-r--r--chromium/dbus/mock_unittest.cc6
-rw-r--r--chromium/dbus/object_manager.cc9
-rw-r--r--chromium/dbus/object_manager_unittest.cc19
-rw-r--r--chromium/dbus/object_proxy.cc67
-rw-r--r--chromium/dbus/object_proxy.h5
-rw-r--r--chromium/dbus/object_proxy_unittest.cc6
-rw-r--r--chromium/dbus/property.cc147
-rw-r--r--chromium/dbus/property.h47
-rw-r--r--chromium/dbus/property_unittest.cc159
-rw-r--r--chromium/dbus/signal_sender_verification_unittest.cc4
-rw-r--r--chromium/dbus/test_server.cc2
-rw-r--r--chromium/dbus/test_service.cc38
-rw-r--r--chromium/dbus/test_service.h10
-rw-r--r--chromium/dbus/util.h7
-rw-r--r--chromium/dbus/values_util_unittest.cc4
29 files changed, 561 insertions, 233 deletions
diff --git a/chromium/dbus/BUILD.gn b/chromium/dbus/BUILD.gn
index 830bd19406c..a133e724b64 100644
--- a/chromium/dbus/BUILD.gn
+++ b/chromium/dbus/BUILD.gn
@@ -2,6 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//testing/test.gni")
import("//third_party/protobuf/proto_library.gni")
component("dbus") {
@@ -29,28 +30,28 @@ component("dbus") {
"scoped_dbus_error.h",
"string_util.cc",
"string_util.h",
- "values_util.cc",
- "values_util.h",
"util.cc",
"util.h",
+ "values_util.cc",
+ "values_util.h",
]
- defines = [
- "DBUS_IMPLEMENTATION",
- ]
+ defines = [ "DBUS_IMPLEMENTATION" ]
deps = [
- "//base",
"//third_party/protobuf:protobuf_lite",
]
-
- public_configs = [
- "//build/config/linux:dbus",
+ public_deps = [
+ "//base",
]
+
+ public_configs = [ "//build/config/linux:dbus" ]
}
proto_library("test_proto") {
- sources = [ "test_proto.proto" ]
+ sources = [
+ "test_proto.proto",
+ ]
}
# This target contains mocks that can be used to write unit tests without
@@ -68,14 +69,14 @@ source_set("test_support") {
"mock_object_proxy.h",
]
- deps = [
+ public_deps = [
":dbus",
+ ]
+ deps = [
"//testing/gmock",
]
- configs += [
- "//build/config/linux:dbus",
- ]
+ configs += [ "//build/config/linux:dbus" ]
}
test("dbus_unittests") {
@@ -108,9 +109,7 @@ test("dbus_unittests") {
"//third_party/protobuf:protobuf_lite",
]
- configs += [
- "//build/config/linux:dbus",
- ]
+ configs += [ "//build/config/linux:dbus" ]
}
executable("dbus_test_server") {
@@ -127,7 +126,5 @@ executable("dbus_test_server") {
"//base/test:test_support",
]
- configs += [
- "//build/config/linux:dbus",
- ]
+ configs += [ "//build/config/linux:dbus" ]
}
diff --git a/chromium/dbus/OWNERS b/chromium/dbus/OWNERS
index cfe5da564ca..fc425e6db42 100644
--- a/chromium/dbus/OWNERS
+++ b/chromium/dbus/OWNERS
@@ -1,3 +1,4 @@
+hashimoto@chromium.org
keybuk@chromium.org
satorux@chromium.org
stevenjb@chromium.org
diff --git a/chromium/dbus/bus.cc b/chromium/dbus/bus.cc
index e9e77a5dcd4..2f1300a25e3 100644
--- a/chromium/dbus/bus.cc
+++ b/chromium/dbus/bus.cc
@@ -47,9 +47,7 @@ class Watch : public base::MessagePumpLibevent::Watcher {
dbus_watch_set_data(raw_watch_, this, NULL);
}
- virtual ~Watch() {
- dbus_watch_set_data(raw_watch_, NULL, NULL);
- }
+ ~Watch() override { dbus_watch_set_data(raw_watch_, NULL, NULL); }
// Returns true if the underlying file descriptor is ready to be watched.
bool IsReadyToBeWatched() {
@@ -84,13 +82,13 @@ class Watch : public base::MessagePumpLibevent::Watcher {
private:
// Implement MessagePumpLibevent::Watcher.
- virtual void OnFileCanReadWithoutBlocking(int file_descriptor) override {
+ void OnFileCanReadWithoutBlocking(int file_descriptor) override {
const bool success = dbus_watch_handle(raw_watch_, DBUS_WATCH_READABLE);
CHECK(success) << "Unable to allocate memory";
}
// Implement MessagePumpLibevent::Watcher.
- virtual void OnFileCanWriteWithoutBlocking(int file_descriptor) override {
+ void OnFileCanWriteWithoutBlocking(int file_descriptor) override {
const bool success = dbus_watch_handle(raw_watch_, DBUS_WATCH_WRITABLE);
CHECK(success) << "Unable to allocate memory";
}
@@ -197,8 +195,7 @@ Bus::Bus(const Options& options)
shutdown_completed_(false),
num_pending_watches_(0),
num_pending_timeouts_(0),
- address_(options.address),
- on_disconnected_closure_(options.disconnected_callback) {
+ address_(options.address) {
// This is safe to call multiple times.
dbus_threads_init_default();
// The origin message loop is unnecessary if the client uses synchronous
@@ -690,7 +687,7 @@ void Bus::Send(DBusMessage* request, uint32* serial) {
CHECK(success) << "Unable to allocate memory";
}
-bool Bus::AddFilterFunction(DBusHandleMessageFunction filter_function,
+void Bus::AddFilterFunction(DBusHandleMessageFunction filter_function,
void* user_data) {
DCHECK(connection_);
AssertOnDBusThread();
@@ -701,17 +698,16 @@ bool Bus::AddFilterFunction(DBusHandleMessageFunction filter_function,
filter_functions_added_.end()) {
VLOG(1) << "Filter function already exists: " << filter_function
<< " with associated data: " << user_data;
- return false;
+ return;
}
const bool success = dbus_connection_add_filter(
connection_, filter_function, user_data, NULL);
CHECK(success) << "Unable to allocate memory";
filter_functions_added_.insert(filter_data_pair);
- return true;
}
-bool Bus::RemoveFilterFunction(DBusHandleMessageFunction filter_function,
+void Bus::RemoveFilterFunction(DBusHandleMessageFunction filter_function,
void* user_data) {
DCHECK(connection_);
AssertOnDBusThread();
@@ -723,12 +719,11 @@ bool Bus::RemoveFilterFunction(DBusHandleMessageFunction filter_function,
VLOG(1) << "Requested to remove an unknown filter function: "
<< filter_function
<< " with associated data: " << user_data;
- return false;
+ return;
}
dbus_connection_remove_filter(connection_, filter_function, user_data);
filter_functions_added_.erase(filter_data_pair);
- return true;
}
void Bus::AddMatch(const std::string& match_rule, DBusError* error) {
@@ -826,8 +821,7 @@ void Bus::ProcessAllIncomingDataIfAny() {
return;
// It is safe and necessary to call dbus_connection_get_dispatch_status even
- // if the connection is lost. Otherwise we will miss "Disconnected" signal.
- // (crbug.com/174431)
+ // if the connection is lost.
if (dbus_connection_get_dispatch_status(connection_) ==
DBUS_DISPATCH_DATA_REMAINS) {
while (dbus_connection_dispatch(connection_) ==
@@ -948,11 +942,8 @@ void Bus::ListenForServiceOwnerChangeInternal(
if (!Connect() || !SetUpAsyncOperations())
return;
- if (service_owner_changed_listener_map_.empty()) {
- bool filter_added =
- AddFilterFunction(Bus::OnServiceOwnerChangedFilter, this);
- DCHECK(filter_added);
- }
+ if (service_owner_changed_listener_map_.empty())
+ AddFilterFunction(Bus::OnServiceOwnerChangedFilter, this);
ServiceOwnerChangedListenerMap::iterator it =
service_owner_changed_listener_map_.find(service_name);
@@ -1026,11 +1017,8 @@ void Bus::UnlistenForServiceOwnerChangeInternal(
// And remove |service_owner_changed_listener_map_| entry.
service_owner_changed_listener_map_.erase(it);
- if (service_owner_changed_listener_map_.empty()) {
- bool filter_removed =
- RemoveFilterFunction(Bus::OnServiceOwnerChangedFilter, this);
- DCHECK(filter_removed);
- }
+ if (service_owner_changed_listener_map_.empty())
+ RemoveFilterFunction(Bus::OnServiceOwnerChangedFilter, this);
}
dbus_bool_t Bus::OnAddWatch(DBusWatch* raw_watch) {
@@ -1112,19 +1100,6 @@ void Bus::OnDispatchStatusChanged(DBusConnection* connection,
this));
}
-void Bus::OnConnectionDisconnected(DBusConnection* connection) {
- AssertOnDBusThread();
-
- if (!on_disconnected_closure_.is_null())
- GetOriginTaskRunner()->PostTask(FROM_HERE, on_disconnected_closure_);
-
- if (!connection)
- return;
- DCHECK(!dbus_connection_get_is_connected(connection));
-
- ShutdownAndBlock();
-}
-
void Bus::OnServiceOwnerChanged(DBusMessage* message) {
DCHECK(message);
AssertOnDBusThread();
@@ -1215,9 +1190,8 @@ DBusHandlerResult Bus::OnConnectionDisconnectedFilter(
if (dbus_message_is_signal(message,
DBUS_INTERFACE_LOCAL,
kDisconnectedSignal)) {
- Bus* self = static_cast<Bus*>(data);
- self->OnConnectionDisconnected(connection);
- return DBUS_HANDLER_RESULT_HANDLED;
+ // Abort when the connection is lost.
+ LOG(FATAL) << "D-Bus connection was disconnected. Aborting.";
}
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
diff --git a/chromium/dbus/bus.h b/chromium/dbus/bus.h
index 544d31fc169..f9f0dfd9cf6 100644
--- a/chromium/dbus/bus.h
+++ b/chromium/dbus/bus.h
@@ -218,12 +218,6 @@ class CHROME_DBUS_EXPORT Bus : public base::RefCountedThreadSafe<Bus> {
// // Do something.
//
std::string address;
-
- // If the connection with dbus-daemon is closed, |disconnected_callback|
- // will be called on the origin thread. This is also called when the
- // disonnection by ShutdownAndBlock. |disconnected_callback| can be null
- // callback
- base::Closure disconnected_callback;
};
// Creates a Bus object. The actual connection will be established when
@@ -471,24 +465,23 @@ class CHROME_DBUS_EXPORT Bus : public base::RefCountedThreadSafe<Bus> {
virtual void Send(DBusMessage* request, uint32* serial);
// Adds the message filter function. |filter_function| will be called
- // when incoming messages are received. Returns true on success.
+ // when incoming messages are received.
//
// When a new incoming message arrives, filter functions are called in
// the order that they were added until the the incoming message is
// handled by a filter function.
//
// The same filter function associated with the same user data cannot be
- // added more than once. Returns false for this case.
+ // added more than once.
//
// BLOCKING CALL.
- virtual bool AddFilterFunction(DBusHandleMessageFunction filter_function,
+ virtual void AddFilterFunction(DBusHandleMessageFunction filter_function,
void* user_data);
// Removes the message filter previously added by AddFilterFunction().
- // Returns true on success.
//
// BLOCKING CALL.
- virtual bool RemoveFilterFunction(DBusHandleMessageFunction filter_function,
+ virtual void RemoveFilterFunction(DBusHandleMessageFunction filter_function,
void* user_data);
// Adds the match rule. Messages that match the rule will be processed
@@ -671,9 +664,6 @@ class CHROME_DBUS_EXPORT Bus : public base::RefCountedThreadSafe<Bus> {
void OnDispatchStatusChanged(DBusConnection* connection,
DBusDispatchStatus status);
- // Called when the connection is diconnected.
- void OnConnectionDisconnected(DBusConnection* connection);
-
// Called when a service owner change occurs.
void OnServiceOwnerChanged(DBusMessage* message);
@@ -761,7 +751,6 @@ class CHROME_DBUS_EXPORT Bus : public base::RefCountedThreadSafe<Bus> {
int num_pending_timeouts_;
std::string address_;
- base::Closure on_disconnected_closure_;
DISALLOW_COPY_AND_ASSIGN(Bus);
};
diff --git a/chromium/dbus/bus_unittest.cc b/chromium/dbus/bus_unittest.cc
index d6955698390..22ccddc57cd 100644
--- a/chromium/dbus/bus_unittest.cc
+++ b/chromium/dbus/bus_unittest.cc
@@ -21,13 +21,6 @@ namespace dbus {
namespace {
-// Used to test AddFilterFunction().
-DBusHandlerResult DummyHandler(DBusConnection* connection,
- DBusMessage* raw_message,
- void* user_data) {
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-}
-
// Test helper for BusTest.ListenForServiceOwnerChange that wraps a
// base::RunLoop. At Run() time, the caller pass in the expected number of
// quit calls, and at QuitIfConditionIsSatisified() time, only quit the RunLoop
@@ -284,27 +277,6 @@ TEST(BusTest, ShutdownAndBlockWithDBusThread) {
dbus_thread.Stop();
}
-TEST(BusTest, AddFilterFunction) {
- Bus::Options options;
- scoped_refptr<Bus> bus = new Bus(options);
- // Should connect before calling AddFilterFunction().
- bus->Connect();
-
- int data1 = 100;
- int data2 = 200;
- ASSERT_TRUE(bus->AddFilterFunction(&DummyHandler, &data1));
- // Cannot add the same function with the same data.
- ASSERT_FALSE(bus->AddFilterFunction(&DummyHandler, &data1));
- // Can add the same function with different data.
- ASSERT_TRUE(bus->AddFilterFunction(&DummyHandler, &data2));
-
- ASSERT_TRUE(bus->RemoveFilterFunction(&DummyHandler, &data1));
- ASSERT_FALSE(bus->RemoveFilterFunction(&DummyHandler, &data1));
- ASSERT_TRUE(bus->RemoveFilterFunction(&DummyHandler, &data2));
-
- bus->ShutdownAndBlock();
-}
-
TEST(BusTest, DoubleAddAndRemoveMatch) {
Bus::Options options;
scoped_refptr<Bus> bus = new Bus(options);
diff --git a/chromium/dbus/dbus_statistics_unittest.cc b/chromium/dbus/dbus_statistics_unittest.cc
index 0c0dd034972..6260a63ebe9 100644
--- a/chromium/dbus/dbus_statistics_unittest.cc
+++ b/chromium/dbus/dbus_statistics_unittest.cc
@@ -15,13 +15,9 @@ class DBusStatisticsTest : public testing::Test {
DBusStatisticsTest() {
}
- virtual void SetUp() override {
- statistics::Initialize();
- }
+ void SetUp() override { statistics::Initialize(); }
- virtual void TearDown() override {
- statistics::Shutdown();
- }
+ void TearDown() override { statistics::Shutdown(); }
protected:
void AddTestMethodCalls() {
diff --git a/chromium/dbus/end_to_end_async_unittest.cc b/chromium/dbus/end_to_end_async_unittest.cc
index 15f410eadc0..10516b99971 100644
--- a/chromium/dbus/end_to_end_async_unittest.cc
+++ b/chromium/dbus/end_to_end_async_unittest.cc
@@ -35,9 +35,7 @@ const int kHugePayloadSize = 64 << 20; // 64 MB
// ExportedObject.
class EndToEndAsyncTest : public testing::Test {
public:
- EndToEndAsyncTest() : on_disconnected_call_count_(0) {}
-
- virtual void SetUp() {
+ void SetUp() override {
// Make the main thread not to allow IO.
base::ThreadRestrictions::SetIOAllowed(false);
@@ -60,8 +58,6 @@ class EndToEndAsyncTest : public testing::Test {
bus_options.bus_type = Bus::SESSION;
bus_options.connection_type = Bus::PRIVATE;
bus_options.dbus_task_runner = dbus_thread_->message_loop_proxy();
- bus_options.disconnected_callback =
- base::Bind(&EndToEndAsyncTest::OnDisconnected, base::Unretained(this));
bus_ = new Bus(bus_options);
object_proxy_ = bus_->GetObjectProxy(
"org.chromium.TestService",
@@ -116,7 +112,7 @@ class EndToEndAsyncTest : public testing::Test {
run_loop_->Run();
}
- virtual void TearDown() {
+ void TearDown() override {
bus_->ShutdownOnDBusThreadAndBlock();
// Shut down the service.
@@ -248,12 +244,6 @@ class EndToEndAsyncTest : public testing::Test {
run_loop_->Quit();
}
- // Called when the connection with dbus-daemon is disconnected.
- void OnDisconnected() {
- run_loop_->Quit();
- ++on_disconnected_call_count_;
- }
-
// Wait for the hey signal to be received.
void WaitForTestSignal() {
// OnTestSignal() will quit the message loop.
@@ -274,7 +264,6 @@ class EndToEndAsyncTest : public testing::Test {
std::string test_signal_string_;
// Text message from "Test" signal delivered to root.
std::string root_test_signal_string_;
- int on_disconnected_call_count_;
};
TEST_F(EndToEndAsyncTest, Echo) {
@@ -429,6 +418,33 @@ TEST_F(EndToEndAsyncTest, TimeoutWithErrorCallback) {
ASSERT_EQ(DBUS_ERROR_NO_REPLY, error_names_[0]);
}
+TEST_F(EndToEndAsyncTest, CancelPendingCalls) {
+ const char* kHello = "hello";
+
+ // Create the method call.
+ MethodCall method_call("org.chromium.TestInterface", "Echo");
+ MessageWriter writer(&method_call);
+ writer.AppendString(kHello);
+
+ // Call the method.
+ const int timeout_ms = ObjectProxy::TIMEOUT_USE_DEFAULT;
+ CallMethod(&method_call, timeout_ms);
+
+ // Remove the object proxy before receiving the result.
+ // This results in cancelling the pending method call.
+ bus_->RemoveObjectProxy("org.chromium.TestService",
+ ObjectPath("/org/chromium/TestObject"),
+ base::Bind(&base::DoNothing));
+
+ // We shouldn't receive any responses. Wait for a while just to make sure.
+ run_loop_.reset(new base::RunLoop);
+ message_loop_.PostDelayedTask(FROM_HERE,
+ run_loop_->QuitClosure(),
+ TestTimeouts::tiny_timeout());
+ run_loop_->Run();
+ EXPECT_TRUE(response_strings_.empty());
+}
+
// Tests calling a method that sends its reply asynchronously.
TEST_F(EndToEndAsyncTest, AsyncEcho) {
const char* kHello = "hello";
@@ -588,22 +604,12 @@ TEST_F(EndToEndAsyncTest, TestHugeSignal) {
ASSERT_EQ(kHugeMessage, test_signal_string_);
}
-TEST_F(EndToEndAsyncTest, DisconnectedSignal) {
- bus_->GetDBusTaskRunner()->PostTask(FROM_HERE,
- base::Bind(&Bus::ClosePrivateConnection,
- base::Unretained(bus_.get())));
- // OnDisconnected callback quits message loop.
- run_loop_.reset(new base::RunLoop);
- run_loop_->Run();
- EXPECT_EQ(1, on_disconnected_call_count_);
-}
-
class SignalMultipleHandlerTest : public EndToEndAsyncTest {
public:
SignalMultipleHandlerTest() {
}
- virtual void SetUp() {
+ void SetUp() override {
// Set up base class.
EndToEndAsyncTest::SetUp();
diff --git a/chromium/dbus/end_to_end_sync_unittest.cc b/chromium/dbus/end_to_end_sync_unittest.cc
index e3b316ab6f8..1167d96650b 100644
--- a/chromium/dbus/end_to_end_sync_unittest.cc
+++ b/chromium/dbus/end_to_end_sync_unittest.cc
@@ -21,7 +21,7 @@ class EndToEndSyncTest : public testing::Test {
EndToEndSyncTest() {
}
- virtual void SetUp() {
+ void SetUp() override {
// Start the test service;
TestService::Options options;
test_service_.reset(new TestService(options));
@@ -40,7 +40,7 @@ class EndToEndSyncTest : public testing::Test {
ASSERT_FALSE(client_bus_->HasDBusThread());
}
- virtual void TearDown() {
+ void TearDown() override {
test_service_->ShutdownAndBlock();
test_service_->Stop();
client_bus_->ShutdownAndBlock();
diff --git a/chromium/dbus/exported_object.cc b/chromium/dbus/exported_object.cc
index 107d2e5dd17..669b871e35b 100644
--- a/chromium/dbus/exported_object.cc
+++ b/chromium/dbus/exported_object.cc
@@ -91,12 +91,21 @@ void ExportedObject::SendSignal(Signal* signal) {
dbus_message_ref(signal_message);
const base::TimeTicks start_time = base::TimeTicks::Now();
- bus_->GetDBusTaskRunner()->PostTask(
- FROM_HERE,
- base::Bind(&ExportedObject::SendSignalInternal,
- this,
- start_time,
- signal_message));
+ if (bus_->GetDBusTaskRunner()->RunsTasksOnCurrentThread()) {
+ // The Chrome OS power manager doesn't use a dedicated TaskRunner for
+ // sending DBus messages. Sending signals asynchronously can cause an
+ // inversion in the message order if the power manager calls
+ // ObjectProxy::CallMethodAndBlock() before going back to the top level of
+ // the MessageLoop: crbug.com/472361.
+ SendSignalInternal(start_time, signal_message);
+ } else {
+ bus_->GetDBusTaskRunner()->PostTask(
+ FROM_HERE,
+ base::Bind(&ExportedObject::SendSignalInternal,
+ this,
+ start_time,
+ signal_message));
+ }
}
void ExportedObject::Unregister() {
diff --git a/chromium/dbus/exported_object.h b/chromium/dbus/exported_object.h
index 5f74dc2b1e4..89de096199c 100644
--- a/chromium/dbus/exported_object.h
+++ b/chromium/dbus/exported_object.h
@@ -92,7 +92,8 @@ class CHROME_DBUS_EXPORT ExportedObject
OnExportedCallback on_exported_callback);
// Requests to send the signal from this object. The signal will be sent
- // asynchronously from the message loop in the D-Bus thread.
+ // synchronously if this method is called from the message loop in the D-Bus
+ // thread and asynchronously otherwise.
virtual void SendSignal(Signal* signal);
// Unregisters the object from the bus. The Bus object will take care of
diff --git a/chromium/dbus/file_descriptor.cc b/chromium/dbus/file_descriptor.cc
index d2d6a31f1e3..e607fc01356 100644
--- a/chromium/dbus/file_descriptor.cc
+++ b/chromium/dbus/file_descriptor.cc
@@ -2,12 +2,21 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/bind.h"
#include "base/files/file.h"
+#include "base/location.h"
#include "base/logging.h"
+#include "base/threading/worker_pool.h"
#include "dbus/file_descriptor.h"
namespace dbus {
+void CHROME_DBUS_EXPORT FileDescriptor::Deleter::operator()(
+ FileDescriptor* fd) {
+ base::WorkerPool::PostTask(
+ FROM_HERE, base::Bind(&base::DeletePointer<FileDescriptor>, fd), false);
+}
+
FileDescriptor::~FileDescriptor() {
if (owner_)
base::File auto_closer(value_);
diff --git a/chromium/dbus/file_descriptor.h b/chromium/dbus/file_descriptor.h
index 19e0b1ab44b..a01ee6ee011 100644
--- a/chromium/dbus/file_descriptor.h
+++ b/chromium/dbus/file_descriptor.h
@@ -6,6 +6,7 @@
#define DBUS_FILE_DESCRIPTOR_H_
#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
#include "dbus/dbus_export.h"
namespace dbus {
@@ -33,6 +34,12 @@ namespace dbus {
// with i/o restrictions.
class CHROME_DBUS_EXPORT FileDescriptor {
public:
+ // This provides a simple way to pass around file descriptors since they must
+ // be closed on a thread that is allowed to perform I/O.
+ struct Deleter {
+ void CHROME_DBUS_EXPORT operator()(FileDescriptor* fd);
+ };
+
// Permits initialization without a value for passing to
// dbus::MessageReader::PopFileDescriptor to fill in and from int values.
FileDescriptor() : value_(-1), owner_(false), valid_(false) {}
@@ -70,6 +77,9 @@ class CHROME_DBUS_EXPORT FileDescriptor {
DISALLOW_COPY_AND_ASSIGN(FileDescriptor);
};
+using ScopedFileDescriptor =
+ scoped_ptr<FileDescriptor, FileDescriptor::Deleter>;
+
} // namespace dbus
#endif // DBUS_FILE_DESCRIPTOR_H_
diff --git a/chromium/dbus/message_unittest.cc b/chromium/dbus/message_unittest.cc
index 0eaea8395f5..2c13d08c6b9 100644
--- a/chromium/dbus/message_unittest.cc
+++ b/chromium/dbus/message_unittest.cc
@@ -4,6 +4,8 @@
#include "dbus/message.h"
+#include <stdint.h>
+
#include "base/basictypes.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
@@ -400,7 +402,7 @@ TEST(MessageTest, CreateComplexMessageAndReadIt) {
MessageWriter dict_entry_writer(NULL);
dict_array_writer.OpenDictEntry(&dict_entry_writer);
dict_entry_writer.AppendString("foo");
- dict_entry_writer.AppendInt64(GG_INT64_C(1234567890123456789));
+ dict_entry_writer.AppendInt64(INT64_C(1234567890123456789));
dict_array_writer.CloseContainer(&dict_entry_writer);
}
variant_writer.CloseContainer(&dict_array_writer);
@@ -475,7 +477,7 @@ TEST(MessageTest, CreateComplexMessageAndReadIt) {
EXPECT_EQ("foo", string_value);
int64 int64_value = 0;
ASSERT_TRUE(dict_entry_reader.PopInt64(&int64_value));
- EXPECT_EQ(GG_INT64_C(1234567890123456789), int64_value);
+ EXPECT_EQ(INT64_C(1234567890123456789), int64_value);
}
ASSERT_FALSE(dict_array_reader.HasMoreData());
}
diff --git a/chromium/dbus/mock_object_proxy.h b/chromium/dbus/mock_object_proxy.h
index 7c61b47b428..66f485ad06f 100644
--- a/chromium/dbus/mock_object_proxy.h
+++ b/chromium/dbus/mock_object_proxy.h
@@ -29,7 +29,7 @@ class MockObjectProxy : public ObjectProxy {
Response*(MethodCall* method_call,
int timeout_ms,
ScopedDBusError* error));
- virtual scoped_ptr<Response> CallMethodAndBlockWithErrorDetails(
+ scoped_ptr<Response> CallMethodAndBlockWithErrorDetails(
MethodCall* method_call,
int timeout_ms,
ScopedDBusError* error) override {
@@ -38,8 +38,8 @@ class MockObjectProxy : public ObjectProxy {
}
MOCK_METHOD2(MockCallMethodAndBlock, Response*(MethodCall* method_call,
int timeout_ms));
- virtual scoped_ptr<Response> CallMethodAndBlock(MethodCall* method_call,
- int timeout_ms) override {
+ scoped_ptr<Response> CallMethodAndBlock(MethodCall* method_call,
+ int timeout_ms) override {
return scoped_ptr<Response>(MockCallMethodAndBlock(method_call,
timeout_ms));
}
@@ -58,7 +58,7 @@ class MockObjectProxy : public ObjectProxy {
MOCK_METHOD0(Detach, void());
protected:
- virtual ~MockObjectProxy();
+ ~MockObjectProxy() override;
};
} // namespace dbus
diff --git a/chromium/dbus/mock_unittest.cc b/chromium/dbus/mock_unittest.cc
index bfdc5a30c28..6b2a521127a 100644
--- a/chromium/dbus/mock_unittest.cc
+++ b/chromium/dbus/mock_unittest.cc
@@ -29,7 +29,7 @@ class MockTest : public testing::Test {
MockTest() {
}
- virtual void SetUp() {
+ void SetUp() override {
// Create a mock bus.
Bus::Options options;
options.bus_type = Bus::SYSTEM;
@@ -66,9 +66,7 @@ class MockTest : public testing::Test {
EXPECT_CALL(*mock_bus_.get(), ShutdownAndBlock()).WillOnce(Return());
}
- virtual void TearDown() {
- mock_bus_->ShutdownAndBlock();
- }
+ void TearDown() override { mock_bus_->ShutdownAndBlock(); }
// Called when the response is received.
void OnResponse(Response* response) {
diff --git a/chromium/dbus/object_manager.cc b/chromium/dbus/object_manager.cc
index f754bb693fd..851fee44b2e 100644
--- a/chromium/dbus/object_manager.cc
+++ b/chromium/dbus/object_manager.cc
@@ -155,8 +155,7 @@ void ObjectManager::CleanUp() {
if (!setup_success_)
return;
- if (!bus_->RemoveFilterFunction(&ObjectManager::HandleMessageThunk, this))
- LOG(ERROR) << "Failed to remove filter function";
+ bus_->RemoveFilterFunction(&ObjectManager::HandleMessageThunk, this);
ScopedDBusError error;
bus_->RemoveMatch(match_rule_, error.get());
@@ -216,10 +215,7 @@ bool ObjectManager::SetupMatchRuleAndFilter() {
kPropertiesInterface,
kPropertiesChanged);
- if (!bus_->AddFilterFunction(&ObjectManager::HandleMessageThunk, this)) {
- LOG(ERROR) << "ObjectManager failed to add filter function";
- return false;
- }
+ bus_->AddFilterFunction(&ObjectManager::HandleMessageThunk, this);
ScopedDBusError error;
bus_->AddMatch(match_rule, error.get());
@@ -486,6 +482,7 @@ void ObjectManager::RemoveInterface(const ObjectPath& object_path,
interface->ObjectRemoved(object_path, interface_name);
}
+ delete piter->second;
object->properties_map.erase(piter);
if (object->properties_map.empty()) {
diff --git a/chromium/dbus/object_manager_unittest.cc b/chromium/dbus/object_manager_unittest.cc
index cd02c5e13c1..76ddb85fa8f 100644
--- a/chromium/dbus/object_manager_unittest.cc
+++ b/chromium/dbus/object_manager_unittest.cc
@@ -48,10 +48,9 @@ class ObjectManagerTest
}
};
- virtual PropertySet* CreateProperties(
- ObjectProxy* object_proxy,
- const ObjectPath& object_path,
- const std::string& interface_name) override {
+ PropertySet* CreateProperties(ObjectProxy* object_proxy,
+ const ObjectPath& object_path,
+ const std::string& interface_name) override {
Properties* properties = new Properties(
object_proxy, interface_name,
base::Bind(&ObjectManagerTest::OnPropertyChanged,
@@ -59,7 +58,7 @@ class ObjectManagerTest
return static_cast<PropertySet*>(properties);
}
- virtual void SetUp() {
+ void SetUp() override {
// Make the main thread not to allow IO.
base::ThreadRestrictions::SetIOAllowed(false);
@@ -93,7 +92,7 @@ class ObjectManagerTest
WaitForObject();
}
- virtual void TearDown() {
+ void TearDown() override {
bus_->ShutdownOnDBusThreadAndBlock();
// Shut down the service.
@@ -126,15 +125,15 @@ class ObjectManagerTest
protected:
// Called when an object is added.
- virtual void ObjectAdded(const ObjectPath& object_path,
- const std::string& interface_name) override {
+ void ObjectAdded(const ObjectPath& object_path,
+ const std::string& interface_name) override {
added_objects_.push_back(std::make_pair(object_path, interface_name));
run_loop_->Quit();
}
// Called when an object is removed.
- virtual void ObjectRemoved(const ObjectPath& object_path,
- const std::string& interface_name) override {
+ void ObjectRemoved(const ObjectPath& object_path,
+ const std::string& interface_name) override {
removed_objects_.push_back(std::make_pair(object_path, interface_name));
run_loop_->Quit();
}
diff --git a/chromium/dbus/object_proxy.cc b/chromium/dbus/object_proxy.cc
index 59584f2ce34..441dc757bd7 100644
--- a/chromium/dbus/object_proxy.cc
+++ b/chromium/dbus/object_proxy.cc
@@ -55,12 +55,12 @@ ObjectProxy::ObjectProxy(Bus* bus,
: bus_(bus),
service_name_(service_name),
object_path_(object_path),
- filter_added_(false),
ignore_service_unknown_errors_(
options & IGNORE_SERVICE_UNKNOWN_ERRORS) {
}
ObjectProxy::~ObjectProxy() {
+ DCHECK(pending_calls_.empty());
}
// Originally we tried to make |method_call| a const reference, but we
@@ -169,17 +169,20 @@ void ObjectProxy::ConnectToSignal(const std::string& interface_name,
OnConnectedCallback on_connected_callback) {
bus_->AssertOnOriginThread();
- base::PostTaskAndReplyWithResult(
- bus_->GetDBusTaskRunner(),
- FROM_HERE,
- base::Bind(&ObjectProxy::ConnectToSignalInternal,
- this,
- interface_name,
- signal_name,
- signal_callback),
- base::Bind(on_connected_callback,
- interface_name,
- signal_name));
+ if (bus_->HasDBusThread()) {
+ base::PostTaskAndReplyWithResult(
+ bus_->GetDBusTaskRunner(), FROM_HERE,
+ base::Bind(&ObjectProxy::ConnectToSignalInternal, this, interface_name,
+ signal_name, signal_callback),
+ base::Bind(on_connected_callback, interface_name, signal_name));
+ } else {
+ // If the bus doesn't have a dedicated dbus thread we need to call
+ // ConnectToSignalInternal directly otherwise we might miss a signal
+ // that is currently queued if we do a PostTask.
+ const bool success =
+ ConnectToSignalInternal(interface_name, signal_name, signal_callback);
+ on_connected_callback.Run(interface_name, signal_name, success);
+ }
}
void ObjectProxy::SetNameOwnerChangedCallback(
@@ -202,22 +205,24 @@ void ObjectProxy::WaitForServiceToBeAvailable(
void ObjectProxy::Detach() {
bus_->AssertOnDBusThread();
- if (filter_added_) {
- if (!bus_->RemoveFilterFunction(&ObjectProxy::HandleMessageThunk, this)) {
- LOG(ERROR) << "Failed to remove filter function";
- }
- }
+ if (bus_->is_connected())
+ bus_->RemoveFilterFunction(&ObjectProxy::HandleMessageThunk, this);
- for (std::set<std::string>::iterator iter = match_rules_.begin();
- iter != match_rules_.end(); ++iter) {
+ for (const auto& match_rule : match_rules_) {
ScopedDBusError error;
- bus_->RemoveMatch(*iter, error.get());
+ bus_->RemoveMatch(match_rule, error.get());
if (error.is_set()) {
// There is nothing we can do to recover, so just print the error.
- LOG(ERROR) << "Failed to remove match rule: " << *iter;
+ LOG(ERROR) << "Failed to remove match rule: " << match_rule;
}
}
match_rules_.clear();
+
+ for (auto* pending_call : pending_calls_) {
+ dbus_pending_call_cancel(pending_call);
+ dbus_pending_call_unref(pending_call);
+ }
+ pending_calls_.clear();
}
// static
@@ -276,9 +281,9 @@ void ObjectProxy::StartAsyncMethodCall(int timeout_ms,
pending_call,
&ObjectProxy::OnPendingCallIsCompleteThunk,
data,
- NULL);
+ &DeleteVoidPointer<OnPendingCallIsCompleteData>);
CHECK(success) << "Unable to allocate memory";
- dbus_pending_call_unref(pending_call);
+ pending_calls_.insert(pending_call);
// It's now safe to unref the request message.
dbus_message_unref(request_message);
@@ -298,6 +303,10 @@ void ObjectProxy::OnPendingCallIsComplete(DBusPendingCall* pending_call,
start_time,
response_message);
bus_->GetOriginTaskRunner()->PostTask(FROM_HERE, task);
+
+ // Remove the pending call from the set.
+ pending_calls_.erase(pending_call);
+ dbus_pending_call_unref(pending_call);
}
void ObjectProxy::RunResponseCallback(ResponseCallback response_callback,
@@ -368,7 +377,6 @@ void ObjectProxy::OnPendingCallIsCompleteThunk(DBusPendingCall* pending_call,
data->response_callback,
data->error_callback,
data->start_time);
- delete data;
}
bool ObjectProxy::ConnectToNameOwnerChangedSignal() {
@@ -377,15 +385,8 @@ bool ObjectProxy::ConnectToNameOwnerChangedSignal() {
if (!bus_->Connect() || !bus_->SetUpAsyncOperations())
return false;
- // We should add the filter only once. Otherwise, HandleMessage() will
- // be called more than once.
- if (!filter_added_) {
- if (bus_->AddFilterFunction(&ObjectProxy::HandleMessageThunk, this)) {
- filter_added_ = true;
- } else {
- LOG(ERROR) << "Failed to add filter function";
- }
- }
+ bus_->AddFilterFunction(&ObjectProxy::HandleMessageThunk, this);
+
// Add a match_rule listening NameOwnerChanged for the well-known name
// |service_name_|.
const std::string name_owner_changed_match_rule =
diff --git a/chromium/dbus/object_proxy.h b/chromium/dbus/object_proxy.h
index 1400328fda0..c0211b1db61 100644
--- a/chromium/dbus/object_proxy.h
+++ b/chromium/dbus/object_proxy.h
@@ -297,9 +297,6 @@ class CHROME_DBUS_EXPORT ObjectProxy
std::string service_name_;
ObjectPath object_path_;
- // True if the message filter was added.
- bool filter_added_;
-
// The method table where keys are absolute signal names (i.e. interface
// name + signal name), and values are lists of the corresponding callbacks.
typedef std::map<std::string, std::vector<SignalCallback> > MethodTable;
@@ -319,6 +316,8 @@ class CHROME_DBUS_EXPORT ObjectProxy
// Known name owner of the well-known bus name represented by |service_name_|.
std::string service_name_owner_;
+ std::set<DBusPendingCall*> pending_calls_;
+
DISALLOW_COPY_AND_ASSIGN(ObjectProxy);
};
diff --git a/chromium/dbus/object_proxy_unittest.cc b/chromium/dbus/object_proxy_unittest.cc
index 246058ddd5d..22130b64bc3 100644
--- a/chromium/dbus/object_proxy_unittest.cc
+++ b/chromium/dbus/object_proxy_unittest.cc
@@ -15,7 +15,7 @@ namespace {
class ObjectProxyTest : public testing::Test {
protected:
- virtual void SetUp() override {
+ void SetUp() override {
Bus::Options bus_options;
bus_options.bus_type = Bus::SESSION;
bus_options.connection_type = Bus::PRIVATE;
@@ -25,9 +25,7 @@ class ObjectProxyTest : public testing::Test {
"org.chromium.TestService", ObjectPath("/org/chromium/TestObject"));
}
- virtual void TearDown() override {
- bus_->ShutdownAndBlock();
- }
+ void TearDown() override { bus_->ShutdownAndBlock(); }
base::MessageLoopForIO message_loop_;
scoped_refptr<Bus> bus_;
diff --git a/chromium/dbus/property.cc b/chromium/dbus/property.cc
index 9475a0728a6..66b86c0486d 100644
--- a/chromium/dbus/property.cc
+++ b/chromium/dbus/property.cc
@@ -21,10 +21,10 @@ namespace dbus {
void PropertyBase::Init(PropertySet* property_set, const std::string& name) {
DCHECK(!property_set_);
property_set_ = property_set;
+ is_valid_ = false;
name_ = name;
}
-
//
// PropertySet implementation.
//
@@ -78,10 +78,10 @@ void PropertySet::ChangedReceived(Signal* signal) {
<< "expected dictionary: " << signal->ToString();
}
- // TODO(keybuk): dbus properties api has invalidated properties array
- // on the end, we don't handle this right now because I don't know of
- // any service that sends it - or what they expect us to do with it.
- // Add later when we need it.
+ if (!InvalidatePropertiesFromReader(&reader)) {
+ LOG(WARNING) << "Property changed signal has wrong parameters: "
+ << "expected array to invalidate: " << signal->ToString();
+ }
}
void PropertySet::ChangedConnected(const std::string& interface_name,
@@ -115,8 +115,15 @@ void PropertySet::OnGet(PropertyBase* property, GetCallback callback,
}
MessageReader reader(response);
- if (property->PopValueFromReader(&reader))
+ if (property->PopValueFromReader(&reader)) {
+ property->set_valid(true);
NotifyPropertyChanged(property->name());
+ } else {
+ if (property->is_valid()) {
+ property->set_valid(false);
+ NotifyPropertyChanged(property->name());
+ }
+ }
if (!callback.is_null())
callback.Run(response);
@@ -199,13 +206,42 @@ bool PropertySet::UpdatePropertyFromReader(MessageReader* reader) {
PropertyBase* property = it->second;
if (property->PopValueFromReader(reader)) {
+ property->set_valid(true);
NotifyPropertyChanged(name);
return true;
} else {
+ if (property->is_valid()) {
+ property->set_valid(false);
+ NotifyPropertyChanged(property->name());
+ }
return false;
}
}
+bool PropertySet::InvalidatePropertiesFromReader(MessageReader* reader) {
+ DCHECK(reader);
+ MessageReader array_reader(NULL);
+ if (!reader->PopArray(&array_reader))
+ return false;
+
+ while (array_reader.HasMoreData()) {
+ std::string name;
+ if (!array_reader.PopString(&name))
+ return false;
+
+ PropertiesMap::iterator it = properties_map_.find(name);
+ if (it == properties_map_.end())
+ continue;
+
+ PropertyBase* property = it->second;
+ if (property->is_valid()) {
+ property->set_valid(false);
+ NotifyPropertyChanged(property->name());
+ }
+ }
+
+ return true;
+}
void PropertySet::NotifyPropertyChanged(const std::string& name) {
if (!property_changed_callback_.is_null())
@@ -478,6 +514,103 @@ void Property<std::vector<uint8> >::AppendSetValueToWriter(
writer->CloseContainer(&variant_writer);
}
+//
+// Property<std::map<std::string, std::string>> specialization.
+//
+
+template <>
+bool Property<std::map<std::string, std::string>>::PopValueFromReader(
+ MessageReader* reader) {
+ MessageReader variant_reader(NULL);
+ MessageReader array_reader(NULL);
+ if (!reader->PopVariant(&variant_reader) ||
+ !variant_reader.PopArray(&array_reader))
+ return false;
+ value_.clear();
+ while (array_reader.HasMoreData()) {
+ dbus::MessageReader dict_entry_reader(NULL);
+ if (!array_reader.PopDictEntry(&dict_entry_reader))
+ return false;
+ std::string key;
+ std::string value;
+ if (!dict_entry_reader.PopString(&key) ||
+ !dict_entry_reader.PopString(&value))
+ return false;
+ value_[key] = value;
+ }
+ return true;
+}
+
+template <>
+void Property<std::map<std::string, std::string>>::AppendSetValueToWriter(
+ MessageWriter* writer) {
+ MessageWriter variant_writer(NULL);
+ MessageWriter dict_writer(NULL);
+ writer->OpenVariant("a{ss}", &variant_writer);
+ variant_writer.OpenArray("{ss}", &dict_writer);
+ for (const auto& pair : set_value_) {
+ dbus::MessageWriter entry_writer(NULL);
+ dict_writer.OpenDictEntry(&entry_writer);
+ entry_writer.AppendString(pair.first);
+ entry_writer.AppendString(pair.second);
+ dict_writer.CloseContainer(&entry_writer);
+ }
+ variant_writer.CloseContainer(&dict_writer);
+ writer->CloseContainer(&variant_writer);
+}
+
+//
+// Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>
+// specialization.
+//
+
+template <>
+bool Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>::
+ PopValueFromReader(MessageReader* reader) {
+ MessageReader variant_reader(NULL);
+ MessageReader array_reader(NULL);
+ if (!reader->PopVariant(&variant_reader) ||
+ !variant_reader.PopArray(&array_reader))
+ return false;
+
+ value_.clear();
+ while (array_reader.HasMoreData()) {
+ dbus::MessageReader struct_reader(NULL);
+ if (!array_reader.PopStruct(&struct_reader))
+ return false;
+
+ std::pair<std::vector<uint8_t>, uint16_t> entry;
+ const uint8* bytes = NULL;
+ size_t length = 0;
+ if (!struct_reader.PopArrayOfBytes(&bytes, &length))
+ return false;
+ entry.first.assign(bytes, bytes + length);
+ if (!struct_reader.PopUint16(&entry.second))
+ return false;
+ value_.push_back(entry);
+ }
+ return true;
+}
+
+template <>
+void Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>::
+ AppendSetValueToWriter(MessageWriter* writer) {
+ MessageWriter variant_writer(NULL);
+ MessageWriter array_writer(NULL);
+ writer->OpenVariant("a(ayq)", &variant_writer);
+ variant_writer.OpenArray("(ayq)", &array_writer);
+ for (const auto& pair : set_value_) {
+ dbus::MessageWriter struct_writer(nullptr);
+ array_writer.OpenStruct(&struct_writer);
+ struct_writer.AppendArrayOfBytes(std::get<0>(pair).data(),
+ std::get<0>(pair).size());
+ struct_writer.AppendUint16(std::get<1>(pair));
+ array_writer.CloseContainer(&struct_writer);
+ }
+ variant_writer.CloseContainer(&array_writer);
+ writer->CloseContainer(&variant_writer);
+}
+
template class Property<uint8>;
template class Property<bool>;
template class Property<int16>;
@@ -492,5 +625,7 @@ template class Property<ObjectPath>;
template class Property<std::vector<std::string> >;
template class Property<std::vector<ObjectPath> >;
template class Property<std::vector<uint8> >;
+template class Property<std::map<std::string, std::string>>;
+template class Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>;
} // namespace dbus
diff --git a/chromium/dbus/property.h b/chromium/dbus/property.h
index a20e0ad466f..321f4dbd078 100644
--- a/chromium/dbus/property.h
+++ b/chromium/dbus/property.h
@@ -7,6 +7,8 @@
#include <map>
#include <string>
+#include <utility>
+#include <vector>
#include "base/basictypes.h"
#include "base/bind.h"
@@ -132,7 +134,7 @@ class PropertySet;
// used by PropertySet.
class PropertyBase {
public:
- PropertyBase() : property_set_(NULL) {}
+ PropertyBase() : property_set_(nullptr), is_valid_(false) {}
// Initializes the |property_set| and property |name| so that method
// calls may be made from this class. This method is called by
@@ -154,11 +156,17 @@ class PropertyBase {
// }
const std::string& name() const { return name_; }
+ // Returns true if property is valid, false otherwise.
+ bool is_valid() const { return is_valid_; }
+
+ // Allows to mark Property as valid or invalid.
+ void set_valid(bool is_valid) { is_valid_ = is_valid; }
+
// Method used by PropertySet to retrieve the value from a MessageReader,
// no knowledge of the contained type is required, this method returns
// true if its expected type was found, false if not.
// Implementation provided by specialization.
- virtual bool PopValueFromReader(MessageReader*) = 0;
+ virtual bool PopValueFromReader(MessageReader* reader) = 0;
// Method used by PropertySet to append the set value to a MessageWriter,
// no knowledge of the contained type is required.
@@ -179,6 +187,8 @@ class PropertyBase {
// no ownership is taken and |property_set_| must outlive this class.
PropertySet* property_set_;
+ bool is_valid_;
+
// Name of the property.
std::string name_;
@@ -229,7 +239,7 @@ class CHROME_DBUS_EXPORT PropertySet {
// Methods connected by ConnectSignals() and called by dbus:: when
// a property is changed. Sub-classes may override if the property
// changed signal provides different arguments.
- virtual void ChangedReceived(Signal*);
+ virtual void ChangedReceived(Signal* signal);
virtual void ChangedConnected(const std::string& interface_name,
const std::string& signal_name,
bool success);
@@ -300,6 +310,10 @@ class CHROME_DBUS_EXPORT PropertySet {
}
private:
+ // Invalidates properties by reading an array of names, from
+ // |message_reader|. Returns false if message is in incorrect format.
+ bool InvalidatePropertiesFromReader(MessageReader* reader);
+
// Pointer to object proxy for making method calls, no ownership is taken
// so this must outlive this class.
ObjectProxy* object_proxy_;
@@ -376,17 +390,17 @@ class CHROME_DBUS_EXPORT Property : public PropertyBase {
// Method used by PropertySet to retrieve the value from a MessageReader,
// no knowledge of the contained type is required, this method returns
// true if its expected type was found, false if not.
- virtual bool PopValueFromReader(MessageReader*);
+ bool PopValueFromReader(MessageReader* reader) override;
// Method used by PropertySet to append the set value to a MessageWriter,
// no knowledge of the contained type is required.
// Implementation provided by specialization.
- virtual void AppendSetValueToWriter(MessageWriter* writer);
+ void AppendSetValueToWriter(MessageWriter* writer) override;
// Method used by test and stub implementations of dbus::PropertySet::Set
// to replace the property value with the set value without using a
// dbus::MessageReader.
- virtual void ReplaceValueWithSetValue() {
+ void ReplaceValueWithSetValue() override {
value_ = set_value_;
property_set()->NotifyPropertyChanged(name());
}
@@ -398,6 +412,10 @@ class CHROME_DBUS_EXPORT Property : public PropertyBase {
property_set()->NotifyPropertyChanged(name());
}
+ // Method used by test and stub implementations to directly set the
+ // |set_value_| of a property.
+ void ReplaceSetValueForTesting(const T& value) { set_value_ = value; }
+
private:
// Current cached value of the property.
T value_;
@@ -485,6 +503,23 @@ template <> void Property<std::vector<uint8> >::AppendSetValueToWriter(
MessageWriter* writer);
extern template class Property<std::vector<uint8> >;
+template <>
+bool Property<std::map<std::string, std::string>>::PopValueFromReader(
+ MessageReader* reader);
+template <>
+void Property<std::map<std::string, std::string>>::AppendSetValueToWriter(
+ MessageWriter* writer);
+extern template class Property<std::map<std::string, std::string>>;
+
+template <>
+bool Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>::
+ PopValueFromReader(MessageReader* reader);
+template <>
+void Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>::
+ AppendSetValueToWriter(MessageWriter* writer);
+extern template class Property<
+ std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>;
+
} // namespace dbus
#endif // DBUS_PROPERTY_H_
diff --git a/chromium/dbus/property_unittest.cc b/chromium/dbus/property_unittest.cc
index 879a9a60665..5208f848915 100644
--- a/chromium/dbus/property_unittest.cc
+++ b/chromium/dbus/property_unittest.cc
@@ -12,6 +12,7 @@
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
+#include "base/strings/string_number_conversions.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "dbus/bus.h"
@@ -26,8 +27,7 @@ namespace dbus {
// Property<>.
class PropertyTest : public testing::Test {
public:
- PropertyTest() {
- }
+ PropertyTest() {}
struct Properties : public PropertySet {
Property<std::string> name;
@@ -49,7 +49,7 @@ class PropertyTest : public testing::Test {
}
};
- virtual void SetUp() {
+ void SetUp() override {
// Make the main thread not to allow IO.
base::ThreadRestrictions::SetIOAllowed(false);
@@ -87,7 +87,7 @@ class PropertyTest : public testing::Test {
properties_->GetAll();
}
- virtual void TearDown() {
+ void TearDown() override {
bus_->ShutdownOnDBusThreadAndBlock();
// Shut down the service.
@@ -109,6 +109,10 @@ class PropertyTest : public testing::Test {
run_loop_->Quit();
}
+ // Generic method callback, that might be used together with
+ // WaitForMethodCallback to test wether method was succesfully called.
+ void MethodCallback(Response* response) { run_loop_->Quit(); }
+
protected:
// Called when a property value is updated.
void OnPropertyChanged(const std::string& name) {
@@ -134,6 +138,12 @@ class PropertyTest : public testing::Test {
WaitForUpdates(kExpectedSignalUpdates);
}
+ // Waits until MethodCallback is called.
+ void WaitForMethodCallback() {
+ run_loop_.reset(new base::RunLoop);
+ run_loop_->Run();
+ }
+
// Waits for the callback. |id| is the string bound to the callback when
// the method call is made that identifies it and distinguishes from any
// other; you can set this to whatever you wish.
@@ -158,9 +168,14 @@ class PropertyTest : public testing::Test {
};
TEST_F(PropertyTest, InitialValues) {
+ EXPECT_FALSE(properties_->name.is_valid());
+ EXPECT_FALSE(properties_->version.is_valid());
+
WaitForGetAll();
+ EXPECT_TRUE(properties_->name.is_valid());
EXPECT_EQ("TestService", properties_->name.value());
+ EXPECT_TRUE(properties_->version.is_valid());
EXPECT_EQ(10, properties_->version.value());
std::vector<std::string> methods = properties_->methods.value();
@@ -277,4 +292,140 @@ TEST_F(PropertyTest, Set) {
EXPECT_EQ("NewService", properties_->name.value());
}
+TEST_F(PropertyTest, Invalidate) {
+ WaitForGetAll();
+
+ EXPECT_TRUE(properties_->name.is_valid());
+
+ // Invalidate name.
+ MethodCall method_call("org.chromium.TestInterface", "PerformAction");
+ MessageWriter writer(&method_call);
+ writer.AppendString("InvalidateProperty");
+ writer.AppendObjectPath(ObjectPath("/org/chromium/TestService"));
+ object_proxy_->CallMethod(
+ &method_call, ObjectProxy::TIMEOUT_USE_DEFAULT,
+ base::Bind(&PropertyTest::MethodCallback, base::Unretained(this)));
+ WaitForMethodCallback();
+
+ // TestService sends a property update.
+ WaitForUpdates(1);
+
+ EXPECT_FALSE(properties_->name.is_valid());
+
+ // Set name to something valid.
+ properties_->name.Set("NewService",
+ base::Bind(&PropertyTest::PropertyCallback,
+ base::Unretained(this), "Set"));
+ WaitForCallback("Set");
+
+ // TestService sends a property update.
+ WaitForUpdates(1);
+
+ EXPECT_TRUE(properties_->name.is_valid());
+}
+
+TEST(PropertyTestStatic, ReadWriteStringMap) {
+ scoped_ptr<Response> message(Response::CreateEmpty());
+ MessageWriter writer(message.get());
+ MessageWriter variant_writer(NULL);
+ MessageWriter variant_array_writer(NULL);
+ MessageWriter struct_entry_writer(NULL);
+
+ writer.OpenVariant("a{ss}", &variant_writer);
+ variant_writer.OpenArray("{ss}", &variant_array_writer);
+ const char* items[] = {"One", "Two", "Three", "Four"};
+ for (unsigned i = 0; i < arraysize(items); ++i) {
+ variant_array_writer.OpenDictEntry(&struct_entry_writer);
+ struct_entry_writer.AppendString(items[i]);
+ struct_entry_writer.AppendString(base::UintToString(i + 1));
+ variant_array_writer.CloseContainer(&struct_entry_writer);
+ }
+ variant_writer.CloseContainer(&variant_array_writer);
+ writer.CloseContainer(&variant_writer);
+
+ MessageReader reader(message.get());
+ Property<std::map<std::string, std::string>> string_map;
+ EXPECT_TRUE(string_map.PopValueFromReader(&reader));
+ ASSERT_EQ(4U, string_map.value().size());
+ EXPECT_EQ("1", string_map.value().at("One"));
+ EXPECT_EQ("2", string_map.value().at("Two"));
+ EXPECT_EQ("3", string_map.value().at("Three"));
+ EXPECT_EQ("4", string_map.value().at("Four"));
+}
+
+TEST(PropertyTestStatic, SerializeStringMap) {
+ std::map<std::string, std::string> test_map;
+ test_map["Hi"] = "There";
+ test_map["Map"] = "Test";
+ test_map["Random"] = "Text";
+
+ scoped_ptr<Response> message(Response::CreateEmpty());
+ MessageWriter writer(message.get());
+
+ Property<std::map<std::string, std::string>> string_map;
+ string_map.ReplaceSetValueForTesting(test_map);
+ string_map.AppendSetValueToWriter(&writer);
+
+ MessageReader reader(message.get());
+ EXPECT_TRUE(string_map.PopValueFromReader(&reader));
+ EXPECT_EQ(test_map, string_map.value());
+}
+
+TEST(PropertyTestStatic, ReadWriteNetAddressArray) {
+ scoped_ptr<Response> message(Response::CreateEmpty());
+ MessageWriter writer(message.get());
+ MessageWriter variant_writer(NULL);
+ MessageWriter variant_array_writer(NULL);
+ MessageWriter struct_entry_writer(NULL);
+
+ writer.OpenVariant("a(ayq)", &variant_writer);
+ variant_writer.OpenArray("(ayq)", &variant_array_writer);
+ uint8 ip_bytes[] = {0x54, 0x65, 0x73, 0x74, 0x30};
+ for (uint16 i = 0; i < 5; ++i) {
+ variant_array_writer.OpenStruct(&struct_entry_writer);
+ ip_bytes[4] = 0x30 + i;
+ struct_entry_writer.AppendArrayOfBytes(ip_bytes, arraysize(ip_bytes));
+ struct_entry_writer.AppendUint16(i);
+ variant_array_writer.CloseContainer(&struct_entry_writer);
+ }
+ variant_writer.CloseContainer(&variant_array_writer);
+ writer.CloseContainer(&variant_writer);
+
+ MessageReader reader(message.get());
+ Property<std::vector<std::pair<std::vector<uint8>, uint16>>> ip_list;
+ EXPECT_TRUE(ip_list.PopValueFromReader(&reader));
+
+ ASSERT_EQ(5U, ip_list.value().size());
+ size_t item_index = 0;
+ for (auto& item : ip_list.value()) {
+ ASSERT_EQ(5U, item.first.size());
+ ip_bytes[4] = 0x30 + item_index;
+ EXPECT_EQ(0, memcmp(ip_bytes, item.first.data(), 5U));
+ EXPECT_EQ(item_index, item.second);
+ ++item_index;
+ }
+}
+
+TEST(PropertyTestStatic, SerializeNetAddressArray) {
+ std::vector<std::pair<std::vector<uint8>, uint16>> test_list;
+
+ uint8 ip_bytes[] = {0x54, 0x65, 0x73, 0x74, 0x30};
+ for (uint16 i = 0; i < 5; ++i) {
+ ip_bytes[4] = 0x30 + i;
+ std::vector<uint8> bytes(ip_bytes, ip_bytes + arraysize(ip_bytes));
+ test_list.push_back(make_pair(bytes, 16));
+ }
+
+ scoped_ptr<Response> message(Response::CreateEmpty());
+ MessageWriter writer(message.get());
+
+ Property<std::vector<std::pair<std::vector<uint8>, uint16>>> ip_list;
+ ip_list.ReplaceSetValueForTesting(test_list);
+ ip_list.AppendSetValueToWriter(&writer);
+
+ MessageReader reader(message.get());
+ EXPECT_TRUE(ip_list.PopValueFromReader(&reader));
+ EXPECT_EQ(test_list, ip_list.value());
+}
+
} // namespace dbus
diff --git a/chromium/dbus/signal_sender_verification_unittest.cc b/chromium/dbus/signal_sender_verification_unittest.cc
index c8589f8b641..0f718a4817b 100644
--- a/chromium/dbus/signal_sender_verification_unittest.cc
+++ b/chromium/dbus/signal_sender_verification_unittest.cc
@@ -28,7 +28,7 @@ class SignalSenderVerificationTest : public testing::Test {
on_ownership_called_(false) {
}
- virtual void SetUp() {
+ void SetUp() override {
base::StatisticsRecorder::Initialize();
// Make the main thread not to allow IO.
@@ -94,7 +94,7 @@ class SignalSenderVerificationTest : public testing::Test {
ASSERT_FALSE(latest_name_owner_.empty());
}
- virtual void TearDown() {
+ void TearDown() override {
bus_->ShutdownOnDBusThreadAndBlock();
// Shut down the service.
diff --git a/chromium/dbus/test_server.cc b/chromium/dbus/test_server.cc
index 88f751f7eb5..7e4722de9e9 100644
--- a/chromium/dbus/test_server.cc
+++ b/chromium/dbus/test_server.cc
@@ -10,7 +10,7 @@
int main(int argc, char** argv) {
base::AtExitManager exit_manager;
- CommandLine::Init(argc, argv);
+ base::CommandLine::Init(argc, argv);
TestTimeouts::Initialize();
base::Thread* dbus_thread = new base::Thread("D-Bus Thread");
diff --git a/chromium/dbus/test_service.cc b/chromium/dbus/test_service.cc
index 1ec20702467..2c148697d23 100644
--- a/chromium/dbus/test_service.cc
+++ b/chromium/dbus/test_service.cc
@@ -4,6 +4,9 @@
#include "dbus/test_service.h"
+#include <string>
+#include <vector>
+
#include "base/bind.h"
#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
@@ -485,7 +488,7 @@ void TestService::PerformAction(
RemoveObject(object_path);
} else if (action == "SetSendImmediatePropertiesChanged") {
SetSendImmediatePropertiesChanged();
- } if (action == "ReleaseOwnership") {
+ } else if (action == "ReleaseOwnership") {
ReleaseOwnership(base::Bind(&TestService::PerformActionResponse,
base::Unretained(this),
method_call, response_sender));
@@ -495,6 +498,8 @@ void TestService::PerformAction(
base::Unretained(this),
method_call, response_sender));
return;
+ } else if (action == "InvalidateProperty") {
+ SendPropertyInvalidatedSignal();
}
scoped_ptr<Response> response = Response::FromMethodCall(method_call);
@@ -702,6 +707,37 @@ void TestService::SendPropertyChangedSignalInternal(const std::string& name) {
array_writer.CloseContainer(&dict_entry_writer);
writer.CloseContainer(&array_writer);
+ MessageWriter invalidated_array_writer(NULL);
+
+ writer.OpenArray("s", &invalidated_array_writer);
+ writer.CloseContainer(&invalidated_array_writer);
+
+ exported_object_->SendSignal(&signal);
+}
+
+void TestService::SendPropertyInvalidatedSignal() {
+ message_loop()->PostTask(
+ FROM_HERE, base::Bind(&TestService::SendPropertyInvalidatedSignalInternal,
+ base::Unretained(this)));
+}
+
+void TestService::SendPropertyInvalidatedSignalInternal() {
+ Signal signal(kPropertiesInterface, kPropertiesChanged);
+ MessageWriter writer(&signal);
+ writer.AppendString("org.chromium.TestInterface");
+
+ MessageWriter array_writer(NULL);
+ MessageWriter dict_entry_writer(NULL);
+
+ writer.OpenArray("{sv}", &array_writer);
+ writer.CloseContainer(&array_writer);
+
+ MessageWriter invalidated_array_writer(NULL);
+
+ writer.OpenArray("s", &invalidated_array_writer);
+ invalidated_array_writer.AppendString("Name");
+ writer.CloseContainer(&invalidated_array_writer);
+
exported_object_->SendSignal(&signal);
}
diff --git a/chromium/dbus/test_service.h b/chromium/dbus/test_service.h
index cc7d5211f91..de4aa720ac7 100644
--- a/chromium/dbus/test_service.h
+++ b/chromium/dbus/test_service.h
@@ -46,7 +46,7 @@ class TestService : public base::Thread {
static const int kNumMethodsToExport;
explicit TestService(const Options& options);
- virtual ~TestService();
+ ~TestService() override;
// Starts the service in a separate thread.
// Returns true if the thread is started successfully.
@@ -106,7 +106,7 @@ class TestService : public base::Thread {
bool success);
// base::Thread override.
- virtual void Run(base::MessageLoop* message_loop) override;
+ void Run(base::MessageLoop* message_loop) override;
//
// Exported methods.
@@ -167,6 +167,12 @@ class TestService : public base::Thread {
// Helper function for SendPropertyChangedSignal().
void SendPropertyChangedSignalInternal(const std::string& name);
+ // Sends a property invalidated signal for the name property.
+ void SendPropertyInvalidatedSignal();
+
+ // Helper function for SendPropertyInvalidatedSignal().
+ void SendPropertyInvalidatedSignalInternal();
+
// Helper function for RequestOwnership().
void RequestOwnershipInternal(base::Callback<void(bool)> callback);
diff --git a/chromium/dbus/util.h b/chromium/dbus/util.h
index b983b6fdb86..b05834ddd6b 100644
--- a/chromium/dbus/util.h
+++ b/chromium/dbus/util.h
@@ -23,6 +23,13 @@ CHROME_DBUS_EXPORT std::string GetAbsoluteMemberName(
const std::string& interface_name,
const std::string& member_name);
+// Similar to base::DeletePointer, but takes void* as an argument.
+// Used as DBusFreeFunction.
+template<typename T>
+void DeleteVoidPointer(void* memory) {
+ delete static_cast<T*>(memory);
+}
+
} // namespace dbus
#endif // DBUS_UTIL_H_
diff --git a/chromium/dbus/values_util_unittest.cc b/chromium/dbus/values_util_unittest.cc
index 336d771400e..27ec2d0c989 100644
--- a/chromium/dbus/values_util_unittest.cc
+++ b/chromium/dbus/values_util_unittest.cc
@@ -4,9 +4,9 @@
#include "dbus/values_util.h"
+#include <cmath>
#include <vector>
-#include "base/float_util.h"
#include "base/json/json_writer.h"
#include "base/memory/scoped_ptr.h"
#include "base/values.h"
@@ -358,7 +358,7 @@ TEST(ValuesUtilTest, PopDoubleToIntDictionary) {
const std::vector<int32> values(kValues, kValues + arraysize(kValues));
std::vector<double> keys(values.size());
for (size_t i = 0; i != values.size(); ++i)
- keys[i] = sqrt(values[i]);
+ keys[i] = std::sqrt(values[i]);
// Append a dictionary.
scoped_ptr<Response> response(Response::CreateEmpty());