Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / utility / image_writer / disk_unmounter_mac.cc
blob8d3155a2955fc3654a0ed821e96724d8eae18f0a
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.
5 #include "chrome/utility/image_writer/disk_unmounter_mac.h"
7 #include <sys/socket.h>
8 #include <IOKit/storage/IOStorageProtocolCharacteristics.h>
10 #include "base/message_loop/message_pump_mac.h"
11 #include "base/posix/eintr_wrapper.h"
12 #include "base/thread_task_runner_handle.h"
13 #include "chrome/utility/image_writer/error_messages.h"
14 #include "chrome/utility/image_writer/image_writer.h"
16 namespace image_writer {
18 DiskUnmounterMac::DiskUnmounterMac() : cf_thread_("ImageWriterDiskArb") {
19 base::Thread::Options options;
20 options.message_pump_factory = base::Bind(&CreateMessagePump);
22 cf_thread_.StartWithOptions(options);
25 DiskUnmounterMac::~DiskUnmounterMac() {
26 if (disk_)
27 DADiskUnclaim(disk_);
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::ThreadTaskRunnerHandle::Get();
36 success_continuation_ = success_continuation;
37 failure_continuation_ = failure_continuation;
39 cf_thread_.message_loop()->PostTask(
40 FROM_HERE,
41 base::Bind(&DiskUnmounterMac::UnmountOnWorker,
42 base::Unretained(this),
43 device_path));
46 // static
47 void DiskUnmounterMac::DiskClaimed(DADiskRef disk,
48 DADissenterRef dissenter,
49 void* context) {
50 DiskUnmounterMac* disk_unmounter = static_cast<DiskUnmounterMac*>(context);
52 if (dissenter) {
53 LOG(ERROR) << "Unable to claim disk.";
54 disk_unmounter->Error();
55 return;
58 DADiskUnmount(disk,
59 kDADiskUnmountOptionForce | kDADiskUnmountOptionWhole,
60 DiskUnmounted,
61 disk_unmounter);
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);
75 // static
76 void DiskUnmounterMac::DiskUnmounted(DADiskRef disk,
77 DADissenterRef dissenter,
78 void* context) {
79 DiskUnmounterMac* disk_unmounter = static_cast<DiskUnmounterMac*>(context);
81 if (dissenter) {
82 LOG(ERROR) << "Unable to unmount disk.";
83 disk_unmounter->Error();
84 return;
87 disk_unmounter->original_thread_->PostTask(
88 FROM_HERE, disk_unmounter->success_continuation_);
91 // static
92 scoped_ptr<base::MessagePump> DiskUnmounterMac::CreateMessagePump() {
93 return scoped_ptr<base::MessagePump>(new base::MessagePumpCFRunLoop);
96 void DiskUnmounterMac::UnmountOnWorker(const std::string& device_path) {
97 DCHECK(cf_thread_.message_loop() == base::MessageLoop::current());
99 session_.reset(DASessionCreate(NULL));
101 DASessionScheduleWithRunLoop(
102 session_, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
104 disk_.reset(DADiskCreateFromBSDName(
105 kCFAllocatorDefault, session_, device_path.c_str()));
107 if (!disk_) {
108 LOG(ERROR) << "Unable to get disk reference.";
109 Error();
110 return;
113 DADiskClaim(disk_,
114 kDADiskClaimOptionDefault,
115 DiskClaimRevoked,
116 this,
117 DiskClaimed,
118 this);
121 void DiskUnmounterMac::Error() {
122 original_thread_->PostTask(FROM_HERE, failure_continuation_);
125 } // namespace image_writer