blob: 3ecea30b61c48207fdc1104cd8614f980594a041 [file] [log] [blame]
Ryan Cairnsea6505f2011-04-10 19:54:53 -07001// Copyright (c) 2011 The Chromium OS 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
Ben Chan6e726922011-06-28 15:54:32 -07005#include "cros-disks/cros-disks-server-impl.h"
6
Ben Chanf51ff002011-04-25 12:41:57 -07007#include <base/logging.h>
Ryan Cairnsea6505f2011-04-10 19:54:53 -07008
Ben Chan8dcede82011-07-25 20:56:13 -07009#include "cros-disks/archive-manager.h"
Ben Chan6e726922011-06-28 15:54:32 -070010#include "cros-disks/device-event.h"
Ben Chanbdc39742011-05-11 17:51:26 -070011#include "cros-disks/disk.h"
12#include "cros-disks/disk-manager.h"
Szymon Sidor2733b512011-06-30 18:00:51 -070013#include "cros-disks/format-manager.h"
Ben Chan8dcede82011-07-25 20:56:13 -070014#include "cros-disks/platform.h"
Szymon Sidor2733b512011-06-30 18:00:51 -070015
Ben Chan190d3cf2011-07-07 09:38:48 -070016using std::string;
17using std::vector;
Ryan Cairnsea6505f2011-04-10 19:54:53 -070018
19namespace cros_disks {
20
21// TODO(rtc): this should probably be a flag.
Ben Chanb092d752011-07-13 11:44:38 -070022// TODO(benchan): move these to common/chromeos/dbus/service_constants.
23static const char kServicePath[] = "/org/chromium/CrosDisks";
24static const char kServiceErrorName[] = "org.chromium.CrosDisks.Error";
25static const char kPropertyExperimentalFeaturesEnabled[] =
26 "ExperimentalFeaturesEnabled";
Ryan Cairnsea6505f2011-04-10 19:54:53 -070027
Ben Chan6e726922011-06-28 15:54:32 -070028CrosDisksServer::CrosDisksServer(DBus::Connection& connection, // NOLINT
Ben Chan8dcede82011-07-25 20:56:13 -070029 Platform* platform,
30 ArchiveManager* archive_manager,
31 DiskManager* disk_manager,
32 FormatManager* format_manager)
Ben Chanf51ff002011-04-25 12:41:57 -070033 : DBus::ObjectAdaptor(connection, kServicePath),
Ben Chan8dcede82011-07-25 20:56:13 -070034 platform_(platform),
35 archive_manager_(archive_manager),
Ben Chan6e726922011-06-28 15:54:32 -070036 disk_manager_(disk_manager),
Szymon Sidor2733b512011-06-30 18:00:51 -070037 format_manager_(format_manager),
Ben Chan6e726922011-06-28 15:54:32 -070038 is_device_event_queued_(true) {
Ben Chan8dcede82011-07-25 20:56:13 -070039 CHECK(platform_) << "Invalid platform object";
40 CHECK(archive_manager_) << "Invalid archive manager object";
Ben Chanb092d752011-07-13 11:44:38 -070041 CHECK(disk_manager_) << "Invalid disk manager object";
42 CHECK(format_manager_) << "Invalid format manager object";
Szymon Sidor2733b512011-06-30 18:00:51 -070043
Ben Chan8dcede82011-07-25 20:56:13 -070044 // TODO(benchan): Refactor the code so that we don't have to pass
45 // DiskManager, ArchiveManager, etc to the constructor
46 // of CrosDisksServer, but instead pass a list of mount
47 // managers.
48 mount_managers_.push_back(disk_manager_);
49 mount_managers_.push_back(archive_manager_);
50
Ben Chanb092d752011-07-13 11:44:38 -070051 InitializeProperties();
Szymon Sidor2733b512011-06-30 18:00:51 -070052 format_manager_->set_parent(this);
Ben Chanf51ff002011-04-25 12:41:57 -070053}
Ryan Cairnsea6505f2011-04-10 19:54:53 -070054
Ben Chan190d3cf2011-07-07 09:38:48 -070055CrosDisksServer::~CrosDisksServer() {
56}
Ryan Cairnsea6505f2011-04-10 19:54:53 -070057
58bool CrosDisksServer::IsAlive(DBus::Error& error) { // NOLINT
59 return true;
60}
61
Ben Chan190d3cf2011-07-07 09:38:48 -070062string CrosDisksServer::GetDeviceFilesystem(const string& device_path,
Ben Chan8dcede82011-07-25 20:56:13 -070063 DBus::Error& error) { // NOLINT
Szymon Sidor2733b512011-06-30 18:00:51 -070064 return disk_manager_->GetFilesystemTypeOfDevice(device_path);
65}
66
Ben Chan190d3cf2011-07-07 09:38:48 -070067void CrosDisksServer::SignalFormattingFinished(const string& device_path,
Ben Chan8dcede82011-07-25 20:56:13 -070068 int status) {
Szymon Sidor2733b512011-06-30 18:00:51 -070069 if (status) {
Szymon Sidorea0ecbd32011-07-19 16:23:10 -070070 FormattingFinished(std::string("!") + device_path);
Szymon Sidor2733b512011-06-30 18:00:51 -070071 LOG(ERROR) << "Could not format device '" << device_path
Ben Chan8dcede82011-07-25 20:56:13 -070072 << "'. Formatting process failed with an exit code " << status;
Szymon Sidor2733b512011-06-30 18:00:51 -070073 } else {
Szymon Sidorea0ecbd32011-07-19 16:23:10 -070074 FormattingFinished(device_path);
Szymon Sidor2733b512011-06-30 18:00:51 -070075 }
76}
77
Ben Chan190d3cf2011-07-07 09:38:48 -070078bool CrosDisksServer::FormatDevice(const string& device_path,
Ben Chan8dcede82011-07-25 20:56:13 -070079 const string& filesystem,
80 DBus::Error &error) { // NOLINT
Szymon Sidor2733b512011-06-30 18:00:51 -070081 if (!format_manager_->StartFormatting(device_path, filesystem)) {
82 LOG(ERROR) << "Could not format device " << device_path
Ben Chan8dcede82011-07-25 20:56:13 -070083 << " as file system '" << filesystem << "'";
Szymon Sidor2733b512011-06-30 18:00:51 -070084 return false;
85 }
86 return true;
87}
88
Ben Chand3fdc722011-07-21 18:15:22 -070089// TODO(benchan): Deprecate this method.
Ben Chan190d3cf2011-07-07 09:38:48 -070090string CrosDisksServer::FilesystemMount(const string& device_path,
Ben Chan8dcede82011-07-25 20:56:13 -070091 const string& filesystem_type,
92 const vector<string>& mount_options,
93 DBus::Error& error) { // NOLINT
Ben Chan190d3cf2011-07-07 09:38:48 -070094 string mount_path;
Ben Chanf51ff002011-04-25 12:41:57 -070095 if (disk_manager_->Mount(device_path, filesystem_type, mount_options,
Ben Chan8dcede82011-07-25 20:56:13 -070096 &mount_path) == kMountErrorNone) {
Ben Chan42888362011-06-09 18:16:24 -070097 DiskChanged(device_path);
Ben Chanf51ff002011-04-25 12:41:57 -070098 } else {
Ben Chan190d3cf2011-07-07 09:38:48 -070099 string message = "Could not mount device " + device_path;
Ben Chanf51ff002011-04-25 12:41:57 -0700100 LOG(ERROR) << message;
101 error.set(kServiceErrorName, message.c_str());
102 }
103 return mount_path;
Ryan Cairnsea6505f2011-04-10 19:54:53 -0700104}
105
Ben Chand3fdc722011-07-21 18:15:22 -0700106// TODO(benchan): Deprecate this method.
Ben Chan190d3cf2011-07-07 09:38:48 -0700107void CrosDisksServer::FilesystemUnmount(const string& device_path,
Ben Chan8dcede82011-07-25 20:56:13 -0700108 const vector<string>& mount_options,
109 DBus::Error& error) { // NOLINT
110 if (disk_manager_->Unmount(device_path, mount_options) != kMountErrorNone) {
Ben Chan190d3cf2011-07-07 09:38:48 -0700111 string message = "Could not unmount device " + device_path;
Ben Chanf51ff002011-04-25 12:41:57 -0700112 LOG(ERROR) << message;
113 error.set(kServiceErrorName, message.c_str());
114 }
Ryan Cairnsea6505f2011-04-10 19:54:53 -0700115}
116
Ben Chand3fdc722011-07-21 18:15:22 -0700117void CrosDisksServer::Mount(const string& path,
Ben Chan8dcede82011-07-25 20:56:13 -0700118 const string& filesystem_type,
119 const vector<string>& options,
120 DBus::Error& error) { // NOLINT
121 MountErrorType error_type = kMountErrorInvalidPath;
122 MountSourceType source_type = kMountSourceInvalid;
Ben Chand3fdc722011-07-21 18:15:22 -0700123 string mount_path;
Ben Chan8dcede82011-07-25 20:56:13 -0700124
125 for (vector<MountManager*>::iterator manager_iter = mount_managers_.begin();
126 manager_iter != mount_managers_.end(); ++manager_iter) {
127 MountManager* manager = *manager_iter;
128 if (manager->CanMount(path)) {
129 source_type = manager->GetMountSourceType();
130 error_type = manager->Mount(path, filesystem_type, options, &mount_path);
131 break;
132 }
133 }
134
135 if (error_type == kMountErrorNone) {
Ben Chand3fdc722011-07-21 18:15:22 -0700136 // TODO(benchan): Remove this DiskChanged signal when UI
137 // no longer requires it.
138 DiskChanged(path);
Ben Chand3fdc722011-07-21 18:15:22 -0700139 } else {
Ben Chan8dcede82011-07-25 20:56:13 -0700140 LOG(ERROR) << "Failed to mount '" << path << "'";
Ben Chand3fdc722011-07-21 18:15:22 -0700141 }
Ben Chan8dcede82011-07-25 20:56:13 -0700142 MountCompleted(error_type, path, source_type, mount_path);
Ben Chand3fdc722011-07-21 18:15:22 -0700143}
144
145void CrosDisksServer::Unmount(const string& path,
Ben Chan8dcede82011-07-25 20:56:13 -0700146 const vector<string>& options,
147 DBus::Error& error) { // NOLINT
148 MountErrorType error_type = kMountErrorInvalidPath;
149 for (vector<MountManager*>::iterator manager_iter = mount_managers_.begin();
150 manager_iter != mount_managers_.end(); ++manager_iter) {
151 MountManager* manager = *manager_iter;
152 if (manager->CanUnmount(path)) {
153 error_type = manager->Unmount(path, options);
154 break;
155 }
156 }
157
158 if (error_type != kMountErrorNone) {
159 string message = "Failed to unmount '" + path + "'";
Ben Chand3fdc722011-07-21 18:15:22 -0700160 error.set(kServiceErrorName, message.c_str());
161 }
162}
163
Ben Chan190d3cf2011-07-07 09:38:48 -0700164vector<string> CrosDisksServer::DoEnumerateDevices(
Ben Chan490319f2011-05-06 14:00:42 -0700165 bool auto_mountable_only) const {
Ben Chan190d3cf2011-07-07 09:38:48 -0700166 vector<Disk> disks = disk_manager_->EnumerateDisks();
167 vector<string> devices;
Ben Chanf51ff002011-04-25 12:41:57 -0700168 devices.reserve(disks.size());
Ben Chan8dcede82011-07-25 20:56:13 -0700169 for (vector<Disk>::const_iterator disk_iterator = disks.begin();
170 disk_iterator != disks.end(); ++disk_iterator) {
Ben Chan1c2d4252011-06-03 13:33:49 -0700171 if (!auto_mountable_only || disk_iterator->is_auto_mountable()) {
Ben Chan490319f2011-05-06 14:00:42 -0700172 devices.push_back(disk_iterator->native_path());
173 }
174 }
Ben Chanf51ff002011-04-25 12:41:57 -0700175 return devices;
176}
177
Ben Chan190d3cf2011-07-07 09:38:48 -0700178vector<string> CrosDisksServer::EnumerateDevices(
Ben Chan490319f2011-05-06 14:00:42 -0700179 DBus::Error& error) { // NOLINT
180 return DoEnumerateDevices(false);
181}
182
Ben Chan190d3cf2011-07-07 09:38:48 -0700183vector<string> CrosDisksServer::EnumerateAutoMountableDevices(
Ben Chan490319f2011-05-06 14:00:42 -0700184 DBus::Error& error) { // NOLINT
185 return DoEnumerateDevices(true);
186}
187
Ben Chan190d3cf2011-07-07 09:38:48 -0700188DBusDisk CrosDisksServer::GetDeviceProperties(const string& device_path,
Ben Chan8dcede82011-07-25 20:56:13 -0700189 DBus::Error& error) { // NOLINT
Ben Chanf51ff002011-04-25 12:41:57 -0700190 Disk disk;
191 if (!disk_manager_->GetDiskByDevicePath(device_path, &disk)) {
Ben Chan190d3cf2011-07-07 09:38:48 -0700192 string message = "Could not get the properties of device " + device_path;
Ben Chanf51ff002011-04-25 12:41:57 -0700193 LOG(ERROR) << message;
194 error.set(kServiceErrorName, message.c_str());
195 }
196 return disk.ToDBusFormat();
197}
198
199void CrosDisksServer::SignalDeviceChanges() {
Ben Chan6e726922011-06-28 15:54:32 -0700200 DeviceEvent event;
201 if (disk_manager_->GetDeviceEvent(&event)) {
202 if (is_device_event_queued_) {
203 device_event_queue_.Add(event);
204 } else {
205 DispatchDeviceEvent(event);
Ben Chanf51ff002011-04-25 12:41:57 -0700206 }
207 }
Ryan Cairnsea6505f2011-04-10 19:54:53 -0700208}
209
Ben Chan6e726922011-06-28 15:54:32 -0700210void CrosDisksServer::OnScreenIsLocked() {
211 LOG(INFO) << "Screen is locked";
212 is_device_event_queued_ = true;
213}
214
215void CrosDisksServer::OnScreenIsUnlocked() {
216 LOG(INFO) << "Screen is unlocked";
217 DispatchQueuedDeviceEvents();
218 is_device_event_queued_ = false;
219}
220
Ben Chan190d3cf2011-07-07 09:38:48 -0700221void CrosDisksServer::OnSessionStarted(const string& user) {
Ben Chan6e726922011-06-28 15:54:32 -0700222 LOG(INFO) << "Session started";
223 DispatchQueuedDeviceEvents();
224 is_device_event_queued_ = false;
Ben Chan8dcede82011-07-25 20:56:13 -0700225
226 for (vector<MountManager*>::iterator manager_iter = mount_managers_.begin();
227 manager_iter != mount_managers_.end(); ++manager_iter) {
228 MountManager* manager = *manager_iter;
229 manager->StartSession(user);
230 }
Ben Chan6e726922011-06-28 15:54:32 -0700231}
232
Ben Chan190d3cf2011-07-07 09:38:48 -0700233void CrosDisksServer::OnSessionStopped(const string& user) {
Ben Chan6e726922011-06-28 15:54:32 -0700234 LOG(INFO) << "Session stopped";
235 is_device_event_queued_ = true;
Ben Chan8dcede82011-07-25 20:56:13 -0700236
237 for (vector<MountManager*>::iterator manager_iter = mount_managers_.begin();
238 manager_iter != mount_managers_.end(); ++manager_iter) {
239 MountManager* manager = *manager_iter;
240 manager->StopSession(user);
241 }
Ben Chan6e726922011-06-28 15:54:32 -0700242}
243
244void CrosDisksServer::DispatchDeviceEvent(const DeviceEvent& event) {
245 switch (event.event_type) {
246 case DeviceEvent::kDeviceAdded:
247 DeviceAdded(event.device_path);
248 break;
249 case DeviceEvent::kDeviceScanned:
250 DeviceScanned(event.device_path);
251 break;
252 case DeviceEvent::kDeviceRemoved:
253 DeviceRemoved(event.device_path);
254 break;
255 case DeviceEvent::kDiskAdded:
256 DiskAdded(event.device_path);
257 break;
258 case DeviceEvent::kDiskAddedAfterRemoved:
259 DiskRemoved(event.device_path);
260 DiskAdded(event.device_path);
261 break;
262 case DeviceEvent::kDiskChanged:
263 DiskChanged(event.device_path);
264 break;
265 case DeviceEvent::kDiskRemoved:
266 DiskRemoved(event.device_path);
267 break;
268 default:
269 break;
270 }
271}
272
273void CrosDisksServer::DispatchQueuedDeviceEvents() {
274 const DeviceEvent* event;
275 while ((event = device_event_queue_.Head()) != NULL) {
276 LOG(INFO) << "Dispatch queued event: type=" << event->event_type
Ben Chan8dcede82011-07-25 20:56:13 -0700277 << " device='" << event->device_path << "'";
Ben Chan6e726922011-06-28 15:54:32 -0700278 DispatchDeviceEvent(*event);
279 device_event_queue_.Remove();
280 }
281}
282
Ben Chanb092d752011-07-13 11:44:38 -0700283void CrosDisksServer::InitializeProperties() {
284 try {
285 DBus::Variant value;
Ben Chan8dcede82011-07-25 20:56:13 -0700286 value.writer().append_bool(platform_->experimental_features_enabled());
Ben Chanb092d752011-07-13 11:44:38 -0700287 CrosDisks_adaptor::set_property(kPropertyExperimentalFeaturesEnabled,
Ben Chan8dcede82011-07-25 20:56:13 -0700288 value);
289 } catch (const DBus::Error& e) { // NOLINT
Ben Chanb092d752011-07-13 11:44:38 -0700290 LOG(FATAL) << "Failed to initialize properties: " << e.what();
291 }
292}
293
294void CrosDisksServer::on_set_property(
295 DBus::InterfaceAdaptor& interface, // NOLINT
Ben Chan8dcede82011-07-25 20:56:13 -0700296 const string& property, const DBus::Variant& value) {
Ben Chanb092d752011-07-13 11:44:38 -0700297 if (property == kPropertyExperimentalFeaturesEnabled) {
Ben Chan8dcede82011-07-25 20:56:13 -0700298 platform_->set_experimental_features_enabled(value.reader().get_bool());
Ben Chanb092d752011-07-13 11:44:38 -0700299 }
300}
301
Ben Chanbdc39742011-05-11 17:51:26 -0700302} // namespace cros_disks