hashimoto | bb42dee | 2016-01-14 10:13:56 | [diff] [blame] | 1 | // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "chromeos/binder/test_service.h" |
| 6 | |
| 7 | #include "base/bind.h" |
hashimoto | 93582b2 | 2016-01-18 05:52:10 | [diff] [blame] | 8 | #include "base/files/file_util.h" |
| 9 | #include "base/files/scoped_temp_dir.h" |
hashimoto | bb42dee | 2016-01-14 10:13:56 | [diff] [blame] | 10 | #include "base/guid.h" |
dcheng | 0a6e80c | 2016-04-08 18:37:38 | [diff] [blame] | 11 | #include "base/memory/ptr_util.h" |
hashimoto | bb42dee | 2016-01-14 10:13:56 | [diff] [blame] | 12 | #include "base/run_loop.h" |
| 13 | #include "base/strings/utf_string_conversions.h" |
hashimoto | 9aea6a15 | 2016-02-01 06:27:52 | [diff] [blame] | 14 | #include "base/synchronization/waitable_event.h" |
hashimoto | bb42dee | 2016-01-14 10:13:56 | [diff] [blame] | 15 | #include "chromeos/binder/local_object.h" |
| 16 | #include "chromeos/binder/service_manager_proxy.h" |
| 17 | #include "chromeos/binder/transaction_data.h" |
| 18 | #include "chromeos/binder/transaction_data_reader.h" |
| 19 | #include "chromeos/binder/writable_transaction_data.h" |
| 20 | |
| 21 | namespace binder { |
| 22 | |
| 23 | class TestService::TestObject : public LocalObject::TransactionHandler { |
| 24 | public: |
hashimoto | 9aea6a15 | 2016-02-01 06:27:52 | [diff] [blame] | 25 | TestObject() |
| 26 | : event_(false /* manual_reset */, false /* initially_signaled */) { |
| 27 | VLOG(1) << "Object created: " << this; |
| 28 | } |
hashimoto | bb42dee | 2016-01-14 10:13:56 | [diff] [blame] | 29 | |
| 30 | ~TestObject() override { VLOG(1) << "Object destroyed: " << this; } |
| 31 | |
dcheng | 0a6e80c | 2016-04-08 18:37:38 | [diff] [blame] | 32 | std::unique_ptr<binder::TransactionData> OnTransact( |
hashimoto | bb42dee | 2016-01-14 10:13:56 | [diff] [blame] | 33 | binder::CommandBroker* command_broker, |
| 34 | const binder::TransactionData& data) { |
| 35 | VLOG(1) << "Transact code = " << data.GetCode(); |
| 36 | binder::TransactionDataReader reader(data); |
| 37 | switch (data.GetCode()) { |
| 38 | case INCREMENT_INT_TRANSACTION: { |
| 39 | int32_t arg = 0; |
| 40 | reader.ReadInt32(&arg); |
dcheng | 0a6e80c | 2016-04-08 18:37:38 | [diff] [blame] | 41 | std::unique_ptr<binder::WritableTransactionData> reply( |
hashimoto | bb42dee | 2016-01-14 10:13:56 | [diff] [blame] | 42 | new binder::WritableTransactionData()); |
| 43 | reply->WriteInt32(arg + 1); |
| 44 | return std::move(reply); |
| 45 | } |
hashimoto | 93582b2 | 2016-01-18 05:52:10 | [diff] [blame] | 46 | case GET_FD_TRANSACTION: { |
| 47 | // Prepare a file. |
| 48 | std::string data = GetFileContents(); |
| 49 | base::ScopedTempDir temp_dir; |
| 50 | base::FilePath path; |
| 51 | if (!temp_dir.CreateUniqueTempDir() || |
| 52 | !base::CreateTemporaryFileInDir(temp_dir.path(), &path) || |
| 53 | !base::WriteFile(path, data.data(), data.size())) { |
| 54 | LOG(ERROR) << "Failed to create a file"; |
dcheng | 0a6e80c | 2016-04-08 18:37:38 | [diff] [blame] | 55 | return std::unique_ptr<TransactionData>(); |
hashimoto | 93582b2 | 2016-01-18 05:52:10 | [diff] [blame] | 56 | } |
| 57 | // Open the file. |
| 58 | base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ); |
| 59 | if (!file.IsValid()) { |
| 60 | LOG(ERROR) << "Failed to open the file."; |
dcheng | 0a6e80c | 2016-04-08 18:37:38 | [diff] [blame] | 61 | return std::unique_ptr<TransactionData>(); |
hashimoto | 93582b2 | 2016-01-18 05:52:10 | [diff] [blame] | 62 | } |
| 63 | // Return the FD. |
| 64 | // The file will be deleted by |temp_dir|, but the FD remains valid |
| 65 | // until the receiving process closes it. |
dcheng | 0a6e80c | 2016-04-08 18:37:38 | [diff] [blame] | 66 | std::unique_ptr<binder::WritableTransactionData> reply( |
hashimoto | 93582b2 | 2016-01-18 05:52:10 | [diff] [blame] | 67 | new binder::WritableTransactionData()); |
| 68 | reply->WriteFileDescriptor(base::ScopedFD(file.TakePlatformFile())); |
| 69 | return std::move(reply); |
| 70 | } |
hashimoto | 9aea6a15 | 2016-02-01 06:27:52 | [diff] [blame] | 71 | case WAIT_TRANSACTION: { |
| 72 | event_.Wait(); |
dcheng | 0a6e80c | 2016-04-08 18:37:38 | [diff] [blame] | 73 | std::unique_ptr<binder::WritableTransactionData> reply( |
hashimoto | 9aea6a15 | 2016-02-01 06:27:52 | [diff] [blame] | 74 | new binder::WritableTransactionData()); |
| 75 | reply->WriteUint32(WAIT_TRANSACTION); |
| 76 | return std::move(reply); |
| 77 | } |
| 78 | case SIGNAL_TRANSACTION: { |
| 79 | event_.Signal(); |
dcheng | 0a6e80c | 2016-04-08 18:37:38 | [diff] [blame] | 80 | std::unique_ptr<binder::WritableTransactionData> reply( |
hashimoto | 9aea6a15 | 2016-02-01 06:27:52 | [diff] [blame] | 81 | new binder::WritableTransactionData()); |
| 82 | reply->WriteUint32(SIGNAL_TRANSACTION); |
| 83 | return std::move(reply); |
| 84 | } |
hashimoto | bb42dee | 2016-01-14 10:13:56 | [diff] [blame] | 85 | } |
dcheng | 0a6e80c | 2016-04-08 18:37:38 | [diff] [blame] | 86 | return std::unique_ptr<TransactionData>(); |
hashimoto | bb42dee | 2016-01-14 10:13:56 | [diff] [blame] | 87 | } |
| 88 | |
| 89 | private: |
hashimoto | 9aea6a15 | 2016-02-01 06:27:52 | [diff] [blame] | 90 | base::WaitableEvent event_; |
| 91 | |
hashimoto | bb42dee | 2016-01-14 10:13:56 | [diff] [blame] | 92 | DISALLOW_COPY_AND_ASSIGN(TestObject); |
| 93 | }; |
| 94 | |
| 95 | TestService::TestService() |
| 96 | : service_name_(base::ASCIIToUTF16("org.chromium.TestService-" + |
hashimoto | 9aea6a15 | 2016-02-01 06:27:52 | [diff] [blame] | 97 | base::GenerateGUID())), |
| 98 | sub_thread_(&main_thread_) {} |
hashimoto | bb42dee | 2016-01-14 10:13:56 | [diff] [blame] | 99 | |
| 100 | TestService::~TestService() {} |
| 101 | |
| 102 | bool TestService::StartAndWait() { |
hashimoto | 9aea6a15 | 2016-02-01 06:27:52 | [diff] [blame] | 103 | if (!main_thread_.Start() || !sub_thread_.Start() || |
| 104 | !main_thread_.WaitUntilThreadStarted() || !main_thread_.initialized() || |
| 105 | !sub_thread_.WaitUntilThreadStarted() || !sub_thread_.initialized()) { |
| 106 | LOG(ERROR) << "Failed to start the threads."; |
hashimoto | bb42dee | 2016-01-14 10:13:56 | [diff] [blame] | 107 | return false; |
| 108 | } |
| 109 | bool result = false; |
| 110 | base::RunLoop run_loop; |
hashimoto | 9aea6a15 | 2016-02-01 06:27:52 | [diff] [blame] | 111 | main_thread_.task_runner()->PostTaskAndReply( |
hashimoto | bb42dee | 2016-01-14 10:13:56 | [diff] [blame] | 112 | FROM_HERE, |
| 113 | base::Bind(&TestService::Initialize, base::Unretained(this), &result), |
| 114 | run_loop.QuitClosure()); |
| 115 | run_loop.Run(); |
| 116 | return result; |
| 117 | } |
| 118 | |
| 119 | void TestService::Stop() { |
hashimoto | 9aea6a15 | 2016-02-01 06:27:52 | [diff] [blame] | 120 | sub_thread_.Stop(); |
| 121 | main_thread_.Stop(); |
hashimoto | bb42dee | 2016-01-14 10:13:56 | [diff] [blame] | 122 | } |
| 123 | |
hashimoto | 93582b2 | 2016-01-18 05:52:10 | [diff] [blame] | 124 | // static |
| 125 | std::string TestService::GetFileContents() { |
| 126 | return "Test data"; |
| 127 | } |
| 128 | |
hashimoto | bb42dee | 2016-01-14 10:13:56 | [diff] [blame] | 129 | void TestService::Initialize(bool* result) { |
| 130 | // Add service. |
| 131 | scoped_refptr<LocalObject> object( |
dcheng | 0a6e80c | 2016-04-08 18:37:38 | [diff] [blame] | 132 | new LocalObject(base::WrapUnique(new TestObject))); |
hashimoto | 9aea6a15 | 2016-02-01 06:27:52 | [diff] [blame] | 133 | *result = ServiceManagerProxy::AddService(main_thread_.command_broker(), |
hashimoto | bb42dee | 2016-01-14 10:13:56 | [diff] [blame] | 134 | service_name_, object, 0); |
| 135 | } |
| 136 | |
| 137 | } // namespace binder |