1// Copyright (c) 2012 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/chromeos/file_manager/zip_file_creator.h" 6 7#include "base/bind.h" 8#include "base/callback_helpers.h" 9#include "base/message_loop/message_loop.h" 10#include "base/threading/sequenced_worker_pool.h" 11#include "chrome/common/chrome_utility_messages.h" 12#include "content/public/browser/browser_thread.h" 13#include "content/public/browser/utility_process_host.h" 14 15using content::BrowserThread; 16using content::UtilityProcessHost; 17 18namespace { 19 20// Creates the destination zip file only if it does not already exist. 21base::File OpenFileHandleOnBlockingThreadPool(const base::FilePath& zip_path) { 22 return base::File(zip_path, base::File::FLAG_CREATE | base::File::FLAG_WRITE); 23} 24 25} // namespace 26 27namespace file_manager { 28 29ZipFileCreator::ZipFileCreator( 30 const ResultCallback& callback, 31 const base::FilePath& src_dir, 32 const std::vector<base::FilePath>& src_relative_paths, 33 const base::FilePath& dest_file) 34 : callback_(callback), 35 src_dir_(src_dir), 36 src_relative_paths_(src_relative_paths), 37 dest_file_(dest_file) { 38 DCHECK(!callback_.is_null()); 39} 40 41void ZipFileCreator::Start() { 42 DCHECK_CURRENTLY_ON(BrowserThread::UI); 43 44 base::PostTaskAndReplyWithResult( 45 BrowserThread::GetBlockingPool(), 46 FROM_HERE, 47 base::Bind(&OpenFileHandleOnBlockingThreadPool, dest_file_), 48 base::Bind(&ZipFileCreator::OnOpenFileHandle, this)); 49} 50 51ZipFileCreator::~ZipFileCreator() { 52} 53 54bool ZipFileCreator::OnMessageReceived(const IPC::Message& message) { 55 bool handled = true; 56 IPC_BEGIN_MESSAGE_MAP(ZipFileCreator, message) 57 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_CreateZipFile_Succeeded, 58 OnCreateZipFileSucceeded) 59 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_CreateZipFile_Failed, 60 OnCreateZipFileFailed) 61 IPC_MESSAGE_UNHANDLED(handled = false) 62 IPC_END_MESSAGE_MAP() 63 return handled; 64} 65 66void ZipFileCreator::OnProcessCrashed(int exit_code) { 67 ReportDone(false); 68} 69 70void ZipFileCreator::OnOpenFileHandle(base::File file) { 71 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 72 73 if (!file.IsValid()) { 74 LOG(ERROR) << "Failed to create dest zip file " << dest_file_.value(); 75 ReportDone(false); 76 return; 77 } 78 79 BrowserThread::PostTask( 80 BrowserThread::IO, 81 FROM_HERE, 82 base::Bind( 83 &ZipFileCreator::StartProcessOnIOThread, this, base::Passed(&file))); 84} 85 86void ZipFileCreator::StartProcessOnIOThread(base::File dest_file) { 87 DCHECK_CURRENTLY_ON(BrowserThread::IO); 88 89 base::FileDescriptor dest_fd(dest_file.Pass()); 90 91 UtilityProcessHost* host = UtilityProcessHost::Create( 92 this, 93 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI).get()); 94 host->SetExposedDir(src_dir_); 95 host->Send(new ChromeUtilityMsg_CreateZipFile(src_dir_, src_relative_paths_, 96 dest_fd)); 97} 98 99void ZipFileCreator::OnCreateZipFileSucceeded() { 100 ReportDone(true); 101} 102 103void ZipFileCreator::OnCreateZipFileFailed() { 104 ReportDone(false); 105} 106 107void ZipFileCreator::ReportDone(bool success) { 108 DCHECK_CURRENTLY_ON(BrowserThread::UI); 109 110 // Guard against calling observer multiple times. 111 if (!callback_.is_null()) 112 base::ResetAndReturn(&callback_).Run(success); 113} 114 115} // namespace file_manager 116