diff options
author | cmasone@chromium.org <cmasone@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-31 06:34:59 +0000 |
---|---|---|
committer | cmasone@chromium.org <cmasone@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-31 06:34:59 +0000 |
commit | e282490e359a536c91b15c9a9023cc798fab303b (patch) | |
tree | 1dfee9533ded06413b5b713f246a317a67c47ddd /dbus/signal_sender_verification_unittest.cc | |
parent | 6bedbeffa4fa25ba16d50253dcc7c1aec5ac4702 (diff) | |
download | chromium_src-e282490e359a536c91b15c9a9023cc798fab303b.zip chromium_src-e282490e359a536c91b15c9a9023cc798fab303b.tar.gz chromium_src-e282490e359a536c91b15c9a9023cc798fab303b.tar.bz2 |
Allow Chromium's DBus service ownership to be stealable
We've seen some cases in tests where a Chromium process winds up in a
temporarily unkillable state, causing the dbus-daemon to believe that
it still actively owns org.chromium.LibCrosService. This makes
attempts to restart the UI fail, as the browser dies when it cannot
take ownership of this service name. The reason it can't is because
Chromium currently doesn't allow other processes to steal ownership --
and the unkillable process is holding onto the token.
This can be remedied by providing certain options when ownership of
the service name is taken, options that allow other processes to seize
ownership if they so choose. The ramifications of this are discussed
further in the bug.
BUG=chromium:261381
TEST=new unit test in dbus_unittest
TEST=run the following as chronos on a device: "gdbus call --system --dest org.freedesktop.DBus --object-path /org/freedesktop/DBus --method org.freedesktop.DBus.RequestName org.chromium.LibCrosService 7"
TEST=This should return (uint32 1,)
Review URL: https://chromiumcodereview.appspot.com/20555003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@214589 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'dbus/signal_sender_verification_unittest.cc')
-rw-r--r-- | dbus/signal_sender_verification_unittest.cc | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/dbus/signal_sender_verification_unittest.cc b/dbus/signal_sender_verification_unittest.cc index df2acd2..cbf4b5f 100644 --- a/dbus/signal_sender_verification_unittest.cc +++ b/dbus/signal_sender_verification_unittest.cc @@ -154,6 +154,14 @@ class SignalSenderVerificationTest : public testing::Test { message_loop_.Run(); } + // Stopping a thread is considered an IO operation, so we need to fiddle with + // thread restrictions before and after calling Stop() on a TestService. + void SafeServiceStop(TestService* test_service) { + base::ThreadRestrictions::SetIOAllowed(true); + test_service->Stop(); + base::ThreadRestrictions::SetIOAllowed(false); + } + base::MessageLoop message_loop_; scoped_ptr<base::Thread> dbus_thread_; scoped_refptr<Bus> bus_; @@ -224,6 +232,7 @@ TEST_F(SignalSenderVerificationTest, TestOwnerChanged) { // Reset the flag as NameOwnerChanged is already received in setup. on_name_owner_changed_called_ = false; + on_ownership_called_ = false; test_service2_->RequestOwnership( base::Bind(&SignalSenderVerificationTest::OnOwnership, base::Unretained(this), true)); @@ -246,6 +255,64 @@ TEST_F(SignalSenderVerificationTest, TestOwnerChanged) { ASSERT_EQ(kNewMessage, test_signal_string_); } +TEST_F(SignalSenderVerificationTest, TestOwnerStealing) { + // Release and acquire the name ownership. + // latest_name_owner_ should be non empty as |test_service_| owns the name. + ASSERT_FALSE(latest_name_owner_.empty()); + test_service_->ShutdownAndBlock(); + // OnNameOwnerChanged will PostTask to quit the message loop. + message_loop_.Run(); + // latest_name_owner_ should be empty as the owner is gone. + ASSERT_TRUE(latest_name_owner_.empty()); + // Reset the flag as NameOwnerChanged is already received in setup. + on_name_owner_changed_called_ = false; + + // Start a test service that allows theft, using the D-Bus thread. + TestService::Options options; + options.dbus_task_runner = dbus_thread_->message_loop_proxy(); + options.request_ownership_options = Bus::REQUIRE_PRIMARY_ALLOW_REPLACEMENT; + TestService stealable_test_service(options); + ASSERT_TRUE(stealable_test_service.StartService()); + ASSERT_TRUE(stealable_test_service.WaitUntilServiceIsStarted()); + ASSERT_TRUE(stealable_test_service.HasDBusThread()); + ASSERT_TRUE(stealable_test_service.has_ownership()); + + // OnNameOwnerChanged will PostTask to quit the message loop. + message_loop_.Run(); + + // Send a signal to check that the service is correctly owned. + const char kMessage[] = "hello, world"; + + // Send the test signal from the exported object. + stealable_test_service.SendTestSignal(kMessage); + // Receive the signal with the object proxy. The signal is handled in + // SignalSenderVerificationTest::OnTestSignal() in the main thread. + WaitForTestSignal(); + ASSERT_EQ(kMessage, test_signal_string_); + + // Reset the flag as NameOwnerChanged was called above. + on_name_owner_changed_called_ = false; + test_service2_->RequestOwnership( + base::Bind(&SignalSenderVerificationTest::OnOwnership, + base::Unretained(this), true)); + // Both of OnNameOwnerChanged() and OnOwnership() should quit the MessageLoop, + // but there's no expected order of those 2 event. + message_loop_.Run(); + if (!on_name_owner_changed_called_ || !on_ownership_called_) + message_loop_.Run(); + ASSERT_TRUE(on_name_owner_changed_called_); + ASSERT_TRUE(on_ownership_called_); + + // Now the second service owns the name. + const char kNewMessage[] = "hello, new world"; + + test_service2_->SendTestSignal(kNewMessage); + WaitForTestSignal(); + ASSERT_EQ(kNewMessage, test_signal_string_); + + SafeServiceStop(&stealable_test_service); +} + // Fails on Linux ChromiumOS Tests TEST_F(SignalSenderVerificationTest, DISABLED_TestMultipleObjects) { const char kMessage[] = "hello, world"; |