Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / chromeos / dbus / cros_disks_client.cc
1 // Copyright (c) 2012 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/dbus/cros_disks_client.h"
6
7 #include <map>
8
9 #include "base/bind.h"
10 #include "base/files/file_path.h"
11 #include "base/files/file_util.h"
12 #include "base/location.h"
13 #include "base/message_loop/message_loop_proxy.h"
14 #include "base/stl_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/sys_info.h"
17 #include "base/task_runner_util.h"
18 #include "base/threading/worker_pool.h"
19 #include "base/values.h"
20 #include "chromeos/dbus/fake_cros_disks_client.h"
21 #include "dbus/bus.h"
22 #include "dbus/message.h"
23 #include "dbus/object_path.h"
24 #include "dbus/object_proxy.h"
25 #include "dbus/values_util.h"
26 #include "third_party/cros_system_api/dbus/service_constants.h"
27
28 namespace chromeos {
29
30 namespace {
31
32 const char* kDefaultMountOptions[] = {
33   "rw",
34   "nodev",
35   "noexec",
36   "nosuid",
37 };
38
39 const char* kDefaultUnmountOptions[] = {
40   "force",
41 };
42
43 const char kLazyUnmountOption[] = "lazy";
44
45 const char kMountLabelOption[] = "mountlabel";
46
47 // Checks if retrieved media type is in boundaries of DeviceMediaType.
48 bool IsValidMediaType(uint32 type) {
49   return type < static_cast<uint32>(cros_disks::DEVICE_MEDIA_NUM_VALUES);
50 }
51
52 // Translates enum used in cros-disks to enum used in Chrome.
53 // Note that we could just do static_cast, but this is less sensitive to
54 // changes in cros-disks.
55 DeviceType DeviceMediaTypeToDeviceType(uint32 media_type_uint32) {
56   if (!IsValidMediaType(media_type_uint32))
57     return DEVICE_TYPE_UNKNOWN;
58
59   cros_disks::DeviceMediaType media_type =
60       cros_disks::DeviceMediaType(media_type_uint32);
61
62   switch (media_type) {
63     case(cros_disks::DEVICE_MEDIA_UNKNOWN):
64       return DEVICE_TYPE_UNKNOWN;
65     case(cros_disks::DEVICE_MEDIA_USB):
66       return DEVICE_TYPE_USB;
67     case(cros_disks::DEVICE_MEDIA_SD):
68       return DEVICE_TYPE_SD;
69     case(cros_disks::DEVICE_MEDIA_OPTICAL_DISC):
70       return DEVICE_TYPE_OPTICAL_DISC;
71     case(cros_disks::DEVICE_MEDIA_MOBILE):
72       return DEVICE_TYPE_MOBILE;
73     case(cros_disks::DEVICE_MEDIA_DVD):
74       return DEVICE_TYPE_DVD;
75     default:
76       return DEVICE_TYPE_UNKNOWN;
77   }
78 }
79
80 bool ReadMountEntryFromDbus(dbus::MessageReader* reader, MountEntry* entry) {
81   uint32 error_code = 0;
82   std::string source_path;
83   uint32 mount_type = 0;
84   std::string mount_path;
85   if (!reader->PopUint32(&error_code) ||
86       !reader->PopString(&source_path) ||
87       !reader->PopUint32(&mount_type) ||
88       !reader->PopString(&mount_path)) {
89     return false;
90   }
91   *entry = MountEntry(static_cast<MountError>(error_code), source_path,
92                       static_cast<MountType>(mount_type), mount_path);
93   return true;
94 }
95
96 // The CrosDisksClient implementation.
97 class CrosDisksClientImpl : public CrosDisksClient {
98  public:
99   CrosDisksClientImpl() : proxy_(NULL), weak_ptr_factory_(this) {}
100
101   // CrosDisksClient override.
102   virtual void Mount(const std::string& source_path,
103                      const std::string& source_format,
104                      const std::string& mount_label,
105                      const base::Closure& callback,
106                      const base::Closure& error_callback) override {
107     dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
108                                  cros_disks::kMount);
109     dbus::MessageWriter writer(&method_call);
110     writer.AppendString(source_path);
111     writer.AppendString(source_format);
112     std::vector<std::string> mount_options(kDefaultMountOptions,
113                                            kDefaultMountOptions +
114                                            arraysize(kDefaultMountOptions));
115     if (!mount_label.empty()) {
116       std::string mount_label_option = base::StringPrintf("%s=%s",
117                                                           kMountLabelOption,
118                                                           mount_label.c_str());
119       mount_options.push_back(mount_label_option);
120     }
121     writer.AppendArrayOfStrings(mount_options);
122     proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
123                        base::Bind(&CrosDisksClientImpl::OnMount,
124                                   weak_ptr_factory_.GetWeakPtr(),
125                                   callback,
126                                   error_callback));
127   }
128
129   // CrosDisksClient override.
130   virtual void Unmount(const std::string& device_path,
131                        UnmountOptions options,
132                        const base::Closure& callback,
133                        const base::Closure& error_callback) override {
134     dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
135                                  cros_disks::kUnmount);
136     dbus::MessageWriter writer(&method_call);
137     writer.AppendString(device_path);
138
139     std::vector<std::string> unmount_options(
140         kDefaultUnmountOptions,
141         kDefaultUnmountOptions + arraysize(kDefaultUnmountOptions));
142     if (options == UNMOUNT_OPTIONS_LAZY)
143       unmount_options.push_back(kLazyUnmountOption);
144
145     writer.AppendArrayOfStrings(unmount_options);
146     proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
147                        base::Bind(&CrosDisksClientImpl::OnUnmount,
148                                   weak_ptr_factory_.GetWeakPtr(),
149                                   callback,
150                                   error_callback));
151   }
152
153   // CrosDisksClient override.
154   virtual void EnumerateAutoMountableDevices(
155       const EnumerateAutoMountableDevicesCallback& callback,
156       const base::Closure& error_callback) override {
157     dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
158                                  cros_disks::kEnumerateAutoMountableDevices);
159     proxy_->CallMethod(
160         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
161         base::Bind(&CrosDisksClientImpl::OnEnumerateAutoMountableDevices,
162                    weak_ptr_factory_.GetWeakPtr(),
163                    callback,
164                    error_callback));
165   }
166
167   // CrosDisksClient override.
168   virtual void EnumerateMountEntries(
169       const EnumerateMountEntriesCallback& callback,
170       const base::Closure& error_callback) override {
171     dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
172                                  cros_disks::kEnumerateMountEntries);
173     proxy_->CallMethod(
174         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
175         base::Bind(&CrosDisksClientImpl::OnEnumerateMountEntries,
176                    weak_ptr_factory_.GetWeakPtr(),
177                    callback,
178                    error_callback));
179   }
180
181   // CrosDisksClient override.
182   virtual void Format(const std::string& device_path,
183                       const std::string& filesystem,
184                       const base::Closure& callback,
185                       const base::Closure& error_callback) override {
186     dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
187                                  cros_disks::kFormat);
188     dbus::MessageWriter writer(&method_call);
189     writer.AppendString(device_path);
190     writer.AppendString(filesystem);
191     // No format option is currently specified, but we can later use this
192     // argument to specify options for the format operation.
193     std::vector<std::string> format_options;
194     writer.AppendArrayOfStrings(format_options);
195     proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
196                        base::Bind(&CrosDisksClientImpl::OnFormat,
197                                   weak_ptr_factory_.GetWeakPtr(),
198                                   callback,
199                                   error_callback));
200   }
201
202   // CrosDisksClient override.
203   virtual void GetDeviceProperties(
204       const std::string& device_path,
205       const GetDevicePropertiesCallback& callback,
206       const base::Closure& error_callback) override {
207     dbus::MethodCall method_call(cros_disks::kCrosDisksInterface,
208                                  cros_disks::kGetDeviceProperties);
209     dbus::MessageWriter writer(&method_call);
210     writer.AppendString(device_path);
211     proxy_->CallMethod(&method_call,
212                        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
213                        base::Bind(&CrosDisksClientImpl::OnGetDeviceProperties,
214                                   weak_ptr_factory_.GetWeakPtr(),
215                                   device_path,
216                                   callback,
217                                   error_callback));
218   }
219
220   // CrosDisksClient override.
221   virtual void SetMountEventHandler(
222       const MountEventHandler& mount_event_handler) override {
223     static const SignalEventTuple kSignalEventTuples[] = {
224       { cros_disks::kDeviceAdded, CROS_DISKS_DEVICE_ADDED },
225       { cros_disks::kDeviceScanned, CROS_DISKS_DEVICE_SCANNED },
226       { cros_disks::kDeviceRemoved, CROS_DISKS_DEVICE_REMOVED },
227       { cros_disks::kDiskAdded, CROS_DISKS_DISK_ADDED },
228       { cros_disks::kDiskChanged, CROS_DISKS_DISK_CHANGED },
229       { cros_disks::kDiskRemoved, CROS_DISKS_DISK_REMOVED },
230     };
231     const size_t kNumSignalEventTuples = arraysize(kSignalEventTuples);
232
233     for (size_t i = 0; i < kNumSignalEventTuples; ++i) {
234       proxy_->ConnectToSignal(
235           cros_disks::kCrosDisksInterface,
236           kSignalEventTuples[i].signal_name,
237           base::Bind(&CrosDisksClientImpl::OnMountEvent,
238                      weak_ptr_factory_.GetWeakPtr(),
239                      kSignalEventTuples[i].event_type,
240                      mount_event_handler),
241           base::Bind(&CrosDisksClientImpl::OnSignalConnected,
242                      weak_ptr_factory_.GetWeakPtr()));
243     }
244   }
245
246   // CrosDisksClient override.
247   virtual void SetMountCompletedHandler(
248       const MountCompletedHandler& mount_completed_handler) override {
249     proxy_->ConnectToSignal(
250         cros_disks::kCrosDisksInterface,
251         cros_disks::kMountCompleted,
252         base::Bind(&CrosDisksClientImpl::OnMountCompleted,
253                    weak_ptr_factory_.GetWeakPtr(),
254                    mount_completed_handler),
255         base::Bind(&CrosDisksClientImpl::OnSignalConnected,
256                    weak_ptr_factory_.GetWeakPtr()));
257   }
258
259   // CrosDisksClient override.
260   virtual void SetFormatCompletedHandler(
261       const FormatCompletedHandler& format_completed_handler) override {
262     proxy_->ConnectToSignal(
263         cros_disks::kCrosDisksInterface,
264         cros_disks::kFormatCompleted,
265         base::Bind(&CrosDisksClientImpl::OnFormatCompleted,
266                    weak_ptr_factory_.GetWeakPtr(),
267                    format_completed_handler),
268         base::Bind(&CrosDisksClientImpl::OnSignalConnected,
269                    weak_ptr_factory_.GetWeakPtr()));
270   }
271
272  protected:
273   virtual void Init(dbus::Bus* bus) override {
274     proxy_ = bus->GetObjectProxy(
275         cros_disks::kCrosDisksServiceName,
276         dbus::ObjectPath(cros_disks::kCrosDisksServicePath));
277   }
278
279  private:
280   // A struct to contain a pair of signal name and mount event type.
281   // Used by SetMountEventHandler.
282   struct SignalEventTuple {
283     const char *signal_name;
284     MountEventType event_type;
285   };
286
287   // Handles the result of Mount and calls |callback| or |error_callback|.
288   void OnMount(const base::Closure& callback,
289                const base::Closure& error_callback,
290                dbus::Response* response) {
291     if (!response) {
292       error_callback.Run();
293       return;
294     }
295     callback.Run();
296   }
297
298   // Handles the result of Unmount and calls |callback| or |error_callback|.
299   void OnUnmount(const base::Closure& callback,
300                  const base::Closure& error_callback,
301                  dbus::Response* response) {
302     if (!response) {
303       error_callback.Run();
304       return;
305     }
306
307     // Temporarly allow Unmount method to report failure both by setting dbus
308     // error (in which case response is not set) and by returning mount error
309     // different from MOUNT_ERROR_NONE. This is done so we can change Unmount
310     // method to return mount error (http://crbug.com/288974) without breaking
311     // Chrome.
312     // TODO(tbarzic): When Unmount implementation is changed on cros disks side,
313     // make this fail if reader is not able to read the error code value from
314     // the response.
315     dbus::MessageReader reader(response);
316     uint32 error_code = 0;
317     if (reader.PopUint32(&error_code) &&
318         static_cast<MountError>(error_code) != MOUNT_ERROR_NONE) {
319       error_callback.Run();
320       return;
321     }
322
323     callback.Run();
324   }
325
326   // Handles the result of EnumerateAutoMountableDevices and calls |callback| or
327   // |error_callback|.
328   void OnEnumerateAutoMountableDevices(
329       const EnumerateAutoMountableDevicesCallback& callback,
330       const base::Closure& error_callback,
331       dbus::Response* response) {
332     if (!response) {
333       error_callback.Run();
334       return;
335     }
336     dbus::MessageReader reader(response);
337     std::vector<std::string> device_paths;
338     if (!reader.PopArrayOfStrings(&device_paths)) {
339       LOG(ERROR) << "Invalid response: " << response->ToString();
340       error_callback.Run();
341       return;
342     }
343     callback.Run(device_paths);
344   }
345
346   // Handles the result of EnumerateMountEntries and calls |callback| or
347   // |error_callback|.
348   void OnEnumerateMountEntries(
349       const EnumerateMountEntriesCallback& callback,
350       const base::Closure& error_callback,
351       dbus::Response* response) {
352     if (!response) {
353       error_callback.Run();
354       return;
355     }
356
357     dbus::MessageReader reader(response);
358     dbus::MessageReader array_reader(NULL);
359     if (!reader.PopArray(&array_reader)) {
360       LOG(ERROR) << "Invalid response: " << response->ToString();
361       error_callback.Run();
362       return;
363     }
364
365     std::vector<MountEntry> entries;
366     while (array_reader.HasMoreData()) {
367       MountEntry entry;
368       dbus::MessageReader sub_reader(NULL);
369       if (!array_reader.PopStruct(&sub_reader) ||
370           !ReadMountEntryFromDbus(&sub_reader, &entry)) {
371         LOG(ERROR) << "Invalid response: " << response->ToString();
372         error_callback.Run();
373         return;
374       }
375       entries.push_back(entry);
376     }
377     callback.Run(entries);
378   }
379
380   // Handles the result of Format and calls |callback| or |error_callback|.
381   void OnFormat(const base::Closure& callback,
382                 const base::Closure& error_callback,
383                 dbus::Response* response) {
384     if (!response) {
385       error_callback.Run();
386       return;
387     }
388     callback.Run();
389   }
390
391   // Handles the result of GetDeviceProperties and calls |callback| or
392   // |error_callback|.
393   void OnGetDeviceProperties(const std::string& device_path,
394                              const GetDevicePropertiesCallback& callback,
395                              const base::Closure& error_callback,
396                              dbus::Response* response) {
397     if (!response) {
398       error_callback.Run();
399       return;
400     }
401     DiskInfo disk(device_path, response);
402     callback.Run(disk);
403   }
404
405   // Handles mount event signals and calls |handler|.
406   void OnMountEvent(MountEventType event_type,
407                     MountEventHandler handler,
408                     dbus::Signal* signal) {
409     dbus::MessageReader reader(signal);
410     std::string device;
411     if (!reader.PopString(&device)) {
412       LOG(ERROR) << "Invalid signal: " << signal->ToString();
413       return;
414     }
415     handler.Run(event_type, device);
416   }
417
418   // Handles MountCompleted signal and calls |handler|.
419   void OnMountCompleted(MountCompletedHandler handler, dbus::Signal* signal) {
420     dbus::MessageReader reader(signal);
421     MountEntry entry;
422     if (!ReadMountEntryFromDbus(&reader, &entry)) {
423       LOG(ERROR) << "Invalid signal: " << signal->ToString();
424       return;
425     }
426     handler.Run(entry);
427   }
428
429   // Handles FormatCompleted signal and calls |handler|.
430   void OnFormatCompleted(FormatCompletedHandler handler, dbus::Signal* signal) {
431     dbus::MessageReader reader(signal);
432     uint32 error_code = 0;
433     std::string device_path;
434     if (!reader.PopUint32(&error_code) || !reader.PopString(&device_path)) {
435       LOG(ERROR) << "Invalid signal: " << signal->ToString();
436       return;
437     }
438     handler.Run(static_cast<FormatError>(error_code), device_path);
439   }
440
441   // Handles the result of signal connection setup.
442   void OnSignalConnected(const std::string& interface,
443                          const std::string& signal,
444                          bool succeeded) {
445     LOG_IF(ERROR, !succeeded) << "Connect to " << interface << " " <<
446         signal << " failed.";
447   }
448
449   dbus::ObjectProxy* proxy_;
450
451   // Note: This should remain the last member so it'll be destroyed and
452   // invalidate its weak pointers before any other members are destroyed.
453   base::WeakPtrFactory<CrosDisksClientImpl> weak_ptr_factory_;
454
455   DISALLOW_COPY_AND_ASSIGN(CrosDisksClientImpl);
456 };
457
458 }  // namespace
459
460 ////////////////////////////////////////////////////////////////////////////////
461 // DiskInfo
462
463 DiskInfo::DiskInfo(const std::string& device_path, dbus::Response* response)
464     : device_path_(device_path),
465       is_drive_(false),
466       has_media_(false),
467       on_boot_device_(false),
468       on_removable_device_(false),
469       device_type_(DEVICE_TYPE_UNKNOWN),
470       total_size_in_bytes_(0),
471       is_read_only_(false),
472       is_hidden_(true) {
473   InitializeFromResponse(response);
474 }
475
476 DiskInfo::~DiskInfo() {
477 }
478
479 // Initializes |this| from |response| given by the cros-disks service.
480 // Below is an example of |response|'s raw message (long string is ellipsized).
481 //
482 //
483 // message_type: MESSAGE_METHOD_RETURN
484 // destination: :1.8
485 // sender: :1.16
486 // signature: a{sv}
487 // serial: 96
488 // reply_serial: 267
489 //
490 // array [
491 //   dict entry {
492 //     string "DeviceFile"
493 //     variant       string "/dev/sdb"
494 //   }
495 //   dict entry {
496 //     string "DeviceIsDrive"
497 //     variant       bool true
498 //   }
499 //   dict entry {
500 //     string "DeviceIsMediaAvailable"
501 //     variant       bool true
502 //   }
503 //   dict entry {
504 //     string "DeviceIsMounted"
505 //     variant       bool false
506 //   }
507 //   dict entry {
508 //     string "DeviceIsOnBootDevice"
509 //     variant       bool false
510 //   }
511 //   dict entry {
512 //     string "DeviceIsOnRemovableDevice"
513 //     variant       bool true
514 //   }
515 //   dict entry {
516 //     string "DeviceIsReadOnly"
517 //     variant       bool false
518 //   }
519 //   dict entry {
520 //     string "DeviceIsVirtual"
521 //     variant       bool false
522 //   }
523 //   dict entry {
524 //     string "DeviceMediaType"
525 //     variant       uint32 1
526 //   }
527 //   dict entry {
528 //     string "DeviceMountPaths"
529 //     variant       array [
530 //       ]
531 //   }
532 //   dict entry {
533 //     string "DevicePresentationHide"
534 //     variant       bool true
535 //   }
536 //   dict entry {
537 //     string "DeviceSize"
538 //     variant       uint64 7998537728
539 //   }
540 //   dict entry {
541 //     string "DriveIsRotational"
542 //     variant       bool false
543 //   }
544 //   dict entry {
545 //     string "VendorId"
546 //     variant       string "18d1"
547 //   }
548 //   dict entry {
549 //     string "VendorName"
550 //     variant       string "Google Inc."
551 //   }
552 //   dict entry {
553 //     string "ProductId"
554 //     variant       string "4e11"
555 //   }
556 //   dict entry {
557 //     string "ProductName"
558 //     variant       string "Nexus One"
559 //   }
560 //   dict entry {
561 //     string "DriveModel"
562 //     variant       string "TransMemory"
563 //   }
564 //   dict entry {
565 //     string "IdLabel"
566 //     variant       string ""
567 //   }
568 //   dict entry {
569 //     string "IdUuid"
570 //     variant       string ""
571 //   }
572 //   dict entry {
573 //     string "NativePath"
574 //     variant       string "/sys/devices/pci0000:00/0000:00:1d.7/usb1/1-4/...
575 //   }
576 // ]
577 void DiskInfo::InitializeFromResponse(dbus::Response* response) {
578   dbus::MessageReader reader(response);
579   scoped_ptr<base::Value> value(dbus::PopDataAsValue(&reader));
580   base::DictionaryValue* properties = NULL;
581   if (!value || !value->GetAsDictionary(&properties))
582     return;
583
584   properties->GetBooleanWithoutPathExpansion(
585       cros_disks::kDeviceIsDrive, &is_drive_);
586   properties->GetBooleanWithoutPathExpansion(
587       cros_disks::kDeviceIsReadOnly, &is_read_only_);
588   properties->GetBooleanWithoutPathExpansion(
589       cros_disks::kDevicePresentationHide, &is_hidden_);
590   properties->GetBooleanWithoutPathExpansion(
591       cros_disks::kDeviceIsMediaAvailable, &has_media_);
592   properties->GetBooleanWithoutPathExpansion(
593       cros_disks::kDeviceIsOnBootDevice, &on_boot_device_);
594   properties->GetBooleanWithoutPathExpansion(
595       cros_disks::kDeviceIsOnRemovableDevice, &on_removable_device_);
596   properties->GetStringWithoutPathExpansion(
597       cros_disks::kNativePath, &system_path_);
598   properties->GetStringWithoutPathExpansion(
599       cros_disks::kDeviceFile, &file_path_);
600   properties->GetStringWithoutPathExpansion(cros_disks::kVendorId, &vendor_id_);
601   properties->GetStringWithoutPathExpansion(
602       cros_disks::kVendorName, &vendor_name_);
603   properties->GetStringWithoutPathExpansion(
604       cros_disks::kProductId, &product_id_);
605   properties->GetStringWithoutPathExpansion(
606       cros_disks::kProductName, &product_name_);
607   properties->GetStringWithoutPathExpansion(
608       cros_disks::kDriveModel, &drive_model_);
609   properties->GetStringWithoutPathExpansion(cros_disks::kIdLabel, &label_);
610   properties->GetStringWithoutPathExpansion(cros_disks::kIdUuid, &uuid_);
611
612   // dbus::PopDataAsValue() pops uint64 as double.
613   // The top 11 bits of uint64 are dropped by the use of double. But, this works
614   // unless the size exceeds 8 PB.
615   double device_size_double = 0;
616   if (properties->GetDoubleWithoutPathExpansion(cros_disks::kDeviceSize,
617                                                 &device_size_double))
618     total_size_in_bytes_ = device_size_double;
619
620   // dbus::PopDataAsValue() pops uint32 as double.
621   double media_type_double = 0;
622   if (properties->GetDoubleWithoutPathExpansion(cros_disks::kDeviceMediaType,
623                                                 &media_type_double))
624     device_type_ = DeviceMediaTypeToDeviceType(media_type_double);
625
626   base::ListValue* mount_paths = NULL;
627   if (properties->GetListWithoutPathExpansion(cros_disks::kDeviceMountPaths,
628                                               &mount_paths))
629     mount_paths->GetString(0, &mount_path_);
630 }
631
632 ////////////////////////////////////////////////////////////////////////////////
633 // CrosDisksClient
634
635 CrosDisksClient::CrosDisksClient() {}
636
637 CrosDisksClient::~CrosDisksClient() {}
638
639 // static
640 CrosDisksClient* CrosDisksClient::Create(DBusClientImplementationType type) {
641   if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
642     return new CrosDisksClientImpl();
643   DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
644   return new FakeCrosDisksClient();
645 }
646
647 // static
648 base::FilePath CrosDisksClient::GetArchiveMountPoint() {
649   return base::FilePath(base::SysInfo::IsRunningOnChromeOS() ?
650                         FILE_PATH_LITERAL("/media/archive") :
651                         FILE_PATH_LITERAL("/tmp/chromeos/media/archive"));
652 }
653
654 // static
655 base::FilePath CrosDisksClient::GetRemovableDiskMountPoint() {
656   return base::FilePath(base::SysInfo::IsRunningOnChromeOS() ?
657                         FILE_PATH_LITERAL("/media/removable") :
658                         FILE_PATH_LITERAL("/tmp/chromeos/media/removable"));
659 }
660
661 }  // namespace chromeos