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/extensions/file_manager/zip_file_creator.h" 6 7#include "base/bind.h" 8#include "base/command_line.h" 9#include "base/files/file_util_proxy.h" 10#include "base/memory/scoped_handle.h" 11#include "base/message_loop/message_loop.h" 12#include "base/path_service.h" 13#include "base/threading/sequenced_worker_pool.h" 14#include "chrome/common/chrome_paths.h" 15#include "chrome/common/chrome_switches.h" 16#include "chrome/common/chrome_utility_messages.h" 17#include "chrome/common/extensions/extension_file_util.h" 18#include "chrome/common/extensions/extension_manifest_constants.h" 19#include "content/public/browser/browser_thread.h" 20#include "content/public/browser/utility_process_host.h" 21#include "grit/generated_resources.h" 22 23using content::BrowserThread; 24using content::UtilityProcessHost; 25 26namespace file_manager { 27 28ZipFileCreator::ZipFileCreator( 29 Observer* observer, 30 const base::FilePath& src_dir, 31 const std::vector<base::FilePath>& src_relative_paths, 32 const base::FilePath& dest_file) 33 : thread_identifier_(BrowserThread::ID_COUNT), 34 observer_(observer), 35 src_dir_(src_dir), 36 src_relative_paths_(src_relative_paths), 37 dest_file_(dest_file), 38 got_response_(false) { 39} 40 41void ZipFileCreator::Start() { 42 CHECK(BrowserThread::GetCurrentThreadIdentifier(&thread_identifier_)); 43 BrowserThread::GetBlockingPool()->PostTask( 44 FROM_HERE, 45 base::Bind(&ZipFileCreator::OpenFileHandleOnBlockingThreadPool, this)); 46} 47 48ZipFileCreator::~ZipFileCreator() { 49} 50 51bool ZipFileCreator::OnMessageReceived(const IPC::Message& message) { 52 bool handled = true; 53 IPC_BEGIN_MESSAGE_MAP(ZipFileCreator, message) 54 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_CreateZipFile_Succeeded, 55 OnCreateZipFileSucceeded) 56 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_CreateZipFile_Failed, 57 OnCreateZipFileFailed) 58 IPC_MESSAGE_UNHANDLED(handled = false) 59 IPC_END_MESSAGE_MAP() 60 return handled; 61} 62 63void ZipFileCreator::OnProcessCrashed(int exit_code) { 64 // Don't report crashes if they happen after we got a response. 65 if (got_response_) 66 return; 67 68 // Utility process crashed while trying to create the zip file. 69 ReportDone(false); 70} 71 72void ZipFileCreator::OpenFileHandleOnBlockingThreadPool() { 73 // Create the destination zip file only if it does not already exist. 74 int flags = base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE; 75 base::PlatformFileError error_code = base::PLATFORM_FILE_OK; 76 base::PlatformFile dest_file = 77 base::CreatePlatformFile(dest_file_, flags, NULL, &error_code); 78 79 if (error_code != base::PLATFORM_FILE_OK) { 80 LOG(ERROR) << "Failed to create dest zip file " << dest_file_.value(); 81 82 BrowserThread::GetMessageLoopProxyForThread(thread_identifier_)->PostTask( 83 FROM_HERE, 84 base::Bind(&ZipFileCreator::ReportDone, this, false)); 85 return; 86 } 87 88 BrowserThread::PostTask( 89 BrowserThread::IO, FROM_HERE, 90 base::Bind(&ZipFileCreator::StartProcessOnIOThread, this, dest_file)); 91} 92 93void ZipFileCreator::StartProcessOnIOThread(base::PlatformFile dest_file) { 94 base::FileDescriptor dest_fd; 95 dest_fd.fd = dest_file; 96 dest_fd.auto_close = true; 97 98 UtilityProcessHost* host = UtilityProcessHost::Create( 99 this, 100 BrowserThread::GetMessageLoopProxyForThread(thread_identifier_).get()); 101 host->Send(new ChromeUtilityMsg_CreateZipFile(src_dir_, src_relative_paths_, 102 dest_fd)); 103} 104 105void ZipFileCreator::OnCreateZipFileSucceeded() { 106 ReportDone(true); 107} 108 109void ZipFileCreator::OnCreateZipFileFailed() { 110 ReportDone(false); 111} 112 113void ZipFileCreator::ReportDone(bool success) { 114 // Skip check for unittests. 115 if (thread_identifier_ != BrowserThread::ID_COUNT) 116 DCHECK(BrowserThread::CurrentlyOn(thread_identifier_)); 117 118 // Guard against calling observer multiple times. 119 if (got_response_) 120 return; 121 122 got_response_ = true; 123 observer_->OnZipDone(success); 124} 125 126} // namespace file_manager 127