Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(375)

Side by Side Diff: components/arc/arc_bridge_service.cc

Issue 1412863004: arc-bridge: Add the ARC Bridge Service (Closed) Base URL: https://chromium.googlesource.com/a/chromium/src.git@master
Patch Set: Added Pref names and separated file I/O to the correct thread Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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 "components/arc/arc_bridge_service.h"
6
7 #include "base/files/file_path.h"
8 #include "base/files/file_util.h"
9 #include "base/prefs/pref_registry_simple.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/task_runner_util.h"
12 #include "base/thread_task_runner_handle.h"
13 #include "chromeos/arc/bridge/common/arc_host_messages.h"
14 #include "chromeos/arc/bridge/common/arc_instance_messages.h"
15 #include "chromeos/dbus/arc_instance_client.h"
16 #include "chromeos/dbus/dbus_method_call_status.h"
17 #include "chromeos/dbus/dbus_thread_manager.h"
18 #include "components/arc/arc_pref_names.h"
19 #include "ipc/ipc_channel.h"
20
21 namespace {
22
23 const char kArcBridgeSocketPath[] = "/home/chronos/ArcBridge/bridge.sock";
satorux1 2015/10/28 05:45:22 Please use const FilePath::CharType and FILE_PATH_
Luis Héctor Chávez 2015/10/28 17:19:14 Done.
24
25 bool EnsureParentDirectoryPresent(const std::string& socket_path) {
satorux1 2015/10/28 05:45:22 how about taking base::FilePath? The caller shou
Luis Héctor Chávez 2015/10/28 17:19:14 Done.
hidehiko 2015/10/28 17:48:45 Or, in this case, we can inline the code in the ca
Luis Héctor Chávez 2015/10/28 21:06:32 Yep, that's cleaner. Done.
26 base::FilePath path(socket_path);
27 return base::CreateDirectory(path.DirName());
28 }
29
30 bool SocketPermissions(const std::string& socket_path) {
satorux1 2015/10/28 05:45:22 Maybe SetSocketPermissions? std::string -> base::F
Luis Héctor Chávez 2015/10/28 17:19:14 Done.
hidehiko 2015/10/28 17:48:45 Or, does base::SetPosixFilePermissions work?
Luis Héctor Chávez 2015/10/28 21:06:32 Done.
31 // TODO(lhchavez): Tighten the security around the socket by tying it to the
32 // user the instance will run as.
33 return HANDLE_EINTR(chmod(socket_path.c_str(), 0777)) == 0;
34 }
35
36 } // namespace
37
38 namespace arc {
39
40 ArcBridgeService::ArcBridgeService(
41 const scoped_refptr<base::SequencedTaskRunner>& file_task_runner)
42 : ipc_thread_("ARC bridge listener"),
43 origin_task_runner_(base::ThreadTaskRunnerHandle::Get()),
44 file_task_runner_(file_task_runner),
45 state_(ArcBridgeService::DISABLED) {
46 ipc_thread_.StartWithOptions(
47 base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
48 }
49
50 ArcBridgeService::~ArcBridgeService() {}
51
52 // static
53 void ArcBridgeService::RegisterPrefs(PrefRegistrySimple* registry) {
54 registry->RegisterBooleanPref(prefs::kArcEnabled, false);
55 }
56
57 // static
58 bool ArcBridgeService::GetEnabledPref(PrefService* pref_service) {
59 // TODO(lhchavez): Once this is user-configurable, use the real pref.
60 return true;
61 }
62
63 void ArcBridgeService::HandleStartup() {
64 DCHECK(origin_task_runner_->RunsTasksOnCurrentThread());
65 if (state_ != ArcBridgeService::STOPPED)
hidehiko 2015/10/28 17:48:45 Is this expected case? If yes, it's good to commen
Luis Héctor Chávez 2015/10/28 21:06:32 Done
66 return;
67 base::PostTaskAndReplyWithResult(
hidehiko 2015/10/28 17:48:45 Just a suggestion. 1) It seems like directory crea
Luis Héctor Chávez 2015/10/28 21:06:32 Done.
68 file_task_runner_.get(),
69 FROM_HERE,
70 base::Bind(&EnsureParentDirectoryPresent, kArcBridgeSocketPath),
71 base::Bind(&ArcBridgeService::SocketConnect,
72 base::Unretained(this), kArcBridgeSocketPath));
satorux1 2015/10/28 05:45:22 How about using WeakPtrFactory and remove use of U
Luis Héctor Chávez 2015/10/28 17:19:14 All other KeyedServices I saw used Unretained(), b
73 }
74
75 void ArcBridgeService::Shutdown() {
hidehiko 2015/10/28 17:48:45 Looks to have a race issue? If this is called whi
Luis Héctor Chávez 2015/10/28 21:06:32 All state transitions are now guarded.
76 DCHECK(origin_task_runner_->RunsTasksOnCurrentThread());
77 if (state_ != ArcBridgeService::CONNECTED &&
78 state_ != ArcBridgeService::STARTING &&
79 state_ != ArcBridgeService::READY)
hidehiko 2015/10/28 17:48:45 Maybe logging?
Luis Héctor Chávez 2015/10/28 21:06:32 Done.
80 return;
81 ipc_channel_->Close();
82 base::PostTaskAndReplyWithResult(
83 file_task_runner_.get(),
84 FROM_HERE,
85 base::Bind(&base::DeleteFile, base::FilePath(kArcBridgeSocketPath),
86 false),
87 base::Bind(&ArcBridgeService::FinishShutdownAfterSocketDeleted,
88 base::Unretained(this)));
89 }
90
91 void ArcBridgeService::AddObserver(Observer* observer) {
92 observer_list_.AddObserver(observer);
93 }
94
95 void ArcBridgeService::RemoveObserver(Observer* observer) {
96 observer_list_.RemoveObserver(observer);
97 }
98
99 void ArcBridgeService::SetEnabled(bool enabled) {
100 DCHECK(origin_task_runner_->RunsTasksOnCurrentThread());
101
102 if ((!enabled && state_ == ArcBridgeService::DISABLED) ||
103 (enabled && state_ != ArcBridgeService::DISABLED))
104 return;
105 if (state_ != ArcBridgeService::DISABLED) {
106 Shutdown();
107 NotifyStateChanged(ArcBridgeService::DISABLED);
108 return;
109 }
110 NotifyStateChanged(ArcBridgeService::STOPPED);
111 }
112
113 bool ArcBridgeService::RegisterInputDevice(
114 const std::string& name, const std::string& device_type,
115 base::ScopedFD fd) {
satorux1 2015/10/28 05:45:22 on which thread should this be called? Add a DCHEC
Luis Héctor Chávez 2015/10/28 17:19:14 It doesn't matter, IPC::ChannelProxy has a thread-
hidehiko 2015/10/28 17:48:45 FYI: I believe this runs on the browser thread. As
Luis Héctor Chávez 2015/10/28 21:06:32 This can run on any thread (you're the second to m
116 return ipc_channel_->Send(new ArcInstanceMsg_RegisterInputDevice(
117 name, device_type, base::FileDescriptor(fd.Pass())));
118 }
119
120 void ArcBridgeService::SocketConnect(const std::string& socket_path,
121 bool directory_creation_success) {
122 DCHECK(origin_task_runner_->RunsTasksOnCurrentThread());
123
124 if (!directory_creation_success) {
125 LOG(ERROR) << "Error creating directory for " << socket_path;
126 NotifyStateChanged(ArcBridgeService::ERROR);
127 return;
128 }
129
130 if (!Connect(IPC::ChannelHandle(socket_path),
131 IPC::Channel::MODE_OPEN_NAMED_SERVER)) {
132 LOG(ERROR) << "Error connecting to " << socket_path;
133 NotifyStateChanged(ArcBridgeService::ERROR);
134 return;
135 }
136
137 base::PostTaskAndReplyWithResult(
138 file_task_runner_.get(),
139 FROM_HERE,
140 base::Bind(&SocketPermissions, socket_path),
141 base::Bind(&ArcBridgeService::FinishConnectAfterSocketPermissions,
142 base::Unretained(this), socket_path));
143 }
144
145 void ArcBridgeService::FinishConnectAfterSocketPermissions(
146 const std::string& socket_path, bool socket_permissions_success) {
147 DCHECK(origin_task_runner_->RunsTasksOnCurrentThread());
148
149 if (!socket_permissions_success) {
150 LOG(ERROR) << "Error setting socket permissions for " << socket_path;
151 NotifyStateChanged(ArcBridgeService::ERROR);
152 return;
153 }
154
155 // This will fail if the ArcInstanceService is not running on Chrome OS.
156 // Use base::Unretained since this is a KeyedService.
157 chromeos::DBusThreadManager::Get()->GetArcInstanceClient()->StartInstance(
158 socket_path,
159 base::Bind(&ArcBridgeService::OnInstanceStarted, base::Unretained(this)));
160 }
161
162
163 bool ArcBridgeService::Connect(const IPC::ChannelHandle& handle,
164 IPC::Channel::Mode mode) {
165 DCHECK(origin_task_runner_->RunsTasksOnCurrentThread());
166
167 ipc_channel_ = IPC::ChannelProxy::Create(handle, mode, this,
168 ipc_thread_.task_runner().get());
169 if (!ipc_channel_)
170 return false;
171 NotifyStateChanged(ArcBridgeService::CONNECTED);
172 return true;
173 }
174
175 void ArcBridgeService::OnInstanceReady() {
176 DCHECK(origin_task_runner_->RunsTasksOnCurrentThread());
177 NotifyStateChanged(ArcBridgeService::READY);
178 }
179
180 void ArcBridgeService::NotifyStateChanged(State state) {
181 DCHECK(origin_task_runner_->RunsTasksOnCurrentThread());
182 if (state_ == state)
183 return;
184 state_ = state;
185 FOR_EACH_OBSERVER(Observer, observer_list_, OnStateChanged(state_));
186 }
187
188 void ArcBridgeService::FinishShutdownAfterSocketDeleted(bool socket_deleted) {
189 NotifyStateChanged(ArcBridgeService::STOPPED);
190 if (state_ != ArcBridgeService::STARTING && state_ != ArcBridgeService::READY)
191 return;
192 chromeos::DBusThreadManager::Get()->GetArcInstanceClient()->StopInstance(
193 base::Bind(&ArcBridgeService::OnInstanceStopped, base::Unretained(this)));
194 }
195
196 bool ArcBridgeService::OnMessageReceived(const IPC::Message& message) {
197 DCHECK(origin_task_runner_->RunsTasksOnCurrentThread());
198 bool handled = true;
199
200 IPC_BEGIN_MESSAGE_MAP(ArcBridgeService, message)
201 IPC_MESSAGE_HANDLER(ArcInstanceHostMsg_InstanceReady, OnInstanceReady)
202 IPC_MESSAGE_UNHANDLED(handled = false)
203 IPC_END_MESSAGE_MAP()
204
205 if (!handled)
206 LOG(ERROR) << "Invalid message with type = " << message.type();
207 return handled;
208 }
209
210 void ArcBridgeService::OnInstanceStarted(
211 chromeos::DBusMethodCallStatus status) {
212 DCHECK(origin_task_runner_->RunsTasksOnCurrentThread());
213 if (status != chromeos::DBUS_METHOD_CALL_SUCCESS) {
214 LOG(ERROR) << "ARC instance unable to start. Shutting down the bridge";
215 Shutdown();
216 return;
217 }
218 NotifyStateChanged(ArcBridgeService::STARTING);
219 }
220
221 void ArcBridgeService::OnInstanceStopped(
222 chromeos::DBusMethodCallStatus status) {
223 DCHECK(origin_task_runner_->RunsTasksOnCurrentThread());
224 NotifyStateChanged(ArcBridgeService::STOPPED);
225 }
226
227 } // namespace arc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698