1 // Copyright 2013 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/browser/extensions/api/image_writer_private/error_messages.h" 6 #include "chrome/browser/extensions/api/image_writer_private/operation.h" 7 #include "chromeos/dbus/dbus_thread_manager.h" 8 #include "chromeos/dbus/image_burner_client.h" 9 #include "chromeos/disks/disk_mount_manager.h" 10 #include "content/public/browser/browser_thread.h" 11 12 namespace extensions { 13 namespace image_writer { 14 15 using chromeos::disks::DiskMountManager; 16 using chromeos::ImageBurnerClient; 17 using content::BrowserThread; 18 19 namespace { 20 21 void ClearImageBurner() { 22 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 23 BrowserThread::PostTask(BrowserThread::UI, 24 FROM_HERE, 25 base::Bind(&ClearImageBurner)); 26 return; 27 } 28 29 chromeos::DBusThreadManager::Get()-> 30 GetImageBurnerClient()-> 31 ResetEventHandlers(); 32 } 33 34 } // namespace 35 36 void Operation::Write(const base::Closure& continuation) { 37 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 38 SetStage(image_writer_api::STAGE_WRITE); 39 40 // Note this has to be run on the FILE thread to avoid concurrent access. 41 AddCleanUpFunction(base::Bind(&ClearImageBurner)); 42 43 BrowserThread::PostTask( 44 BrowserThread::UI, 45 FROM_HERE, 46 base::Bind(&Operation::UnmountVolumes, this, continuation)); 47 } 48 49 void Operation::VerifyWrite(const base::Closure& continuation) { 50 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 51 52 // No verification is available in Chrome OS currently. 53 continuation.Run(); 54 } 55 56 void Operation::UnmountVolumes(const base::Closure& continuation) { 57 DCHECK_CURRENTLY_ON(BrowserThread::UI); 58 DiskMountManager::GetInstance()->UnmountDeviceRecursively( 59 device_path_.value(), 60 base::Bind(&Operation::UnmountVolumesCallback, this, continuation)); 61 } 62 63 void Operation::UnmountVolumesCallback(const base::Closure& continuation, 64 bool success) { 65 DCHECK_CURRENTLY_ON(BrowserThread::UI); 66 67 if (!success) { 68 LOG(ERROR) << "Volume unmounting failed."; 69 Error(error::kUnmountVolumesError); 70 return; 71 } 72 73 const DiskMountManager::DiskMap& disks = 74 DiskMountManager::GetInstance()->disks(); 75 DiskMountManager::DiskMap::const_iterator iter = 76 disks.find(device_path_.value()); 77 78 if (iter == disks.end()) { 79 LOG(ERROR) << "Disk not found in disk list after unmounting volumes."; 80 Error(error::kUnmountVolumesError); 81 return; 82 } 83 84 StartWriteOnUIThread(iter->second->file_path(), continuation); 85 } 86 87 void Operation::StartWriteOnUIThread(const std::string& target_path, 88 const base::Closure& continuation) { 89 DCHECK_CURRENTLY_ON(BrowserThread::UI); 90 91 // TODO(haven): Image Burner cannot handle multiple burns. crbug.com/373575 92 ImageBurnerClient* burner = 93 chromeos::DBusThreadManager::Get()->GetImageBurnerClient(); 94 95 burner->SetEventHandlers( 96 base::Bind(&Operation::OnBurnFinished, this, continuation), 97 base::Bind(&Operation::OnBurnProgress, this)); 98 99 burner->BurnImage(image_path_.value(), 100 target_path, 101 base::Bind(&Operation::OnBurnError, this)); 102 } 103 104 void Operation::OnBurnFinished(const base::Closure& continuation, 105 const std::string& target_path, 106 bool success, 107 const std::string& error) { 108 if (success) { 109 SetProgress(kProgressComplete); 110 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, continuation); 111 } else { 112 DLOG(ERROR) << "Error encountered while burning: " << error; 113 Error(error::kChromeOSImageBurnerError); 114 } 115 } 116 117 void Operation::OnBurnProgress(const std::string& target_path, 118 int64 num_bytes_burnt, 119 int64 total_size) { 120 int progress = kProgressComplete * num_bytes_burnt / total_size; 121 SetProgress(progress); 122 } 123 124 void Operation::OnBurnError() { 125 Error(error::kChromeOSImageBurnerError); 126 } 127 128 } // namespace image_writer 129 } // namespace extensions 130