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