Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / utility / image_writer / disk_unmounter_mac.cc
1 // Copyright 2014 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 "chrome/utility/image_writer/disk_unmounter_mac.h"
6
7 #include <sys/socket.h>
8 #include <IOKit/storage/IOStorageProtocolCharacteristics.h>
9
10 #include "base/message_loop/message_loop_proxy.h"
11 #include "base/message_loop/message_pump_mac.h"
12 #include "base/posix/eintr_wrapper.h"
13 #include "chrome/utility/image_writer/error_messages.h"
14 #include "chrome/utility/image_writer/image_writer.h"
15
16 namespace image_writer {
17
18 DiskUnmounterMac::DiskUnmounterMac() : cf_thread_("ImageWriterDiskArb") {
19   base::Thread::Options options;
20   options.message_pump_factory = base::Bind(&CreateMessagePump);
21
22   cf_thread_.StartWithOptions(options);
23 }
24
25 DiskUnmounterMac::~DiskUnmounterMac() {
26   if (disk_)
27     DADiskUnclaim(disk_);
28 }
29
30 void DiskUnmounterMac::Unmount(const std::string& device_path,
31                                const base::Closure& success_continuation,
32                                const base::Closure& failure_continuation) {
33   // Should only be used once.
34   DCHECK(!original_thread_.get());
35   original_thread_ = base::MessageLoopProxy::current();
36   success_continuation_ = success_continuation;
37   failure_continuation_ = failure_continuation;
38
39   cf_thread_.message_loop()->PostTask(
40       FROM_HERE,
41       base::Bind(&DiskUnmounterMac::UnmountOnWorker,
42                  base::Unretained(this),
43                  device_path));
44 }
45
46 // static
47 void DiskUnmounterMac::DiskClaimed(DADiskRef disk,
48                                    DADissenterRef dissenter,
49                                    void* context) {
50   DiskUnmounterMac* disk_unmounter = static_cast<DiskUnmounterMac*>(context);
51
52   if (dissenter) {
53     LOG(ERROR) << "Unable to claim disk.";
54     disk_unmounter->Error();
55     return;
56   }
57
58   DADiskUnmount(disk,
59                 kDADiskUnmountOptionForce | kDADiskUnmountOptionWhole,
60                 DiskUnmounted,
61                 disk_unmounter);
62 }
63
64 // static
65 DADissenterRef DiskUnmounterMac::DiskClaimRevoked(DADiskRef disk,
66                                                   void* context) {
67   CFStringRef reason = CFSTR(
68       "Hi. Sorry to bother you, but I'm busy overwriting the entire disk "
69       "here. There's nothing to claim but the smoldering ruins of bytes "
70       "that were in flash memory. Trust me, it's nothing that you want. "
71       "All the best. Toodles!");
72   return DADissenterCreate(kCFAllocatorDefault, kDAReturnBusy, reason);
73 }
74
75 // static
76 void DiskUnmounterMac::DiskUnmounted(DADiskRef disk,
77                                      DADissenterRef dissenter,
78                                      void* context) {
79   DiskUnmounterMac* disk_unmounter = static_cast<DiskUnmounterMac*>(context);
80
81   if (dissenter) {
82     LOG(ERROR) << "Unable to unmount disk.";
83     disk_unmounter->Error();
84     return;
85   }
86
87   disk_unmounter->original_thread_->PostTask(
88       FROM_HERE, disk_unmounter->success_continuation_);
89 }
90
91 // static
92 scoped_ptr<base::MessagePump> DiskUnmounterMac::CreateMessagePump() {
93   return scoped_ptr<base::MessagePump>(new base::MessagePumpCFRunLoop);
94 }
95
96 void DiskUnmounterMac::UnmountOnWorker(const std::string& device_path) {
97   DCHECK(cf_thread_.message_loop() == base::MessageLoop::current());
98
99   session_.reset(DASessionCreate(NULL));
100
101   DASessionScheduleWithRunLoop(
102       session_, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
103
104   disk_.reset(DADiskCreateFromBSDName(
105       kCFAllocatorDefault, session_, device_path.c_str()));
106
107   if (!disk_) {
108     LOG(ERROR) << "Unable to get disk reference.";
109     Error();
110     return;
111   }
112
113   DADiskClaim(disk_,
114               kDADiskClaimOptionDefault,
115               DiskClaimRevoked,
116               this,
117               DiskClaimed,
118               this);
119 }
120
121 void DiskUnmounterMac::Error() {
122   original_thread_->PostTask(FROM_HERE, failure_continuation_);
123 }
124
125 }  // namespace image_writer