Home | History | Annotate | Download | only in image_writer_private
      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