// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include #include "chrome/browser/extensions/api/image_writer_private/error_messages.h" #include "chrome/browser/extensions/api/image_writer_private/operation.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/image_burner_client.h" #include "chromeos/disks/disk_mount_manager.h" #include "content/public/browser/browser_thread.h" namespace extensions { namespace image_writer { using chromeos::disks::DiskMountManager; using chromeos::ImageBurnerClient; using content::BrowserThread; namespace { void ClearImageBurner() { if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(&ClearImageBurner)); return; } chromeos::DBusThreadManager::Get()-> GetImageBurnerClient()-> ResetEventHandlers(); } } // namespace void Operation::Write(const base::Closure& continuation) { DCHECK_CURRENTLY_ON(BrowserThread::FILE); SetStage(image_writer_api::STAGE_WRITE); // Note this has to be run on the FILE thread to avoid concurrent access. AddCleanUpFunction(base::Bind(&ClearImageBurner)); BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::Bind(&Operation::UnmountVolumes, this, continuation)); } void Operation::VerifyWrite(const base::Closure& continuation) { DCHECK_CURRENTLY_ON(BrowserThread::FILE); // No verification is available in Chrome OS currently. continuation.Run(); } void Operation::UnmountVolumes(const base::Closure& continuation) { DCHECK_CURRENTLY_ON(BrowserThread::UI); DiskMountManager::GetInstance()->UnmountDeviceRecursively( device_path_.value(), base::Bind(&Operation::UnmountVolumesCallback, this, continuation)); } void Operation::UnmountVolumesCallback(const base::Closure& continuation, bool success) { DCHECK_CURRENTLY_ON(BrowserThread::UI); if (!success) { LOG(ERROR) << "Volume unmounting failed."; Error(error::kUnmountVolumesError); return; } const DiskMountManager::DiskMap& disks = DiskMountManager::GetInstance()->disks(); DiskMountManager::DiskMap::const_iterator iter = disks.find(device_path_.value()); if (iter == disks.end()) { LOG(ERROR) << "Disk not found in disk list after unmounting volumes."; Error(error::kUnmountVolumesError); return; } StartWriteOnUIThread(iter->second->file_path(), continuation); } void Operation::StartWriteOnUIThread(const std::string& target_path, const base::Closure& continuation) { DCHECK_CURRENTLY_ON(BrowserThread::UI); // TODO(haven): Image Burner cannot handle multiple burns. crbug.com/373575 ImageBurnerClient* burner = chromeos::DBusThreadManager::Get()->GetImageBurnerClient(); burner->SetEventHandlers( base::Bind(&Operation::OnBurnFinished, this, continuation), base::Bind(&Operation::OnBurnProgress, this)); burner->BurnImage(image_path_.value(), target_path, base::Bind(&Operation::OnBurnError, this)); } void Operation::OnBurnFinished(const base::Closure& continuation, const std::string& target_path, bool success, const std::string& error) { if (success) { SetProgress(kProgressComplete); BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, continuation); } else { DLOG(ERROR) << "Error encountered while burning: " << error; Error(error::kChromeOSImageBurnerError); } } void Operation::OnBurnProgress(const std::string& target_path, int64_t num_bytes_burnt, int64_t total_size) { int progress = kProgressComplete * num_bytes_burnt / total_size; SetProgress(progress); } void Operation::OnBurnError() { Error(error::kChromeOSImageBurnerError); } } // namespace image_writer } // namespace extensions